mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-17 04:24:00 +00:00
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
This commit is contained in:
@ -571,13 +571,17 @@ protected:
|
|||||||
// These private methods are used by the type resolution code to create
|
// These private methods are used by the type resolution code to create
|
||||||
// ConstantExprs in intermediate forms.
|
// ConstantExprs in intermediate forms.
|
||||||
static Constant *getTy(const Type *Ty, unsigned Opcode,
|
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,
|
static Constant *getCompareTy(unsigned short pred, Constant *C1,
|
||||||
Constant *C2);
|
Constant *C2);
|
||||||
static Constant *getSelectTy(const Type *Ty,
|
static Constant *getSelectTy(const Type *Ty,
|
||||||
Constant *C1, Constant *C2, Constant *C3);
|
Constant *C1, Constant *C2, Constant *C3);
|
||||||
static Constant *getGetElementPtrTy(const Type *Ty, Constant *C,
|
static Constant *getGetElementPtrTy(const Type *Ty, Constant *C,
|
||||||
Value* const *Idxs, unsigned NumIdxs);
|
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,
|
static Constant *getExtractElementTy(const Type *Ty, Constant *Val,
|
||||||
Constant *Idx);
|
Constant *Idx);
|
||||||
static Constant *getInsertElementTy(const Type *Ty, Constant *Val,
|
static Constant *getInsertElementTy(const Type *Ty, Constant *Val,
|
||||||
@ -718,7 +722,8 @@ public:
|
|||||||
/// get - Return a binary or shift operator constant expression,
|
/// get - Return a binary or shift operator constant expression,
|
||||||
/// folding if possible.
|
/// 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.
|
/// @brief Return an ICmp or FCmp comparison operator constant expression.
|
||||||
static Constant *getCompare(unsigned short pred, Constant *C1, Constant *C2);
|
static Constant *getCompare(unsigned short pred, Constant *C1, Constant *C2);
|
||||||
|
@ -200,19 +200,19 @@ public:
|
|||||||
static BinaryOperator *CreateNSWAdd(Value *V1, Value *V2,
|
static BinaryOperator *CreateNSWAdd(Value *V1, Value *V2,
|
||||||
const Twine &Name = "") {
|
const Twine &Name = "") {
|
||||||
BinaryOperator *BO = CreateAdd(V1, V2, Name);
|
BinaryOperator *BO = CreateAdd(V1, V2, Name);
|
||||||
cast<AddOperator>(BO)->setHasNoSignedWrap(true);
|
BO->setHasNoSignedWrap(true);
|
||||||
return BO;
|
return BO;
|
||||||
}
|
}
|
||||||
static BinaryOperator *CreateNSWAdd(Value *V1, Value *V2,
|
static BinaryOperator *CreateNSWAdd(Value *V1, Value *V2,
|
||||||
const Twine &Name, BasicBlock *BB) {
|
const Twine &Name, BasicBlock *BB) {
|
||||||
BinaryOperator *BO = CreateAdd(V1, V2, Name, BB);
|
BinaryOperator *BO = CreateAdd(V1, V2, Name, BB);
|
||||||
cast<AddOperator>(BO)->setHasNoSignedWrap(true);
|
BO->setHasNoSignedWrap(true);
|
||||||
return BO;
|
return BO;
|
||||||
}
|
}
|
||||||
static BinaryOperator *CreateNSWAdd(Value *V1, Value *V2,
|
static BinaryOperator *CreateNSWAdd(Value *V1, Value *V2,
|
||||||
const Twine &Name, Instruction *I) {
|
const Twine &Name, Instruction *I) {
|
||||||
BinaryOperator *BO = CreateAdd(V1, V2, Name, I);
|
BinaryOperator *BO = CreateAdd(V1, V2, Name, I);
|
||||||
cast<AddOperator>(BO)->setHasNoSignedWrap(true);
|
BO->setHasNoSignedWrap(true);
|
||||||
return BO;
|
return BO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,19 +221,19 @@ public:
|
|||||||
static BinaryOperator *CreateExactSDiv(Value *V1, Value *V2,
|
static BinaryOperator *CreateExactSDiv(Value *V1, Value *V2,
|
||||||
const Twine &Name = "") {
|
const Twine &Name = "") {
|
||||||
BinaryOperator *BO = CreateSDiv(V1, V2, Name);
|
BinaryOperator *BO = CreateSDiv(V1, V2, Name);
|
||||||
cast<SDivOperator>(BO)->setIsExact(true);
|
BO->setIsExact(true);
|
||||||
return BO;
|
return BO;
|
||||||
}
|
}
|
||||||
static BinaryOperator *CreateExactSDiv(Value *V1, Value *V2,
|
static BinaryOperator *CreateExactSDiv(Value *V1, Value *V2,
|
||||||
const Twine &Name, BasicBlock *BB) {
|
const Twine &Name, BasicBlock *BB) {
|
||||||
BinaryOperator *BO = CreateSDiv(V1, V2, Name, BB);
|
BinaryOperator *BO = CreateSDiv(V1, V2, Name, BB);
|
||||||
cast<SDivOperator>(BO)->setIsExact(true);
|
BO->setIsExact(true);
|
||||||
return BO;
|
return BO;
|
||||||
}
|
}
|
||||||
static BinaryOperator *CreateExactSDiv(Value *V1, Value *V2,
|
static BinaryOperator *CreateExactSDiv(Value *V1, Value *V2,
|
||||||
const Twine &Name, Instruction *I) {
|
const Twine &Name, Instruction *I) {
|
||||||
BinaryOperator *BO = CreateSDiv(V1, V2, Name, I);
|
BinaryOperator *BO = CreateSDiv(V1, V2, Name, I);
|
||||||
cast<SDivOperator>(BO)->setIsExact(true);
|
BO->setIsExact(true);
|
||||||
return BO;
|
return BO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,6 +287,21 @@ public:
|
|||||||
///
|
///
|
||||||
bool swapOperands();
|
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:
|
// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||||
static inline bool classof(const BinaryOperator *) { return true; }
|
static inline bool classof(const BinaryOperator *) { return true; }
|
||||||
static inline bool classof(const Instruction *I) {
|
static inline bool classof(const Instruction *I) {
|
||||||
|
@ -496,7 +496,7 @@ public:
|
|||||||
Instruction *InsertBefore = 0) {
|
Instruction *InsertBefore = 0) {
|
||||||
GetElementPtrInst *GEP = Create(Ptr, IdxBegin, IdxEnd,
|
GetElementPtrInst *GEP = Create(Ptr, IdxBegin, IdxEnd,
|
||||||
NameStr, InsertBefore);
|
NameStr, InsertBefore);
|
||||||
cast<GEPOperator>(GEP)->setIsInBounds(true);
|
GEP->setIsInBounds(true);
|
||||||
return GEP;
|
return GEP;
|
||||||
}
|
}
|
||||||
template<typename InputIterator>
|
template<typename InputIterator>
|
||||||
@ -507,21 +507,21 @@ public:
|
|||||||
BasicBlock *InsertAtEnd) {
|
BasicBlock *InsertAtEnd) {
|
||||||
GetElementPtrInst *GEP = Create(Ptr, IdxBegin, IdxEnd,
|
GetElementPtrInst *GEP = Create(Ptr, IdxBegin, IdxEnd,
|
||||||
NameStr, InsertAtEnd);
|
NameStr, InsertAtEnd);
|
||||||
cast<GEPOperator>(GEP)->setIsInBounds(true);
|
GEP->setIsInBounds(true);
|
||||||
return GEP;
|
return GEP;
|
||||||
}
|
}
|
||||||
static GetElementPtrInst *CreateInBounds(Value *Ptr, Value *Idx,
|
static GetElementPtrInst *CreateInBounds(Value *Ptr, Value *Idx,
|
||||||
const Twine &NameStr = "",
|
const Twine &NameStr = "",
|
||||||
Instruction *InsertBefore = 0) {
|
Instruction *InsertBefore = 0) {
|
||||||
GetElementPtrInst *GEP = Create(Ptr, Idx, NameStr, InsertBefore);
|
GetElementPtrInst *GEP = Create(Ptr, Idx, NameStr, InsertBefore);
|
||||||
cast<GEPOperator>(GEP)->setIsInBounds(true);
|
GEP->setIsInBounds(true);
|
||||||
return GEP;
|
return GEP;
|
||||||
}
|
}
|
||||||
static GetElementPtrInst *CreateInBounds(Value *Ptr, Value *Idx,
|
static GetElementPtrInst *CreateInBounds(Value *Ptr, Value *Idx,
|
||||||
const Twine &NameStr,
|
const Twine &NameStr,
|
||||||
BasicBlock *InsertAtEnd) {
|
BasicBlock *InsertAtEnd) {
|
||||||
GetElementPtrInst *GEP = Create(Ptr, Idx, NameStr, InsertAtEnd);
|
GetElementPtrInst *GEP = Create(Ptr, Idx, NameStr, InsertAtEnd);
|
||||||
cast<GEPOperator>(GEP)->setIsInBounds(true);
|
GEP->setIsInBounds(true);
|
||||||
return GEP;
|
return GEP;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -602,6 +602,10 @@ public:
|
|||||||
/// a constant offset between them.
|
/// a constant offset between them.
|
||||||
bool hasAllConstantIndices() const;
|
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:
|
// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||||
static inline bool classof(const GetElementPtrInst *) { return true; }
|
static inline bool classof(const GetElementPtrInst *) { return true; }
|
||||||
static inline bool classof(const Instruction *I) {
|
static inline bool classof(const Instruction *I) {
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
class GetElementPtrInst;
|
class GetElementPtrInst;
|
||||||
|
class BinaryOperator;
|
||||||
|
class ConstantExpr;
|
||||||
|
|
||||||
/// Operator - This is a utility class that provides an abstraction for the
|
/// Operator - This is a utility class that provides an abstraction for the
|
||||||
/// common functionality between Instructions and ConstantExprs.
|
/// common functionality between Instructions and ConstantExprs.
|
||||||
@ -67,24 +69,37 @@ public:
|
|||||||
/// despite that operator having the potential for overflow.
|
/// despite that operator having the potential for overflow.
|
||||||
///
|
///
|
||||||
class OverflowingBinaryOperator : public Operator {
|
class OverflowingBinaryOperator : public Operator {
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
NoUnsignedWrap = (1 << 0),
|
||||||
|
NoSignedWrap = (1 << 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
~OverflowingBinaryOperator(); // do not implement
|
~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:
|
public:
|
||||||
/// hasNoUnsignedWrap - Test whether this operation is known to never
|
/// hasNoUnsignedWrap - Test whether this operation is known to never
|
||||||
/// undergo unsigned overflow, aka the nuw property.
|
/// undergo unsigned overflow, aka the nuw property.
|
||||||
bool hasNoUnsignedWrap() const {
|
bool hasNoUnsignedWrap() const {
|
||||||
return SubclassOptionalData & (1 << 0);
|
return SubclassOptionalData & NoUnsignedWrap;
|
||||||
}
|
|
||||||
void setHasNoUnsignedWrap(bool B) {
|
|
||||||
SubclassOptionalData = (SubclassOptionalData & ~(1 << 0)) | (B << 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// hasNoSignedWrap - Test whether this operation is known to never
|
/// hasNoSignedWrap - Test whether this operation is known to never
|
||||||
/// undergo signed overflow, aka the nsw property.
|
/// undergo signed overflow, aka the nsw property.
|
||||||
bool hasNoSignedWrap() const {
|
bool hasNoSignedWrap() const {
|
||||||
return SubclassOptionalData & (1 << 1);
|
return SubclassOptionalData & NoSignedWrap;
|
||||||
}
|
|
||||||
void setHasNoSignedWrap(bool B) {
|
|
||||||
SubclassOptionalData = (SubclassOptionalData & ~(1 << 1)) | (B << 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool classof(const OverflowingBinaryOperator *) { return true; }
|
static inline bool classof(const OverflowingBinaryOperator *) { return true; }
|
||||||
@ -161,15 +176,25 @@ public:
|
|||||||
/// SDivOperator - An Operator with opcode Instruction::SDiv.
|
/// SDivOperator - An Operator with opcode Instruction::SDiv.
|
||||||
///
|
///
|
||||||
class SDivOperator : public Operator {
|
class SDivOperator : public Operator {
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
IsExact = (1 << 0)
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
~SDivOperator(); // do not implement
|
~SDivOperator(); // do not implement
|
||||||
|
|
||||||
|
friend class BinaryOperator;
|
||||||
|
friend class ConstantExpr;
|
||||||
|
void setIsExact(bool B) {
|
||||||
|
SubclassOptionalData = (SubclassOptionalData & ~IsExact) | (B * IsExact);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// isExact - Test whether this division is known to be exact, with
|
/// isExact - Test whether this division is known to be exact, with
|
||||||
/// zero remainder.
|
/// zero remainder.
|
||||||
bool isExact() const {
|
bool isExact() const {
|
||||||
return SubclassOptionalData & (1 << 0);
|
return SubclassOptionalData & IsExact;
|
||||||
}
|
|
||||||
void setIsExact(bool B) {
|
|
||||||
SubclassOptionalData = (SubclassOptionalData & ~(1 << 0)) | (B << 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Methods for support type inquiry through isa, cast, and dyn_cast:
|
// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||||
@ -187,15 +212,24 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
class GEPOperator : public Operator {
|
class GEPOperator : public Operator {
|
||||||
|
enum {
|
||||||
|
IsInBounds = (1 << 0)
|
||||||
|
};
|
||||||
|
|
||||||
~GEPOperator(); // do not implement
|
~GEPOperator(); // do not implement
|
||||||
|
|
||||||
|
friend class GetElementPtrInst;
|
||||||
|
friend class ConstantExpr;
|
||||||
|
void setIsInBounds(bool B) {
|
||||||
|
SubclassOptionalData =
|
||||||
|
(SubclassOptionalData & ~IsInBounds) | (B * IsInBounds);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// isInBounds - Test whether this is an inbounds GEP, as defined
|
/// isInBounds - Test whether this is an inbounds GEP, as defined
|
||||||
/// by LangRef.html.
|
/// by LangRef.html.
|
||||||
bool isInBounds() const {
|
bool isInBounds() const {
|
||||||
return SubclassOptionalData & (1 << 0);
|
return SubclassOptionalData & IsInBounds;
|
||||||
}
|
|
||||||
void setIsInBounds(bool B) {
|
|
||||||
SubclassOptionalData = (SubclassOptionalData & ~(1 << 0)) | (B << 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline op_iterator idx_begin() { return op_begin()+1; }
|
inline op_iterator idx_begin() { return op_begin()+1; }
|
||||||
|
@ -146,12 +146,6 @@ public:
|
|||||||
// Only use when in type resolution situations!
|
// Only use when in type resolution situations!
|
||||||
void uncheckedReplaceAllUsesWith(Value *V);
|
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.
|
// Methods for handling the chain of uses of this Value.
|
||||||
//
|
//
|
||||||
@ -240,6 +234,13 @@ public:
|
|||||||
return SubclassID;
|
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
|
/// hasSameSubclassOptionalData - Test whether the optional flags contained
|
||||||
/// in this value are equal to the optional flags in the given value.
|
/// in this value are equal to the optional flags in the given value.
|
||||||
bool hasSameSubclassOptionalData(const Value *V) const {
|
bool hasSameSubclassOptionalData(const Value *V) const {
|
||||||
|
@ -2095,13 +2095,11 @@ bool LLParser::ParseValID(ValID &ID) {
|
|||||||
if (!Val0->getType()->isIntOrIntVector() &&
|
if (!Val0->getType()->isIntOrIntVector() &&
|
||||||
!Val0->getType()->isFPOrFPVector())
|
!Val0->getType()->isFPOrFPVector())
|
||||||
return Error(ID.Loc,"constexpr requires integer, fp, or vector operands");
|
return Error(ID.Loc,"constexpr requires integer, fp, or vector operands");
|
||||||
Constant *C = ConstantExpr::get(Opc, Val0, Val1);
|
unsigned Flags = 0;
|
||||||
if (NUW)
|
if (NUW) Flags |= OverflowingBinaryOperator::NoUnsignedWrap;
|
||||||
cast<OverflowingBinaryOperator>(C)->setHasNoUnsignedWrap(true);
|
if (NSW) Flags |= OverflowingBinaryOperator::NoSignedWrap;
|
||||||
if (NSW)
|
if (Exact) Flags |= SDivOperator::IsExact;
|
||||||
cast<OverflowingBinaryOperator>(C)->setHasNoSignedWrap(true);
|
Constant *C = ConstantExpr::get(Opc, Val0, Val1, Flags);
|
||||||
if (Exact)
|
|
||||||
cast<SDivOperator>(C)->setIsExact(true);
|
|
||||||
ID.ConstantVal = C;
|
ID.ConstantVal = C;
|
||||||
ID.Kind = ValID::t_Constant;
|
ID.Kind = ValID::t_Constant;
|
||||||
return false;
|
return false;
|
||||||
@ -2157,10 +2155,12 @@ bool LLParser::ParseValID(ValID &ID) {
|
|||||||
(Value**)(Elts.data() + 1),
|
(Value**)(Elts.data() + 1),
|
||||||
Elts.size() - 1))
|
Elts.size() - 1))
|
||||||
return Error(ID.Loc, "invalid indices for getelementptr");
|
return Error(ID.Loc, "invalid indices for getelementptr");
|
||||||
ID.ConstantVal = ConstantExpr::getGetElementPtr(Elts[0],
|
ID.ConstantVal = InBounds ?
|
||||||
Elts.data() + 1, Elts.size() - 1);
|
ConstantExpr::getInBoundsGetElementPtr(Elts[0],
|
||||||
if (InBounds)
|
Elts.data() + 1,
|
||||||
cast<GEPOperator>(ID.ConstantVal)->setIsInBounds(true);
|
Elts.size() - 1) :
|
||||||
|
ConstantExpr::getGetElementPtr(Elts[0],
|
||||||
|
Elts.data() + 1, Elts.size() - 1);
|
||||||
} else if (Opc == Instruction::Select) {
|
} else if (Opc == Instruction::Select) {
|
||||||
if (Elts.size() != 3)
|
if (Elts.size() != 3)
|
||||||
return Error(ID.Loc, "expected three operands to select");
|
return Error(ID.Loc, "expected three operands to select");
|
||||||
@ -2681,9 +2681,9 @@ bool LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB,
|
|||||||
return Error(ModifierLoc, "nsw only applies to integer operations");
|
return Error(ModifierLoc, "nsw only applies to integer operations");
|
||||||
}
|
}
|
||||||
if (NUW)
|
if (NUW)
|
||||||
cast<OverflowingBinaryOperator>(Inst)->setHasNoUnsignedWrap(true);
|
cast<BinaryOperator>(Inst)->setHasNoUnsignedWrap(true);
|
||||||
if (NSW)
|
if (NSW)
|
||||||
cast<OverflowingBinaryOperator>(Inst)->setHasNoSignedWrap(true);
|
cast<BinaryOperator>(Inst)->setHasNoSignedWrap(true);
|
||||||
}
|
}
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
@ -2698,7 +2698,7 @@ bool LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB,
|
|||||||
bool Result = ParseArithmetic(Inst, PFS, KeywordVal, 1);
|
bool Result = ParseArithmetic(Inst, PFS, KeywordVal, 1);
|
||||||
if (!Result)
|
if (!Result)
|
||||||
if (Exact)
|
if (Exact)
|
||||||
cast<SDivOperator>(Inst)->setIsExact(true);
|
cast<BinaryOperator>(Inst)->setIsExact(true);
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3501,7 +3501,7 @@ bool LLParser::ParseGetElementPtr(Instruction *&Inst, PerFunctionState &PFS) {
|
|||||||
return Error(Loc, "invalid getelementptr indices");
|
return Error(Loc, "invalid getelementptr indices");
|
||||||
Inst = GetElementPtrInst::Create(Ptr, Indices.begin(), Indices.end());
|
Inst = GetElementPtrInst::Create(Ptr, Indices.begin(), Indices.end());
|
||||||
if (InBounds)
|
if (InBounds)
|
||||||
cast<GEPOperator>(Inst)->setIsInBounds(true);
|
cast<GetElementPtrInst>(Inst)->setIsInBounds(true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -883,19 +883,6 @@ bool BitcodeReader::ResolveGlobalAndAliasInits() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetOptimizationFlags(Value *V, uint64_t Flags) {
|
|
||||||
if (OverflowingBinaryOperator *OBO =
|
|
||||||
dyn_cast<OverflowingBinaryOperator>(V)) {
|
|
||||||
if (Flags & (1 << bitc::OBO_NO_SIGNED_WRAP))
|
|
||||||
OBO->setHasNoSignedWrap(true);
|
|
||||||
if (Flags & (1 << bitc::OBO_NO_UNSIGNED_WRAP))
|
|
||||||
OBO->setHasNoUnsignedWrap(true);
|
|
||||||
} else if (SDivOperator *Div = dyn_cast<SDivOperator>(V)) {
|
|
||||||
if (Flags & (1 << bitc::SDIV_EXACT))
|
|
||||||
Div->setIsExact(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BitcodeReader::ParseConstants() {
|
bool BitcodeReader::ParseConstants() {
|
||||||
if (Stream.EnterSubBlock(bitc::CONSTANTS_BLOCK_ID))
|
if (Stream.EnterSubBlock(bitc::CONSTANTS_BLOCK_ID))
|
||||||
return Error("Malformed block record");
|
return Error("Malformed block record");
|
||||||
@ -1047,10 +1034,22 @@ bool BitcodeReader::ParseConstants() {
|
|||||||
} else {
|
} else {
|
||||||
Constant *LHS = ValueList.getConstantFwdRef(Record[1], CurTy);
|
Constant *LHS = ValueList.getConstantFwdRef(Record[1], CurTy);
|
||||||
Constant *RHS = ValueList.getConstantFwdRef(Record[2], CurTy);
|
Constant *RHS = ValueList.getConstantFwdRef(Record[2], CurTy);
|
||||||
V = ConstantExpr::get(Opc, LHS, RHS);
|
unsigned Flags = 0;
|
||||||
|
if (Record.size() >= 4) {
|
||||||
|
if (Opc == Instruction::Add ||
|
||||||
|
Opc == Instruction::Sub ||
|
||||||
|
Opc == Instruction::Mul) {
|
||||||
|
if (Record[3] & (1 << bitc::OBO_NO_SIGNED_WRAP))
|
||||||
|
Flags |= OverflowingBinaryOperator::NoSignedWrap;
|
||||||
|
if (Record[3] & (1 << bitc::OBO_NO_UNSIGNED_WRAP))
|
||||||
|
Flags |= OverflowingBinaryOperator::NoUnsignedWrap;
|
||||||
|
} else if (Opc == Instruction::SDiv) {
|
||||||
|
if (Record[3] & (1 << bitc::SDIV_EXACT))
|
||||||
|
Flags |= SDivOperator::IsExact;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
V = ConstantExpr::get(Opc, LHS, RHS, Flags);
|
||||||
}
|
}
|
||||||
if (Record.size() >= 4)
|
|
||||||
SetOptimizationFlags(V, Record[3]);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case bitc::CST_CODE_CE_CAST: { // CE_CAST: [opcode, opty, opval]
|
case bitc::CST_CODE_CE_CAST: { // CE_CAST: [opcode, opty, opval]
|
||||||
@ -1075,10 +1074,12 @@ bool BitcodeReader::ParseConstants() {
|
|||||||
if (!ElTy) return Error("Invalid CE_GEP record");
|
if (!ElTy) return Error("Invalid CE_GEP record");
|
||||||
Elts.push_back(ValueList.getConstantFwdRef(Record[i+1], ElTy));
|
Elts.push_back(ValueList.getConstantFwdRef(Record[i+1], ElTy));
|
||||||
}
|
}
|
||||||
V = ConstantExpr::getGetElementPtr(Elts[0], &Elts[1],
|
|
||||||
Elts.size()-1);
|
|
||||||
if (BitCode == bitc::CST_CODE_CE_INBOUNDS_GEP)
|
if (BitCode == bitc::CST_CODE_CE_INBOUNDS_GEP)
|
||||||
cast<GEPOperator>(V)->setIsInBounds(true);
|
V = ConstantExpr::getInBoundsGetElementPtr(Elts[0], &Elts[1],
|
||||||
|
Elts.size()-1);
|
||||||
|
else
|
||||||
|
V = ConstantExpr::getGetElementPtr(Elts[0], &Elts[1],
|
||||||
|
Elts.size()-1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case bitc::CST_CODE_CE_SELECT: // CE_SELECT: [opval#, opval#, opval#]
|
case bitc::CST_CODE_CE_SELECT: // CE_SELECT: [opval#, opval#, opval#]
|
||||||
@ -1610,8 +1611,19 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
|
|||||||
int Opc = GetDecodedBinaryOpcode(Record[OpNum++], LHS->getType());
|
int Opc = GetDecodedBinaryOpcode(Record[OpNum++], LHS->getType());
|
||||||
if (Opc == -1) return Error("Invalid BINOP record");
|
if (Opc == -1) return Error("Invalid BINOP record");
|
||||||
I = BinaryOperator::Create((Instruction::BinaryOps)Opc, LHS, RHS);
|
I = BinaryOperator::Create((Instruction::BinaryOps)Opc, LHS, RHS);
|
||||||
if (OpNum < Record.size())
|
if (OpNum < Record.size()) {
|
||||||
SetOptimizationFlags(I, Record[3]);
|
if (Opc == Instruction::Add ||
|
||||||
|
Opc == Instruction::Sub ||
|
||||||
|
Opc == Instruction::Mul) {
|
||||||
|
if (Record[3] & (1 << bitc::OBO_NO_SIGNED_WRAP))
|
||||||
|
cast<BinaryOperator>(I)->setHasNoSignedWrap(true);
|
||||||
|
if (Record[3] & (1 << bitc::OBO_NO_UNSIGNED_WRAP))
|
||||||
|
cast<BinaryOperator>(I)->setHasNoUnsignedWrap(true);
|
||||||
|
} else if (Opc == Instruction::SDiv) {
|
||||||
|
if (Record[3] & (1 << bitc::SDIV_EXACT))
|
||||||
|
cast<BinaryOperator>(I)->setIsExact(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case bitc::FUNC_CODE_INST_CAST: { // CAST: [opval, opty, destty, castopc]
|
case bitc::FUNC_CODE_INST_CAST: { // CAST: [opval, opty, destty, castopc]
|
||||||
@ -1645,7 +1657,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
|
|||||||
|
|
||||||
I = GetElementPtrInst::Create(BasePtr, GEPIdx.begin(), GEPIdx.end());
|
I = GetElementPtrInst::Create(BasePtr, GEPIdx.begin(), GEPIdx.end());
|
||||||
if (BitCode == bitc::FUNC_CODE_INST_INBOUNDS_GEP)
|
if (BitCode == bitc::FUNC_CODE_INST_INBOUNDS_GEP)
|
||||||
cast<GEPOperator>(I)->setIsInBounds(true);
|
cast<GetElementPtrInst>(I)->setIsInBounds(true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8086,11 +8086,11 @@ Instruction *InstCombiner::commonPointerCastTransforms(CastInst &CI) {
|
|||||||
// If we were able to index down into an element, create the GEP
|
// If we were able to index down into an element, create the GEP
|
||||||
// and bitcast the result. This eliminates one bitcast, potentially
|
// and bitcast the result. This eliminates one bitcast, potentially
|
||||||
// two.
|
// two.
|
||||||
Value *NGEP = Builder->CreateGEP(OrigBase, NewIndices.begin(),
|
Value *NGEP = cast<GEPOperator>(GEP)->isInBounds() ?
|
||||||
NewIndices.end());
|
Builder->CreateInBoundsGEP(OrigBase,
|
||||||
|
NewIndices.begin(), NewIndices.end()) :
|
||||||
|
Builder->CreateGEP(OrigBase, NewIndices.begin(), NewIndices.end());
|
||||||
NGEP->takeName(GEP);
|
NGEP->takeName(GEP);
|
||||||
if (isa<Instruction>(NGEP) && cast<GEPOperator>(GEP)->isInBounds())
|
|
||||||
cast<GEPOperator>(NGEP)->setIsInBounds(true);
|
|
||||||
|
|
||||||
if (isa<BitCastInst>(CI))
|
if (isa<BitCastInst>(CI))
|
||||||
return new BitCastInst(NGEP, CI.getType());
|
return new BitCastInst(NGEP, CI.getType());
|
||||||
@ -8805,11 +8805,8 @@ Instruction *InstCombiner::visitBitCast(BitCastInst &CI) {
|
|||||||
// If we found a path from the src to dest, create the getelementptr now.
|
// If we found a path from the src to dest, create the getelementptr now.
|
||||||
if (SrcElTy == DstElTy) {
|
if (SrcElTy == DstElTy) {
|
||||||
SmallVector<Value*, 8> Idxs(NumZeros+1, ZeroUInt);
|
SmallVector<Value*, 8> Idxs(NumZeros+1, ZeroUInt);
|
||||||
Instruction *GEP = GetElementPtrInst::Create(Src,
|
return GetElementPtrInst::CreateInBounds(Src, Idxs.begin(), Idxs.end(), "",
|
||||||
Idxs.begin(), Idxs.end(), "",
|
((Instruction*) NULL));
|
||||||
((Instruction*) NULL));
|
|
||||||
cast<GEPOperator>(GEP)->setIsInBounds(true);
|
|
||||||
return GEP;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -10481,12 +10478,11 @@ Instruction *InstCombiner::FoldPHIArgGEPIntoPHI(PHINode &PN) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Value *Base = FixedOperands[0];
|
Value *Base = FixedOperands[0];
|
||||||
GetElementPtrInst *GEP =
|
return cast<GEPOperator>(FirstInst)->isInBounds() ?
|
||||||
|
GetElementPtrInst::CreateInBounds(Base, FixedOperands.begin()+1,
|
||||||
|
FixedOperands.end()) :
|
||||||
GetElementPtrInst::Create(Base, FixedOperands.begin()+1,
|
GetElementPtrInst::Create(Base, FixedOperands.begin()+1,
|
||||||
FixedOperands.end());
|
FixedOperands.end());
|
||||||
if (cast<GEPOperator>(FirstInst)->isInBounds())
|
|
||||||
cast<GEPOperator>(GEP)->setIsInBounds(true);
|
|
||||||
return GEP;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -10889,14 +10885,13 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
|
|||||||
Indices.append(GEP.idx_begin()+1, GEP.idx_end());
|
Indices.append(GEP.idx_begin()+1, GEP.idx_end());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Indices.empty()) {
|
if (!Indices.empty())
|
||||||
GetElementPtrInst *NewGEP =
|
return (cast<GEPOperator>(&GEP)->isInBounds() &&
|
||||||
|
Src->isInBounds()) ?
|
||||||
|
GetElementPtrInst::CreateInBounds(Src->getOperand(0), Indices.begin(),
|
||||||
|
Indices.end(), GEP.getName()) :
|
||||||
GetElementPtrInst::Create(Src->getOperand(0), Indices.begin(),
|
GetElementPtrInst::Create(Src->getOperand(0), Indices.begin(),
|
||||||
Indices.end(), GEP.getName());
|
Indices.end(), GEP.getName());
|
||||||
if (cast<GEPOperator>(&GEP)->isInBounds() && Src->isInBounds())
|
|
||||||
cast<GEPOperator>(NewGEP)->setIsInBounds(true);
|
|
||||||
return NewGEP;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle gep(bitcast x) and gep(gep x, 0, 0, 0).
|
// Handle gep(bitcast x) and gep(gep x, 0, 0, 0).
|
||||||
@ -10926,12 +10921,11 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
|
|||||||
if (CATy->getElementType() == XTy->getElementType()) {
|
if (CATy->getElementType() == XTy->getElementType()) {
|
||||||
// -> GEP i8* X, ...
|
// -> GEP i8* X, ...
|
||||||
SmallVector<Value*, 8> Indices(GEP.idx_begin()+1, GEP.idx_end());
|
SmallVector<Value*, 8> Indices(GEP.idx_begin()+1, GEP.idx_end());
|
||||||
GetElementPtrInst *NewGEP =
|
return cast<GEPOperator>(&GEP)->isInBounds() ?
|
||||||
|
GetElementPtrInst::CreateInBounds(X, Indices.begin(), Indices.end(),
|
||||||
|
GEP.getName()) :
|
||||||
GetElementPtrInst::Create(X, Indices.begin(), Indices.end(),
|
GetElementPtrInst::Create(X, Indices.begin(), Indices.end(),
|
||||||
GEP.getName());
|
GEP.getName());
|
||||||
if (cast<GEPOperator>(&GEP)->isInBounds())
|
|
||||||
cast<GEPOperator>(NewGEP)->setIsInBounds(true);
|
|
||||||
return NewGEP;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const ArrayType *XATy = dyn_cast<ArrayType>(XTy->getElementType())){
|
if (const ArrayType *XATy = dyn_cast<ArrayType>(XTy->getElementType())){
|
||||||
@ -10959,10 +10953,9 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
|
|||||||
Value *Idx[2];
|
Value *Idx[2];
|
||||||
Idx[0] = Constant::getNullValue(Type::getInt32Ty(*Context));
|
Idx[0] = Constant::getNullValue(Type::getInt32Ty(*Context));
|
||||||
Idx[1] = GEP.getOperand(1);
|
Idx[1] = GEP.getOperand(1);
|
||||||
Value *NewGEP =
|
Value *NewGEP = cast<GEPOperator>(&GEP)->isInBounds() ?
|
||||||
|
Builder->CreateInBoundsGEP(X, Idx, Idx + 2, GEP.getName()) :
|
||||||
Builder->CreateGEP(X, Idx, Idx + 2, GEP.getName());
|
Builder->CreateGEP(X, Idx, Idx + 2, GEP.getName());
|
||||||
if (cast<GEPOperator>(&GEP)->isInBounds())
|
|
||||||
cast<GEPOperator>(NewGEP)->setIsInBounds(true);
|
|
||||||
// V and GEP are both pointer types --> BitCast
|
// V and GEP are both pointer types --> BitCast
|
||||||
return new BitCastInst(NewGEP, GEP.getType());
|
return new BitCastInst(NewGEP, GEP.getType());
|
||||||
}
|
}
|
||||||
@ -11019,9 +11012,9 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
|
|||||||
Value *Idx[2];
|
Value *Idx[2];
|
||||||
Idx[0] = Constant::getNullValue(Type::getInt32Ty(*Context));
|
Idx[0] = Constant::getNullValue(Type::getInt32Ty(*Context));
|
||||||
Idx[1] = NewIdx;
|
Idx[1] = NewIdx;
|
||||||
Value *NewGEP = Builder->CreateGEP(X, Idx, Idx + 2, GEP.getName());
|
Value *NewGEP = cast<GEPOperator>(&GEP)->isInBounds() ?
|
||||||
if (cast<GEPOperator>(&GEP)->isInBounds())
|
Builder->CreateInBoundsGEP(X, Idx, Idx + 2, GEP.getName()) :
|
||||||
cast<GEPOperator>(NewGEP)->setIsInBounds(true);
|
Builder->CreateGEP(X, Idx, Idx + 2, GEP.getName());
|
||||||
// The NewGEP must be pointer typed, so must the old one -> BitCast
|
// The NewGEP must be pointer typed, so must the old one -> BitCast
|
||||||
return new BitCastInst(NewGEP, GEP.getType());
|
return new BitCastInst(NewGEP, GEP.getType());
|
||||||
}
|
}
|
||||||
@ -11069,10 +11062,11 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
|
|||||||
const Type *InTy =
|
const Type *InTy =
|
||||||
cast<PointerType>(BCI->getOperand(0)->getType())->getElementType();
|
cast<PointerType>(BCI->getOperand(0)->getType())->getElementType();
|
||||||
if (FindElementAtOffset(InTy, Offset, NewIndices, TD, Context)) {
|
if (FindElementAtOffset(InTy, Offset, NewIndices, TD, Context)) {
|
||||||
Value *NGEP = Builder->CreateGEP(BCI->getOperand(0), NewIndices.begin(),
|
Value *NGEP = cast<GEPOperator>(&GEP)->isInBounds() ?
|
||||||
NewIndices.end());
|
Builder->CreateInBoundsGEP(BCI->getOperand(0), NewIndices.begin(),
|
||||||
if (cast<GEPOperator>(&GEP)->isInBounds())
|
NewIndices.end()) :
|
||||||
cast<GEPOperator>(NGEP)->setIsInBounds(true);
|
Builder->CreateGEP(BCI->getOperand(0), NewIndices.begin(),
|
||||||
|
NewIndices.end());
|
||||||
|
|
||||||
if (NGEP->getType() == GEP.getType())
|
if (NGEP->getType() == GEP.getType())
|
||||||
return ReplaceInstUsesWith(GEP, NGEP);
|
return ReplaceInstUsesWith(GEP, NGEP);
|
||||||
@ -11115,9 +11109,8 @@ Instruction *InstCombiner::visitAllocationInst(AllocationInst &AI) {
|
|||||||
Value *Idx[2];
|
Value *Idx[2];
|
||||||
Idx[0] = NullIdx;
|
Idx[0] = NullIdx;
|
||||||
Idx[1] = NullIdx;
|
Idx[1] = NullIdx;
|
||||||
Value *V = GetElementPtrInst::Create(New, Idx, Idx + 2,
|
Value *V = GetElementPtrInst::CreateInBounds(New, Idx, Idx + 2,
|
||||||
New->getName()+".sub", It);
|
New->getName()+".sub", It);
|
||||||
cast<GEPOperator>(V)->setIsInBounds(true);
|
|
||||||
|
|
||||||
// Now make everything use the getelementptr instead of the original
|
// Now make everything use the getelementptr instead of the original
|
||||||
// allocation.
|
// allocation.
|
||||||
@ -11486,11 +11479,9 @@ static Instruction *InstCombineStoreToCast(InstCombiner &IC, StoreInst &SI) {
|
|||||||
|
|
||||||
// SIOp0 is a pointer to aggregate and this is a store to the first field,
|
// SIOp0 is a pointer to aggregate and this is a store to the first field,
|
||||||
// emit a GEP to index into its first field.
|
// emit a GEP to index into its first field.
|
||||||
if (!NewGEPIndices.empty()) {
|
if (!NewGEPIndices.empty())
|
||||||
CastOp = IC.Builder->CreateGEP(CastOp, NewGEPIndices.begin(),
|
CastOp = IC.Builder->CreateInBoundsGEP(CastOp, NewGEPIndices.begin(),
|
||||||
NewGEPIndices.end());
|
NewGEPIndices.end());
|
||||||
cast<GEPOperator>(CastOp)->setIsInBounds(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
NewCast = IC.Builder->CreateCast(opcode, SIOp0, CastDstTy,
|
NewCast = IC.Builder->CreateCast(opcode, SIOp0, CastDstTy,
|
||||||
SIOp0->getName()+".c");
|
SIOp0->getName()+".c");
|
||||||
@ -12160,8 +12151,7 @@ Instruction *InstCombiner::visitExtractElementInst(ExtractElementInst &EI) {
|
|||||||
PointerType::get(EI.getType(), AS),
|
PointerType::get(EI.getType(), AS),
|
||||||
I->getOperand(0)->getName());
|
I->getOperand(0)->getName());
|
||||||
Value *GEP =
|
Value *GEP =
|
||||||
Builder->CreateGEP(Ptr, EI.getOperand(1), I->getName()+".gep");
|
Builder->CreateInBoundsGEP(Ptr, EI.getOperand(1), I->getName()+".gep");
|
||||||
cast<GEPOperator>(GEP)->setIsInBounds(true);
|
|
||||||
|
|
||||||
LoadInst *Load = Builder->CreateLoad(GEP, "tmp");
|
LoadInst *Load = Builder->CreateLoad(GEP, "tmp");
|
||||||
|
|
||||||
|
@ -632,21 +632,13 @@ Constant* ConstantVector::get(Constant* const* Vals, unsigned NumVals) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Constant* ConstantExpr::getNSWAdd(Constant* C1, Constant* C2) {
|
Constant* ConstantExpr::getNSWAdd(Constant* C1, Constant* C2) {
|
||||||
Constant *C = getAdd(C1, C2);
|
return getTy(C1->getType(), Instruction::Add, C1, C2,
|
||||||
// Set nsw attribute, assuming constant folding didn't eliminate the
|
OverflowingBinaryOperator::NoSignedWrap);
|
||||||
// Add.
|
|
||||||
if (AddOperator *Add = dyn_cast<AddOperator>(C))
|
|
||||||
Add->setHasNoSignedWrap(true);
|
|
||||||
return C;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Constant* ConstantExpr::getExactSDiv(Constant* C1, Constant* C2) {
|
Constant* ConstantExpr::getExactSDiv(Constant* C1, Constant* C2) {
|
||||||
Constant *C = getSDiv(C1, C2);
|
return getTy(C1->getType(), Instruction::SDiv, C1, C2,
|
||||||
// Set exact attribute, assuming constant folding didn't eliminate the
|
SDivOperator::IsExact);
|
||||||
// SDiv.
|
|
||||||
if (SDivOperator *SDiv = dyn_cast<SDivOperator>(C))
|
|
||||||
SDiv->setIsExact(true);
|
|
||||||
return C;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Utility function for determining if a ConstantExpr is a CastOp or not. This
|
// Utility function for determining if a ConstantExpr is a CastOp or not. This
|
||||||
@ -729,15 +721,19 @@ ConstantExpr::getWithOperandReplaced(unsigned OpNo, Constant *Op) const {
|
|||||||
for (unsigned i = 1, e = getNumOperands(); i != e; ++i)
|
for (unsigned i = 1, e = getNumOperands(); i != e; ++i)
|
||||||
Ops[i-1] = getOperand(i);
|
Ops[i-1] = getOperand(i);
|
||||||
if (OpNo == 0)
|
if (OpNo == 0)
|
||||||
return ConstantExpr::getGetElementPtr(Op, &Ops[0], Ops.size());
|
return cast<GEPOperator>(this)->isInBounds() ?
|
||||||
|
ConstantExpr::getInBoundsGetElementPtr(Op, &Ops[0], Ops.size()) :
|
||||||
|
ConstantExpr::getGetElementPtr(Op, &Ops[0], Ops.size());
|
||||||
Ops[OpNo-1] = Op;
|
Ops[OpNo-1] = Op;
|
||||||
return ConstantExpr::getGetElementPtr(getOperand(0), &Ops[0], Ops.size());
|
return cast<GEPOperator>(this)->isInBounds() ?
|
||||||
|
ConstantExpr::getInBoundsGetElementPtr(getOperand(0), &Ops[0], Ops.size()) :
|
||||||
|
ConstantExpr::getGetElementPtr(getOperand(0), &Ops[0], Ops.size());
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
assert(getNumOperands() == 2 && "Must be binary operator?");
|
assert(getNumOperands() == 2 && "Must be binary operator?");
|
||||||
Op0 = (OpNo == 0) ? Op : getOperand(0);
|
Op0 = (OpNo == 0) ? Op : getOperand(0);
|
||||||
Op1 = (OpNo == 1) ? Op : getOperand(1);
|
Op1 = (OpNo == 1) ? Op : getOperand(1);
|
||||||
return ConstantExpr::get(getOpcode(), Op0, Op1);
|
return ConstantExpr::get(getOpcode(), Op0, Op1, SubclassData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -779,13 +775,15 @@ getWithOperands(Constant* const *Ops, unsigned NumOps) const {
|
|||||||
case Instruction::ShuffleVector:
|
case Instruction::ShuffleVector:
|
||||||
return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2]);
|
return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2]);
|
||||||
case Instruction::GetElementPtr:
|
case Instruction::GetElementPtr:
|
||||||
return ConstantExpr::getGetElementPtr(Ops[0], &Ops[1], NumOps-1);
|
return cast<GEPOperator>(this)->isInBounds() ?
|
||||||
|
ConstantExpr::getInBoundsGetElementPtr(Ops[0], &Ops[1], NumOps-1) :
|
||||||
|
ConstantExpr::getGetElementPtr(Ops[0], &Ops[1], NumOps-1);
|
||||||
case Instruction::ICmp:
|
case Instruction::ICmp:
|
||||||
case Instruction::FCmp:
|
case Instruction::FCmp:
|
||||||
return ConstantExpr::getCompare(getPredicate(), Ops[0], Ops[1]);
|
return ConstantExpr::getCompare(getPredicate(), Ops[0], Ops[1]);
|
||||||
default:
|
default:
|
||||||
assert(getNumOperands() == 2 && "Must be binary operator?");
|
assert(getNumOperands() == 2 && "Must be binary operator?");
|
||||||
return ConstantExpr::get(getOpcode(), Ops[0], Ops[1]);
|
return ConstantExpr::get(getOpcode(), Ops[0], Ops[1], SubclassData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1031,8 +1029,9 @@ static ExprMapKeyType getValType(ConstantExpr *CE) {
|
|||||||
Operands.reserve(CE->getNumOperands());
|
Operands.reserve(CE->getNumOperands());
|
||||||
for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i)
|
for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i)
|
||||||
Operands.push_back(cast<Constant>(CE->getOperand(i)));
|
Operands.push_back(cast<Constant>(CE->getOperand(i)));
|
||||||
return ExprMapKeyType(CE->getOpcode(), Operands,
|
return ExprMapKeyType(CE->getOpcode(), Operands,
|
||||||
CE->isCompare() ? CE->getPredicate() : 0,
|
CE->isCompare() ? CE->getPredicate() : 0,
|
||||||
|
CE->getRawSubclassOptionalData(),
|
||||||
CE->hasIndices() ?
|
CE->hasIndices() ?
|
||||||
CE->getIndices() : SmallVector<unsigned, 4>());
|
CE->getIndices() : SmallVector<unsigned, 4>());
|
||||||
}
|
}
|
||||||
@ -1280,7 +1279,8 @@ Constant *ConstantExpr::getBitCast(Constant *C, const Type *DstTy) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Constant *ConstantExpr::getTy(const Type *ReqTy, unsigned Opcode,
|
Constant *ConstantExpr::getTy(const Type *ReqTy, unsigned Opcode,
|
||||||
Constant *C1, Constant *C2) {
|
Constant *C1, Constant *C2,
|
||||||
|
unsigned Flags) {
|
||||||
// Check the operands for consistency first
|
// Check the operands for consistency first
|
||||||
assert(Opcode >= Instruction::BinaryOpsBegin &&
|
assert(Opcode >= Instruction::BinaryOpsBegin &&
|
||||||
Opcode < Instruction::BinaryOpsEnd &&
|
Opcode < Instruction::BinaryOpsEnd &&
|
||||||
@ -1294,7 +1294,7 @@ Constant *ConstantExpr::getTy(const Type *ReqTy, unsigned Opcode,
|
|||||||
return FC; // Fold a few common cases...
|
return FC; // Fold a few common cases...
|
||||||
|
|
||||||
std::vector<Constant*> argVec(1, C1); argVec.push_back(C2);
|
std::vector<Constant*> argVec(1, C1); argVec.push_back(C2);
|
||||||
ExprMapKeyType Key(Opcode, argVec);
|
ExprMapKeyType Key(Opcode, argVec, 0, Flags);
|
||||||
|
|
||||||
LLVMContextImpl *pImpl = ReqTy->getContext().pImpl;
|
LLVMContextImpl *pImpl = ReqTy->getContext().pImpl;
|
||||||
|
|
||||||
@ -1322,7 +1322,8 @@ Constant *ConstantExpr::getCompareTy(unsigned short predicate,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2) {
|
Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2,
|
||||||
|
unsigned Flags) {
|
||||||
// API compatibility: Adjust integer opcodes to floating-point opcodes.
|
// API compatibility: Adjust integer opcodes to floating-point opcodes.
|
||||||
if (C1->getType()->isFPOrFPVector()) {
|
if (C1->getType()->isFPOrFPVector()) {
|
||||||
if (Opcode == Instruction::Add) Opcode = Instruction::FAdd;
|
if (Opcode == Instruction::Add) Opcode = Instruction::FAdd;
|
||||||
@ -1387,7 +1388,7 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return getTy(C1->getType(), Opcode, C1, C2);
|
return getTy(C1->getType(), Opcode, C1, C2, Flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
Constant* ConstantExpr::getSizeOf(const Type* Ty) {
|
Constant* ConstantExpr::getSizeOf(const Type* Ty) {
|
||||||
@ -1481,6 +1482,36 @@ Constant *ConstantExpr::getGetElementPtrTy(const Type *ReqTy, Constant *C,
|
|||||||
return pImpl->ExprConstants.getOrCreate(ReqTy, Key);
|
return pImpl->ExprConstants.getOrCreate(ReqTy, Key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Constant *ConstantExpr::getInBoundsGetElementPtrTy(const Type *ReqTy,
|
||||||
|
Constant *C,
|
||||||
|
Value* const *Idxs,
|
||||||
|
unsigned NumIdx) {
|
||||||
|
assert(GetElementPtrInst::getIndexedType(C->getType(), Idxs,
|
||||||
|
Idxs+NumIdx) ==
|
||||||
|
cast<PointerType>(ReqTy)->getElementType() &&
|
||||||
|
"GEP indices invalid!");
|
||||||
|
|
||||||
|
if (Constant *FC = ConstantFoldGetElementPtr(
|
||||||
|
ReqTy->getContext(), C, (Constant**)Idxs, NumIdx))
|
||||||
|
return FC; // Fold a few common cases...
|
||||||
|
|
||||||
|
assert(isa<PointerType>(C->getType()) &&
|
||||||
|
"Non-pointer type for constant GetElementPtr expression");
|
||||||
|
// Look up the constant in the table first to ensure uniqueness
|
||||||
|
std::vector<Constant*> ArgVec;
|
||||||
|
ArgVec.reserve(NumIdx+1);
|
||||||
|
ArgVec.push_back(C);
|
||||||
|
for (unsigned i = 0; i != NumIdx; ++i)
|
||||||
|
ArgVec.push_back(cast<Constant>(Idxs[i]));
|
||||||
|
const ExprMapKeyType Key(Instruction::GetElementPtr, ArgVec, 0,
|
||||||
|
GEPOperator::IsInBounds);
|
||||||
|
|
||||||
|
LLVMContextImpl *pImpl = ReqTy->getContext().pImpl;
|
||||||
|
|
||||||
|
// Implicitly locked.
|
||||||
|
return pImpl->ExprConstants.getOrCreate(ReqTy, Key);
|
||||||
|
}
|
||||||
|
|
||||||
Constant *ConstantExpr::getGetElementPtr(Constant *C, Value* const *Idxs,
|
Constant *ConstantExpr::getGetElementPtr(Constant *C, Value* const *Idxs,
|
||||||
unsigned NumIdx) {
|
unsigned NumIdx) {
|
||||||
// Get the result type of the getelementptr!
|
// Get the result type of the getelementptr!
|
||||||
@ -1494,12 +1525,12 @@ Constant *ConstantExpr::getGetElementPtr(Constant *C, Value* const *Idxs,
|
|||||||
Constant *ConstantExpr::getInBoundsGetElementPtr(Constant *C,
|
Constant *ConstantExpr::getInBoundsGetElementPtr(Constant *C,
|
||||||
Value* const *Idxs,
|
Value* const *Idxs,
|
||||||
unsigned NumIdx) {
|
unsigned NumIdx) {
|
||||||
Constant *Result = getGetElementPtr(C, Idxs, NumIdx);
|
// Get the result type of the getelementptr!
|
||||||
// Set in bounds attribute, assuming constant folding didn't eliminate the
|
const Type *Ty =
|
||||||
// GEP.
|
GetElementPtrInst::getIndexedType(C->getType(), Idxs, Idxs+NumIdx);
|
||||||
if (GEPOperator *GEP = dyn_cast<GEPOperator>(Result))
|
assert(Ty && "GEP indices invalid!");
|
||||||
GEP->setIsInBounds(true);
|
unsigned As = cast<PointerType>(C->getType())->getAddressSpace();
|
||||||
return Result;
|
return getInBoundsGetElementPtrTy(PointerType::get(Ty, As), C, Idxs, NumIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
Constant *ConstantExpr::getGetElementPtr(Constant *C, Constant* const *Idxs,
|
Constant *ConstantExpr::getGetElementPtr(Constant *C, Constant* const *Idxs,
|
||||||
@ -2104,7 +2135,7 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
|
|||||||
Constant *C2 = getOperand(1);
|
Constant *C2 = getOperand(1);
|
||||||
if (C1 == From) C1 = To;
|
if (C1 == From) C1 = To;
|
||||||
if (C2 == From) C2 = To;
|
if (C2 == From) C2 = To;
|
||||||
Replacement = ConstantExpr::get(getOpcode(), C1, C2);
|
Replacement = ConstantExpr::get(getOpcode(), C1, C2, SubclassData);
|
||||||
} else {
|
} else {
|
||||||
llvm_unreachable("Unknown ConstantExpr type!");
|
llvm_unreachable("Unknown ConstantExpr type!");
|
||||||
return;
|
return;
|
||||||
|
@ -53,10 +53,12 @@ public:
|
|||||||
void *operator new(size_t s) {
|
void *operator new(size_t s) {
|
||||||
return User::operator new(s, 2);
|
return User::operator new(s, 2);
|
||||||
}
|
}
|
||||||
BinaryConstantExpr(unsigned Opcode, Constant *C1, Constant *C2)
|
BinaryConstantExpr(unsigned Opcode, Constant *C1, Constant *C2,
|
||||||
|
unsigned Flags)
|
||||||
: ConstantExpr(C1->getType(), Opcode, &Op<0>(), 2) {
|
: ConstantExpr(C1->getType(), Opcode, &Op<0>(), 2) {
|
||||||
Op<0>() = C1;
|
Op<0>() = C1;
|
||||||
Op<1>() = C2;
|
Op<1>() = C2;
|
||||||
|
SubclassOptionalData = Flags;
|
||||||
}
|
}
|
||||||
/// Transparently provide more efficient getOperand methods.
|
/// Transparently provide more efficient getOperand methods.
|
||||||
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
|
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
|
||||||
@ -206,9 +208,12 @@ class GetElementPtrConstantExpr : public ConstantExpr {
|
|||||||
public:
|
public:
|
||||||
static GetElementPtrConstantExpr *Create(Constant *C,
|
static GetElementPtrConstantExpr *Create(Constant *C,
|
||||||
const std::vector<Constant*>&IdxList,
|
const std::vector<Constant*>&IdxList,
|
||||||
const Type *DestTy) {
|
const Type *DestTy,
|
||||||
return
|
unsigned Flags) {
|
||||||
|
GetElementPtrConstantExpr *Result =
|
||||||
new(IdxList.size() + 1) GetElementPtrConstantExpr(C, IdxList, DestTy);
|
new(IdxList.size() + 1) GetElementPtrConstantExpr(C, IdxList, DestTy);
|
||||||
|
Result->SubclassOptionalData = Flags;
|
||||||
|
return Result;
|
||||||
}
|
}
|
||||||
/// Transparently provide more efficient getOperand methods.
|
/// Transparently provide more efficient getOperand methods.
|
||||||
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
|
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
|
||||||
@ -291,26 +296,32 @@ struct ExprMapKeyType {
|
|||||||
|
|
||||||
ExprMapKeyType(unsigned opc,
|
ExprMapKeyType(unsigned opc,
|
||||||
const std::vector<Constant*> &ops,
|
const std::vector<Constant*> &ops,
|
||||||
unsigned short pred = 0,
|
unsigned short flags = 0,
|
||||||
|
unsigned short optionalflags = 0,
|
||||||
const IndexList &inds = IndexList())
|
const IndexList &inds = IndexList())
|
||||||
: opcode(opc), predicate(pred), operands(ops), indices(inds) {}
|
: opcode(opc), subclassoptionaldata(optionalflags), subclassdata(flags),
|
||||||
uint16_t opcode;
|
operands(ops), indices(inds) {}
|
||||||
uint16_t predicate;
|
uint8_t opcode;
|
||||||
|
uint8_t subclassoptionaldata;
|
||||||
|
uint16_t subclassdata;
|
||||||
std::vector<Constant*> operands;
|
std::vector<Constant*> operands;
|
||||||
IndexList indices;
|
IndexList indices;
|
||||||
bool operator==(const ExprMapKeyType& that) const {
|
bool operator==(const ExprMapKeyType& that) const {
|
||||||
return this->opcode == that.opcode &&
|
return this->opcode == that.opcode &&
|
||||||
this->predicate == that.predicate &&
|
this->subclassdata == that.subclassdata &&
|
||||||
|
this->subclassoptionaldata == that.subclassoptionaldata &&
|
||||||
this->operands == that.operands &&
|
this->operands == that.operands &&
|
||||||
this->indices == that.indices;
|
this->indices == that.indices;
|
||||||
}
|
}
|
||||||
bool operator<(const ExprMapKeyType & that) const {
|
bool operator<(const ExprMapKeyType & that) const {
|
||||||
return this->opcode < that.opcode ||
|
if (this->opcode != that.opcode) return this->opcode < that.opcode;
|
||||||
(this->opcode == that.opcode && this->predicate < that.predicate) ||
|
if (this->operands != that.operands) return this->operands < that.operands;
|
||||||
(this->opcode == that.opcode && this->predicate == that.predicate &&
|
if (this->subclassdata != that.subclassdata)
|
||||||
this->operands < that.operands) ||
|
return this->subclassdata < that.subclassdata;
|
||||||
(this->opcode == that.opcode && this->predicate == that.predicate &&
|
if (this->subclassoptionaldata != that.subclassoptionaldata)
|
||||||
this->operands == that.operands && this->indices < that.indices);
|
return this->subclassoptionaldata < that.subclassoptionaldata;
|
||||||
|
if (this->indices != that.indices) return this->indices < that.indices;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const ExprMapKeyType& that) const {
|
bool operator!=(const ExprMapKeyType& that) const {
|
||||||
@ -354,7 +365,8 @@ struct ConstantCreator<ConstantExpr, Type, ExprMapKeyType> {
|
|||||||
return new UnaryConstantExpr(V.opcode, V.operands[0], Ty);
|
return new UnaryConstantExpr(V.opcode, V.operands[0], Ty);
|
||||||
if ((V.opcode >= Instruction::BinaryOpsBegin &&
|
if ((V.opcode >= Instruction::BinaryOpsBegin &&
|
||||||
V.opcode < Instruction::BinaryOpsEnd))
|
V.opcode < Instruction::BinaryOpsEnd))
|
||||||
return new BinaryConstantExpr(V.opcode, V.operands[0], V.operands[1]);
|
return new BinaryConstantExpr(V.opcode, V.operands[0], V.operands[1],
|
||||||
|
V.subclassoptionaldata);
|
||||||
if (V.opcode == Instruction::Select)
|
if (V.opcode == Instruction::Select)
|
||||||
return new SelectConstantExpr(V.operands[0], V.operands[1],
|
return new SelectConstantExpr(V.operands[0], V.operands[1],
|
||||||
V.operands[2]);
|
V.operands[2]);
|
||||||
@ -373,17 +385,18 @@ struct ConstantCreator<ConstantExpr, Type, ExprMapKeyType> {
|
|||||||
return new ExtractValueConstantExpr(V.operands[0], V.indices, Ty);
|
return new ExtractValueConstantExpr(V.operands[0], V.indices, Ty);
|
||||||
if (V.opcode == Instruction::GetElementPtr) {
|
if (V.opcode == Instruction::GetElementPtr) {
|
||||||
std::vector<Constant*> IdxList(V.operands.begin()+1, V.operands.end());
|
std::vector<Constant*> IdxList(V.operands.begin()+1, V.operands.end());
|
||||||
return GetElementPtrConstantExpr::Create(V.operands[0], IdxList, Ty);
|
return GetElementPtrConstantExpr::Create(V.operands[0], IdxList, Ty,
|
||||||
|
V.subclassoptionaldata);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The compare instructions are weird. We have to encode the predicate
|
// The compare instructions are weird. We have to encode the predicate
|
||||||
// value and it is combined with the instruction opcode by multiplying
|
// value and it is combined with the instruction opcode by multiplying
|
||||||
// the opcode by one hundred. We must decode this to get the predicate.
|
// the opcode by one hundred. We must decode this to get the predicate.
|
||||||
if (V.opcode == Instruction::ICmp)
|
if (V.opcode == Instruction::ICmp)
|
||||||
return new CompareConstantExpr(Ty, Instruction::ICmp, V.predicate,
|
return new CompareConstantExpr(Ty, Instruction::ICmp, V.subclassdata,
|
||||||
V.operands[0], V.operands[1]);
|
V.operands[0], V.operands[1]);
|
||||||
if (V.opcode == Instruction::FCmp)
|
if (V.opcode == Instruction::FCmp)
|
||||||
return new CompareConstantExpr(Ty, Instruction::FCmp, V.predicate,
|
return new CompareConstantExpr(Ty, Instruction::FCmp, V.subclassdata,
|
||||||
V.operands[0], V.operands[1]);
|
V.operands[0], V.operands[1]);
|
||||||
llvm_unreachable("Invalid ConstantExpr!");
|
llvm_unreachable("Invalid ConstantExpr!");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1171,6 +1171,9 @@ bool GetElementPtrInst::hasAllConstantIndices() const {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GetElementPtrInst::setIsInBounds(bool B) {
|
||||||
|
cast<GEPOperator>(this)->setIsInBounds(B);
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// ExtractElementInst Implementation
|
// ExtractElementInst Implementation
|
||||||
@ -1716,6 +1719,18 @@ bool BinaryOperator::swapOperands() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BinaryOperator::setHasNoUnsignedWrap(bool b) {
|
||||||
|
cast<OverflowingBinaryOperator>(this)->setHasNoUnsignedWrap(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BinaryOperator::setHasNoSignedWrap(bool b) {
|
||||||
|
cast<OverflowingBinaryOperator>(this)->setHasNoSignedWrap(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BinaryOperator::setIsExact(bool b) {
|
||||||
|
cast<SDivOperator>(this)->setIsExact(b);
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// CastInst Class
|
// CastInst Class
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
; RUN: llvm-as < %s | llvm-dis | FileCheck %s
|
|
||||||
|
|
||||||
@addr = external global i64
|
|
||||||
|
|
||||||
define i64 @add_plain_ce() {
|
|
||||||
; CHECK: ret i64 add (i64 ptrtoint (i64* @addr to i64), i64 91)
|
|
||||||
ret i64 add (i64 ptrtoint (i64* @addr to i64), i64 91)
|
|
||||||
}
|
|
||||||
|
|
||||||
define i64 @sub_plain_ce() {
|
|
||||||
; CHECK: ret i64 sub (i64 ptrtoint (i64* @addr to i64), i64 91)
|
|
||||||
ret i64 sub (i64 ptrtoint (i64* @addr to i64), i64 91)
|
|
||||||
}
|
|
||||||
|
|
||||||
define i64 @mul_plain_ce() {
|
|
||||||
; CHECK: ret i64 mul (i64 ptrtoint (i64* @addr to i64), i64 91)
|
|
||||||
ret i64 mul (i64 ptrtoint (i64* @addr to i64), i64 91)
|
|
||||||
}
|
|
||||||
|
|
||||||
define i64 @sdiv_plain_ce() {
|
|
||||||
; CHECK: ret i64 sdiv (i64 ptrtoint (i64* @addr to i64), i64 91)
|
|
||||||
ret i64 sdiv (i64 ptrtoint (i64* @addr to i64), i64 91)
|
|
||||||
}
|
|
||||||
|
|
||||||
define i64* @gep_plain_ce() {
|
|
||||||
; CHECK: ret i64* getelementptr (i64* @addr, i64 171)
|
|
||||||
ret i64* getelementptr (i64* @addr, i64 171)
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
; RUN: llvm-as < %s | llvm-dis | FileCheck %s
|
|
||||||
|
|
||||||
@addr = external global i64
|
|
||||||
|
|
||||||
define i64 @add_both_reversed_ce() {
|
|
||||||
; CHECK: ret i64 add nuw nsw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
|
||||||
ret i64 add nsw nuw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
|
||||||
}
|
|
||||||
|
|
||||||
define i64 @sub_both_reversed_ce() {
|
|
||||||
; CHECK: ret i64 sub nuw nsw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
|
||||||
ret i64 sub nsw nuw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
|
||||||
}
|
|
||||||
|
|
||||||
define i64 @mul_both_reversed_ce() {
|
|
||||||
; CHECK: ret i64 mul nuw nsw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
|
||||||
ret i64 mul nsw nuw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
; RUN: llvm-as < %s | llvm-dis | FileCheck %s
|
|
||||||
|
|
||||||
@addr = external global i64
|
|
||||||
|
|
||||||
define i64 @add_signed_ce() {
|
|
||||||
; CHECK: ret i64 add nsw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
|
||||||
ret i64 add nsw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
|
||||||
}
|
|
||||||
|
|
||||||
define i64 @sub_signed_ce() {
|
|
||||||
; CHECK: ret i64 sub nsw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
|
||||||
ret i64 sub nsw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
|
||||||
}
|
|
||||||
|
|
||||||
define i64 @mul_signed_ce() {
|
|
||||||
; CHECK: ret i64 mul nsw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
|
||||||
ret i64 mul nsw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
; RUN: llvm-as < %s | llvm-dis | FileCheck %s
|
|
||||||
|
|
||||||
@addr = external global i64
|
|
||||||
|
|
||||||
define i64 @add_unsigned_ce() {
|
|
||||||
; CHECK: ret i64 add nuw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
|
||||||
ret i64 add nuw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
|
||||||
}
|
|
||||||
|
|
||||||
define i64 @sub_unsigned_ce() {
|
|
||||||
; CHECK: ret i64 sub nuw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
|
||||||
ret i64 sub nuw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
|
||||||
}
|
|
||||||
|
|
||||||
define i64 @mul_unsigned_ce() {
|
|
||||||
; CHECK: ret i64 mul nuw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
|
||||||
ret i64 mul nuw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
|
||||||
}
|
|
@ -141,4 +141,72 @@ define i64* @gep_nw_ce() {
|
|||||||
ret i64* getelementptr inbounds (i64* @addr, i64 171)
|
ret i64* getelementptr inbounds (i64* @addr, i64 171)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define i64 @add_plain_ce() {
|
||||||
|
; CHECK: ret i64 add (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||||
|
ret i64 add (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @sub_plain_ce() {
|
||||||
|
; CHECK: ret i64 sub (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||||
|
ret i64 sub (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @mul_plain_ce() {
|
||||||
|
; CHECK: ret i64 mul (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||||
|
ret i64 mul (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @sdiv_plain_ce() {
|
||||||
|
; CHECK: ret i64 sdiv (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||||
|
ret i64 sdiv (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64* @gep_plain_ce() {
|
||||||
|
; CHECK: ret i64* getelementptr (i64* @addr, i64 171)
|
||||||
|
ret i64* getelementptr (i64* @addr, i64 171)
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @add_both_reversed_ce() {
|
||||||
|
; CHECK: ret i64 add nuw nsw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||||
|
ret i64 add nsw nuw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @sub_both_reversed_ce() {
|
||||||
|
; CHECK: ret i64 sub nuw nsw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||||
|
ret i64 sub nsw nuw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @mul_both_reversed_ce() {
|
||||||
|
; CHECK: ret i64 mul nuw nsw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||||
|
ret i64 mul nsw nuw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @add_signed_ce() {
|
||||||
|
; CHECK: ret i64 add nsw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||||
|
ret i64 add nsw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @sub_signed_ce() {
|
||||||
|
; CHECK: ret i64 sub nsw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||||
|
ret i64 sub nsw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @mul_signed_ce() {
|
||||||
|
; CHECK: ret i64 mul nsw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||||
|
ret i64 mul nsw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @add_unsigned_ce() {
|
||||||
|
; CHECK: ret i64 add nuw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||||
|
ret i64 add nuw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @sub_unsigned_ce() {
|
||||||
|
; CHECK: ret i64 sub nuw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||||
|
ret i64 sub nuw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @mul_unsigned_ce() {
|
||||||
|
; CHECK: ret i64 mul nuw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||||
|
ret i64 mul nuw (i64 ptrtoint (i64* @addr to i64), i64 91)
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user