diff options
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/include/llvm/IR/InstrTypes.h | 29 | ||||
-rw-r--r-- | llvm/include/llvm/IR/Instruction.h | 29 | ||||
-rw-r--r-- | llvm/include/llvm/IR/Operator.h | 4 | ||||
-rw-r--r-- | llvm/lib/IR/Instruction.cpp | 55 | ||||
-rw-r--r-- | llvm/lib/IR/Instructions.cpp | 56 | ||||
-rw-r--r-- | llvm/lib/Transforms/Scalar/EarlyCSE.cpp | 13 | ||||
-rw-r--r-- | llvm/test/Transforms/EarlyCSE/flags.ll | 18 |
7 files changed, 107 insertions, 97 deletions
diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h index 4e85d830d2c..b7446852a0d 100644 --- a/llvm/include/llvm/IR/InstrTypes.h +++ b/llvm/include/llvm/IR/InstrTypes.h @@ -535,35 +535,6 @@ public: /// bool swapOperands(); - /// 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 b = true); - - /// 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 b = true); - - /// 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 b = true); - - /// Determine whether the no unsigned wrap flag is set. - bool hasNoUnsignedWrap() const; - - /// Determine whether the no signed wrap flag is set. - bool hasNoSignedWrap() const; - - /// Determine whether the exact flag is set. - bool isExact() const; - - /// Convenience method to copy supported wrapping, exact, and fast-math flags - /// from V to this instruction. - void copyIRFlags(const Value *V); - - /// Logical 'and' of any supported wrapping, exact, and fast-math flags of - /// V and this instruction. - void andIRFlags(const Value *V); - // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Instruction *I) { return I->isBinaryOp(); diff --git a/llvm/include/llvm/IR/Instruction.h b/llvm/include/llvm/IR/Instruction.h index 12cbcce4c09..e44b23db8cb 100644 --- a/llvm/include/llvm/IR/Instruction.h +++ b/llvm/include/llvm/IR/Instruction.h @@ -223,6 +223,27 @@ public: /// Return the debug location for this node as a DebugLoc. const DebugLoc &getDebugLoc() const { return DbgLoc; } + /// 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 b = true); + + /// 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 b = true); + + /// 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 b = true); + + /// Determine whether the no unsigned wrap flag is set. + bool hasNoUnsignedWrap() const; + + /// Determine whether the no signed wrap flag is set. + bool hasNoSignedWrap() const; + + /// Determine whether the exact flag is set. + bool isExact() const; + /// 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. @@ -281,6 +302,14 @@ public: /// Copy I's fast-math flags void copyFastMathFlags(const Instruction *I); + /// Convenience method to copy supported wrapping, exact, and fast-math flags + /// from V to this instruction. + void copyIRFlags(const Value *V); + + /// Logical 'and' of any supported wrapping, exact, and fast-math flags of + /// V and this instruction. + void andIRFlags(const Value *V); + private: /// Return true if we have an entry in the on-the-side metadata hash. bool hasMetadataHashEntry() const { diff --git a/llvm/include/llvm/IR/Operator.h b/llvm/include/llvm/IR/Operator.h index 50f34665a8e..5880290f3d9 100644 --- a/llvm/include/llvm/IR/Operator.h +++ b/llvm/include/llvm/IR/Operator.h @@ -79,7 +79,7 @@ public: }; private: - friend class BinaryOperator; + friend class Instruction; friend class ConstantExpr; void setHasNoUnsignedWrap(bool B) { SubclassOptionalData = @@ -130,7 +130,7 @@ public: }; private: - friend class BinaryOperator; + friend class Instruction; friend class ConstantExpr; void setIsExact(bool B) { SubclassOptionalData = (SubclassOptionalData & ~IsExact) | (B * IsExact); diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp index 9b996efb5af..dd28b5c506a 100644 --- a/llvm/lib/IR/Instruction.cpp +++ b/llvm/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,37 @@ 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)) { + setHasNoSignedWrap(OB->hasNoSignedWrap()); + setHasNoUnsignedWrap(OB->hasNoUnsignedWrap()); + } + + // Copy the exact flag. + if (auto *PE = dyn_cast<PossiblyExactOperator>(V)) + setIsExact(PE->isExact()); + + // Copy the fast-math flags. + if (auto *FP = dyn_cast<FPMathOperator>(V)) + copyFastMathFlags(FP->getFastMathFlags()); +} + +void Instruction::andIRFlags(const Value *V) { + if (auto *OB = dyn_cast<OverflowingBinaryOperator>(V)) { + setHasNoSignedWrap(hasNoSignedWrap() & OB->hasNoSignedWrap()); + setHasNoUnsignedWrap(hasNoUnsignedWrap() & OB->hasNoUnsignedWrap()); + } + + if (auto *PE = dyn_cast<PossiblyExactOperator>(V)) + setIsExact(isExact() & PE->isExact()); + + if (auto *FP = dyn_cast<FPMathOperator>(V)) { + FastMathFlags FM = getFastMathFlags(); + FM &= FP->getFastMathFlags(); + copyFastMathFlags(FM); + } +} const char *Instruction::getOpcodeName(unsigned OpCode) { switch (OpCode) { diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp index 65703d13ec0..e17db659c2a 100644 --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -2201,62 +2201,6 @@ bool BinaryOperator::swapOperands() { 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<PossiblyExactOperator>(this)->setIsExact(b); -} - -bool BinaryOperator::hasNoUnsignedWrap() const { - return cast<OverflowingBinaryOperator>(this)->hasNoUnsignedWrap(); -} - -bool BinaryOperator::hasNoSignedWrap() const { - return cast<OverflowingBinaryOperator>(this)->hasNoSignedWrap(); -} - -bool BinaryOperator::isExact() const { - return cast<PossiblyExactOperator>(this)->isExact(); -} - -void BinaryOperator::copyIRFlags(const Value *V) { - // Copy the wrapping flags. - if (auto *OB = dyn_cast<OverflowingBinaryOperator>(V)) { - setHasNoSignedWrap(OB->hasNoSignedWrap()); - setHasNoUnsignedWrap(OB->hasNoUnsignedWrap()); - } - - // Copy the exact flag. - if (auto *PE = dyn_cast<PossiblyExactOperator>(V)) - setIsExact(PE->isExact()); - - // Copy the fast-math flags. - if (auto *FP = dyn_cast<FPMathOperator>(V)) - copyFastMathFlags(FP->getFastMathFlags()); -} - -void BinaryOperator::andIRFlags(const Value *V) { - if (auto *OB = dyn_cast<OverflowingBinaryOperator>(V)) { - setHasNoSignedWrap(hasNoSignedWrap() & OB->hasNoSignedWrap()); - setHasNoUnsignedWrap(hasNoUnsignedWrap() & OB->hasNoUnsignedWrap()); - } - - if (auto *PE = dyn_cast<PossiblyExactOperator>(V)) - setIsExact(isExact() & PE->isExact()); - - if (auto *FP = dyn_cast<FPMathOperator>(V)) { - FastMathFlags FM = getFastMathFlags(); - FM &= FP->getFastMathFlags(); - copyFastMathFlags(FM); - } -} - //===----------------------------------------------------------------------===// // FPMathOperator Class diff --git a/llvm/lib/Transforms/Scalar/EarlyCSE.cpp b/llvm/lib/Transforms/Scalar/EarlyCSE.cpp index 7be3aab272d..1d7da48321d 100644 --- a/llvm/lib/Transforms/Scalar/EarlyCSE.cpp +++ b/llvm/lib/Transforms/Scalar/EarlyCSE.cpp @@ -153,7 +153,7 @@ bool DenseMapInfo<SimpleValue>::isEqual(SimpleValue LHS, SimpleValue RHS) { if (LHSI->getOpcode() != RHSI->getOpcode()) return false; - if (LHSI->isIdenticalTo(RHSI)) + if (LHSI->isIdenticalToWhenDefined(RHSI)) return true; // If we're not strictly identical, we still might be a commutable instruction @@ -165,15 +165,6 @@ bool DenseMapInfo<SimpleValue>::isEqual(SimpleValue LHS, SimpleValue RHS) { "same opcode, but different instruction type?"); BinaryOperator *RHSBinOp = cast<BinaryOperator>(RHSI); - // Check overflow attributes - if (isa<OverflowingBinaryOperator>(LHSBinOp)) { - assert(isa<OverflowingBinaryOperator>(RHSBinOp) && - "same opcode, but different operator type?"); - if (LHSBinOp->hasNoUnsignedWrap() != RHSBinOp->hasNoUnsignedWrap() || - LHSBinOp->hasNoSignedWrap() != RHSBinOp->hasNoSignedWrap()) - return false; - } - // Commuted equality return LHSBinOp->getOperand(0) == RHSBinOp->getOperand(1) && LHSBinOp->getOperand(1) == RHSBinOp->getOperand(0); @@ -584,6 +575,8 @@ bool EarlyCSE::processNode(DomTreeNode *Node) { // See if the instruction has an available value. If so, use it. if (Value *V = AvailableValues.lookup(Inst)) { DEBUG(dbgs() << "EarlyCSE CSE: " << *Inst << " to: " << *V << '\n'); + if (auto *I = dyn_cast<Instruction>(V)) + I->andIRFlags(Inst); Inst->replaceAllUsesWith(V); Inst->eraseFromParent(); Changed = true; diff --git a/llvm/test/Transforms/EarlyCSE/flags.ll b/llvm/test/Transforms/EarlyCSE/flags.ll new file mode 100644 index 00000000000..d189012e4be --- /dev/null +++ b/llvm/test/Transforms/EarlyCSE/flags.ll @@ -0,0 +1,18 @@ +; RUN: opt -early-cse -S < %s | FileCheck %s + +declare void @use(i1) + +define void @test1(float %x, float %y) { +entry: + %cmp1 = fcmp nnan oeq float %y, %x + %cmp2 = fcmp oeq float %x, %y + call void @use(i1 %cmp1) + call void @use(i1 %cmp2) + ret void +} + +; CHECK-LABEL: define void @test1( +; CHECK: %[[cmp:.*]] = fcmp oeq float %y, %x +; CHECK-NEXT: call void @use(i1 %[[cmp]]) +; CHECK-NEXT: call void @use(i1 %[[cmp]]) +; CHECK-NEXT: ret void |