summaryrefslogtreecommitdiff
path: root/lib/IR/Instruction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/IR/Instruction.cpp')
-rw-r--r--lib/IR/Instruction.cpp94
1 files changed, 82 insertions, 12 deletions
diff --git a/lib/IR/Instruction.cpp b/lib/IR/Instruction.cpp
index 4b33d2e66ea19..ed08f85c60b6d 100644
--- a/lib/IR/Instruction.cpp
+++ b/lib/IR/Instruction.cpp
@@ -96,6 +96,30 @@ void Instruction::moveBefore(Instruction *MovePos) {
MovePos->getIterator(), getParent()->getInstList(), getIterator());
}
+void Instruction::setHasNoUnsignedWrap(bool b) {
+ cast<OverflowingBinaryOperator>(this)->setHasNoUnsignedWrap(b);
+}
+
+void Instruction::setHasNoSignedWrap(bool b) {
+ cast<OverflowingBinaryOperator>(this)->setHasNoSignedWrap(b);
+}
+
+void Instruction::setIsExact(bool b) {
+ cast<PossiblyExactOperator>(this)->setIsExact(b);
+}
+
+bool Instruction::hasNoUnsignedWrap() const {
+ return cast<OverflowingBinaryOperator>(this)->hasNoUnsignedWrap();
+}
+
+bool Instruction::hasNoSignedWrap() const {
+ return cast<OverflowingBinaryOperator>(this)->hasNoSignedWrap();
+}
+
+bool Instruction::isExact() const {
+ return cast<PossiblyExactOperator>(this)->isExact();
+}
+
/// Set or clear the unsafe-algebra flag on this instruction, which must be an
/// operator which supports this flag. See LangRef.html for the meaning of this
/// flag.
@@ -190,6 +214,54 @@ void Instruction::copyFastMathFlags(const Instruction *I) {
copyFastMathFlags(I->getFastMathFlags());
}
+void Instruction::copyIRFlags(const Value *V) {
+ // Copy the wrapping flags.
+ if (auto *OB = dyn_cast<OverflowingBinaryOperator>(V)) {
+ if (isa<OverflowingBinaryOperator>(this)) {
+ setHasNoSignedWrap(OB->hasNoSignedWrap());
+ setHasNoUnsignedWrap(OB->hasNoUnsignedWrap());
+ }
+ }
+
+ // Copy the exact flag.
+ if (auto *PE = dyn_cast<PossiblyExactOperator>(V))
+ if (isa<PossiblyExactOperator>(this))
+ setIsExact(PE->isExact());
+
+ // Copy the fast-math flags.
+ if (auto *FP = dyn_cast<FPMathOperator>(V))
+ if (isa<FPMathOperator>(this))
+ copyFastMathFlags(FP->getFastMathFlags());
+
+ if (auto *SrcGEP = dyn_cast<GetElementPtrInst>(V))
+ if (auto *DestGEP = dyn_cast<GetElementPtrInst>(this))
+ DestGEP->setIsInBounds(SrcGEP->isInBounds() | DestGEP->isInBounds());
+}
+
+void Instruction::andIRFlags(const Value *V) {
+ if (auto *OB = dyn_cast<OverflowingBinaryOperator>(V)) {
+ if (isa<OverflowingBinaryOperator>(this)) {
+ setHasNoSignedWrap(hasNoSignedWrap() & OB->hasNoSignedWrap());
+ setHasNoUnsignedWrap(hasNoUnsignedWrap() & OB->hasNoUnsignedWrap());
+ }
+ }
+
+ if (auto *PE = dyn_cast<PossiblyExactOperator>(V))
+ if (isa<PossiblyExactOperator>(this))
+ setIsExact(isExact() & PE->isExact());
+
+ if (auto *FP = dyn_cast<FPMathOperator>(V)) {
+ if (isa<FPMathOperator>(this)) {
+ FastMathFlags FM = getFastMathFlags();
+ FM &= FP->getFastMathFlags();
+ copyFastMathFlags(FM);
+ }
+ }
+
+ if (auto *SrcGEP = dyn_cast<GetElementPtrInst>(V))
+ if (auto *DestGEP = dyn_cast<GetElementPtrInst>(this))
+ DestGEP->setIsInBounds(SrcGEP->isInBounds() & DestGEP->isInBounds());
+}
const char *Instruction::getOpcodeName(unsigned OpCode) {
switch (OpCode) {
@@ -271,13 +343,18 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
}
}
-/// Return true if both instructions have the same special state
-/// This must be kept in sync with lib/Transforms/IPO/MergeFunctions.cpp.
+/// Return true if both instructions have the same special state This must be
+/// kept in sync with FunctionComparator::cmpOperations in
+/// lib/Transforms/IPO/MergeFunctions.cpp.
static bool haveSameSpecialState(const Instruction *I1, const Instruction *I2,
bool IgnoreAlignment = false) {
assert(I1->getOpcode() == I2->getOpcode() &&
"Can not compare special state of different instructions");
+ if (const AllocaInst *AI = dyn_cast<AllocaInst>(I1))
+ return AI->getAllocatedType() == cast<AllocaInst>(I2)->getAllocatedType() &&
+ (AI->getAlignment() == cast<AllocaInst>(I2)->getAlignment() ||
+ IgnoreAlignment);
if (const LoadInst *LI = dyn_cast<LoadInst>(I1))
return LI->isVolatile() == cast<LoadInst>(I2)->isVolatile() &&
(LI->getAlignment() == cast<LoadInst>(I2)->getAlignment() ||
@@ -360,8 +437,7 @@ bool Instruction::isIdenticalToWhenDefined(const Instruction *I) const {
return haveSameSpecialState(this, I);
}
-// isSameOperationAs
-// This should be kept in sync with isEquivalentOperation in
+// Keep this in sync with FunctionComparator::cmpOperations in
// lib/Transforms/IPO/MergeFunctions.cpp.
bool Instruction::isSameOperationAs(const Instruction *I,
unsigned flags) const {
@@ -461,9 +537,9 @@ bool Instruction::isAtomic() const {
case Instruction::Fence:
return true;
case Instruction::Load:
- return cast<LoadInst>(this)->getOrdering() != NotAtomic;
+ return cast<LoadInst>(this)->getOrdering() != AtomicOrdering::NotAtomic;
case Instruction::Store:
- return cast<StoreInst>(this)->getOrdering() != NotAtomic;
+ return cast<StoreInst>(this)->getOrdering() != AtomicOrdering::NotAtomic;
}
}
@@ -477,12 +553,6 @@ bool Instruction::mayThrow() const {
return isa<ResumeInst>(this);
}
-bool Instruction::mayReturn() const {
- if (const CallInst *CI = dyn_cast<CallInst>(this))
- return !CI->doesNotReturn();
- return true;
-}
-
/// isAssociative - Return true if the instruction is associative:
///
/// Associative operators satisfy: x op (y op z) === (x op y) op z