aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2009-09-04 12:08:11 +0000
committerDan Gohman <gohman@apple.com>2009-09-04 12:08:11 +0000
commit859fff476dfe8d83abdf4621b1d20062c0daa85c (patch)
tree15f6b66f5538046096a0f13f5ff878227987faef /include
parent70327dabb4cbe7a95b65ea787716170508ac3068 (diff)
downloadexternal_llvm-859fff476dfe8d83abdf4621b1d20062c0daa85c.zip
external_llvm-859fff476dfe8d83abdf4621b1d20062c0daa85c.tar.gz
external_llvm-859fff476dfe8d83abdf4621b1d20062c0daa85c.tar.bz2
Include optional subclass flags, such as inbounds, nsw, etc., in the
Constant uniquing tables. This allows distinct ConstantExpr objects with the same operation and different flags. Even though a ConstantExpr "a + b" is either always overflowing or never overflowing (due to being a ConstantExpr), it's still necessary to be able to represent it both with and without overflow flags at the same time within the IR, because the safety of the flag may depend on the context of the use. If the constant really does overflow, it wouldn't ever be safe to use with the flag set, however the use may be in code that is never actually executed. This also makes it possible to merge all the flags tests into a single test. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@80998 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include')
-rw-r--r--include/llvm/Constants.h9
-rw-r--r--include/llvm/InstrTypes.h27
-rw-r--r--include/llvm/Instructions.h12
-rw-r--r--include/llvm/Operator.h66
-rw-r--r--include/llvm/Value.h13
5 files changed, 93 insertions, 34 deletions
diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h
index da6fe96..e79ca54 100644
--- a/include/llvm/Constants.h
+++ b/include/llvm/Constants.h
@@ -571,13 +571,17 @@ protected:
// These private methods are used by the type resolution code to create
// ConstantExprs in intermediate forms.
static Constant *getTy(const Type *Ty, unsigned Opcode,
- Constant *C1, Constant *C2);
+ Constant *C1, Constant *C2,
+ unsigned Flags = 0);
static Constant *getCompareTy(unsigned short pred, Constant *C1,
Constant *C2);
static Constant *getSelectTy(const Type *Ty,
Constant *C1, Constant *C2, Constant *C3);
static Constant *getGetElementPtrTy(const Type *Ty, Constant *C,
Value* const *Idxs, unsigned NumIdxs);
+ static Constant *getInBoundsGetElementPtrTy(const Type *Ty, Constant *C,
+ Value* const *Idxs,
+ unsigned NumIdxs);
static Constant *getExtractElementTy(const Type *Ty, Constant *Val,
Constant *Idx);
static Constant *getInsertElementTy(const Type *Ty, Constant *Val,
@@ -718,7 +722,8 @@ public:
/// get - Return a binary or shift operator constant expression,
/// folding if possible.
///
- static Constant *get(unsigned Opcode, Constant *C1, Constant *C2);
+ static Constant *get(unsigned Opcode, Constant *C1, Constant *C2,
+ unsigned Flags = 0);
/// @brief Return an ICmp or FCmp comparison operator constant expression.
static Constant *getCompare(unsigned short pred, Constant *C1, Constant *C2);
diff --git a/include/llvm/InstrTypes.h b/include/llvm/InstrTypes.h
index 35d7534..032a1e7 100644
--- a/include/llvm/InstrTypes.h
+++ b/include/llvm/InstrTypes.h
@@ -200,19 +200,19 @@ public:
static BinaryOperator *CreateNSWAdd(Value *V1, Value *V2,
const Twine &Name = "") {
BinaryOperator *BO = CreateAdd(V1, V2, Name);
- cast<AddOperator>(BO)->setHasNoSignedWrap(true);
+ BO->setHasNoSignedWrap(true);
return BO;
}
static BinaryOperator *CreateNSWAdd(Value *V1, Value *V2,
const Twine &Name, BasicBlock *BB) {
BinaryOperator *BO = CreateAdd(V1, V2, Name, BB);
- cast<AddOperator>(BO)->setHasNoSignedWrap(true);
+ BO->setHasNoSignedWrap(true);
return BO;
}
static BinaryOperator *CreateNSWAdd(Value *V1, Value *V2,
const Twine &Name, Instruction *I) {
BinaryOperator *BO = CreateAdd(V1, V2, Name, I);
- cast<AddOperator>(BO)->setHasNoSignedWrap(true);
+ BO->setHasNoSignedWrap(true);
return BO;
}
@@ -221,19 +221,19 @@ public:
static BinaryOperator *CreateExactSDiv(Value *V1, Value *V2,
const Twine &Name = "") {
BinaryOperator *BO = CreateSDiv(V1, V2, Name);
- cast<SDivOperator>(BO)->setIsExact(true);
+ BO->setIsExact(true);
return BO;
}
static BinaryOperator *CreateExactSDiv(Value *V1, Value *V2,
const Twine &Name, BasicBlock *BB) {
BinaryOperator *BO = CreateSDiv(V1, V2, Name, BB);
- cast<SDivOperator>(BO)->setIsExact(true);
+ BO->setIsExact(true);
return BO;
}
static BinaryOperator *CreateExactSDiv(Value *V1, Value *V2,
const Twine &Name, Instruction *I) {
BinaryOperator *BO = CreateSDiv(V1, V2, Name, I);
- cast<SDivOperator>(BO)->setIsExact(true);
+ BO->setIsExact(true);
return BO;
}
@@ -287,6 +287,21 @@ public:
///
bool swapOperands();
+ /// setHasNoUnsignedWrap - Set or clear the nsw flag on this instruction,
+ /// which must be an operator which supports this flag. See LangRef.html
+ /// for the meaning of this flag.
+ void setHasNoUnsignedWrap(bool);
+
+ /// setHasNoSignedWrap - Set or clear the nsw flag on this instruction,
+ /// which must be an operator which supports this flag. See LangRef.html
+ /// for the meaning of this flag.
+ void setHasNoSignedWrap(bool);
+
+ /// setIsExact - Set or clear the exact flag on this instruction,
+ /// which must be an operator which supports this flag. See LangRef.html
+ /// for the meaning of this flag.
+ void setIsExact(bool);
+
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const BinaryOperator *) { return true; }
static inline bool classof(const Instruction *I) {
diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h
index 71f4738..57cff17 100644
--- a/include/llvm/Instructions.h
+++ b/include/llvm/Instructions.h
@@ -496,7 +496,7 @@ public:
Instruction *InsertBefore = 0) {
GetElementPtrInst *GEP = Create(Ptr, IdxBegin, IdxEnd,
NameStr, InsertBefore);
- cast<GEPOperator>(GEP)->setIsInBounds(true);
+ GEP->setIsInBounds(true);
return GEP;
}
template<typename InputIterator>
@@ -507,21 +507,21 @@ public:
BasicBlock *InsertAtEnd) {
GetElementPtrInst *GEP = Create(Ptr, IdxBegin, IdxEnd,
NameStr, InsertAtEnd);
- cast<GEPOperator>(GEP)->setIsInBounds(true);
+ GEP->setIsInBounds(true);
return GEP;
}
static GetElementPtrInst *CreateInBounds(Value *Ptr, Value *Idx,
const Twine &NameStr = "",
Instruction *InsertBefore = 0) {
GetElementPtrInst *GEP = Create(Ptr, Idx, NameStr, InsertBefore);
- cast<GEPOperator>(GEP)->setIsInBounds(true);
+ GEP->setIsInBounds(true);
return GEP;
}
static GetElementPtrInst *CreateInBounds(Value *Ptr, Value *Idx,
const Twine &NameStr,
BasicBlock *InsertAtEnd) {
GetElementPtrInst *GEP = Create(Ptr, Idx, NameStr, InsertAtEnd);
- cast<GEPOperator>(GEP)->setIsInBounds(true);
+ GEP->setIsInBounds(true);
return GEP;
}
@@ -602,6 +602,10 @@ public:
/// a constant offset between them.
bool hasAllConstantIndices() const;
+ /// setIsInBounds - Set or clear the inbounds flag on this GEP instruction.
+ /// See LangRef.html for the meaning of inbounds on a getelementptr.
+ void setIsInBounds(bool);
+
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const GetElementPtrInst *) { return true; }
static inline bool classof(const Instruction *I) {
diff --git a/include/llvm/Operator.h b/include/llvm/Operator.h
index 48ac09d..06eb243 100644
--- a/include/llvm/Operator.h
+++ b/include/llvm/Operator.h
@@ -21,6 +21,8 @@
namespace llvm {
class GetElementPtrInst;
+class BinaryOperator;
+class ConstantExpr;
/// Operator - This is a utility class that provides an abstraction for the
/// common functionality between Instructions and ConstantExprs.
@@ -67,24 +69,37 @@ public:
/// despite that operator having the potential for overflow.
///
class OverflowingBinaryOperator : public Operator {
+public:
+ enum {
+ NoUnsignedWrap = (1 << 0),
+ NoSignedWrap = (1 << 1)
+ };
+
+private:
~OverflowingBinaryOperator(); // do not implement
+
+ friend class BinaryOperator;
+ friend class ConstantExpr;
+ void setHasNoUnsignedWrap(bool B) {
+ SubclassOptionalData =
+ (SubclassOptionalData & ~NoUnsignedWrap) | (B * NoUnsignedWrap);
+ }
+ void setHasNoSignedWrap(bool B) {
+ SubclassOptionalData =
+ (SubclassOptionalData & ~NoSignedWrap) | (B * NoSignedWrap);
+ }
+
public:
/// hasNoUnsignedWrap - Test whether this operation is known to never
/// undergo unsigned overflow, aka the nuw property.
bool hasNoUnsignedWrap() const {
- return SubclassOptionalData & (1 << 0);
- }
- void setHasNoUnsignedWrap(bool B) {
- SubclassOptionalData = (SubclassOptionalData & ~(1 << 0)) | (B << 0);
+ return SubclassOptionalData & NoUnsignedWrap;
}
/// hasNoSignedWrap - Test whether this operation is known to never
/// undergo signed overflow, aka the nsw property.
bool hasNoSignedWrap() const {
- return SubclassOptionalData & (1 << 1);
- }
- void setHasNoSignedWrap(bool B) {
- SubclassOptionalData = (SubclassOptionalData & ~(1 << 1)) | (B << 1);
+ return SubclassOptionalData & NoSignedWrap;
}
static inline bool classof(const OverflowingBinaryOperator *) { return true; }
@@ -161,15 +176,25 @@ public:
/// SDivOperator - An Operator with opcode Instruction::SDiv.
///
class SDivOperator : public Operator {
+public:
+ enum {
+ IsExact = (1 << 0)
+ };
+
+private:
~SDivOperator(); // do not implement
+
+ friend class BinaryOperator;
+ friend class ConstantExpr;
+ void setIsExact(bool B) {
+ SubclassOptionalData = (SubclassOptionalData & ~IsExact) | (B * IsExact);
+ }
+
public:
/// isExact - Test whether this division is known to be exact, with
/// zero remainder.
bool isExact() const {
- return SubclassOptionalData & (1 << 0);
- }
- void setIsExact(bool B) {
- SubclassOptionalData = (SubclassOptionalData & ~(1 << 0)) | (B << 0);
+ return SubclassOptionalData & IsExact;
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
@@ -187,15 +212,24 @@ public:
};
class GEPOperator : public Operator {
+ enum {
+ IsInBounds = (1 << 0)
+ };
+
~GEPOperator(); // do not implement
+
+ friend class GetElementPtrInst;
+ friend class ConstantExpr;
+ void setIsInBounds(bool B) {
+ SubclassOptionalData =
+ (SubclassOptionalData & ~IsInBounds) | (B * IsInBounds);
+ }
+
public:
/// isInBounds - Test whether this is an inbounds GEP, as defined
/// by LangRef.html.
bool isInBounds() const {
- return SubclassOptionalData & (1 << 0);
- }
- void setIsInBounds(bool B) {
- SubclassOptionalData = (SubclassOptionalData & ~(1 << 0)) | (B << 0);
+ return SubclassOptionalData & IsInBounds;
}
inline op_iterator idx_begin() { return op_begin()+1; }
diff --git a/include/llvm/Value.h b/include/llvm/Value.h
index fdc3aeb..415b8fb 100644
--- a/include/llvm/Value.h
+++ b/include/llvm/Value.h
@@ -146,12 +146,6 @@ public:
// Only use when in type resolution situations!
void uncheckedReplaceAllUsesWith(Value *V);
- /// clearOptionalData - Clear any optional optimization data from this Value.
- /// Transformation passes must call this method whenever changing the IR
- /// in a way that would affect the values produced by this Value, unless
- /// it takes special care to ensure correctness in some other way.
- void clearOptionalData() { SubclassOptionalData = 0; }
-
//----------------------------------------------------------------------
// Methods for handling the chain of uses of this Value.
//
@@ -240,6 +234,13 @@ public:
return SubclassID;
}
+ /// getRawSubclassOptionalData - Return the raw optional flags value
+ /// contained in this value. This should only be used when testing two
+ /// Values for equivalence.
+ unsigned getRawSubclassOptionalData() const {
+ return SubclassOptionalData;
+ }
+
/// hasSameSubclassOptionalData - Test whether the optional flags contained
/// in this value are equal to the optional flags in the given value.
bool hasSameSubclassOptionalData(const Value *V) const {