diff options
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/lib/IR/Instruction.cpp | 29 | ||||
-rw-r--r-- | llvm/lib/Transforms/Scalar/GVN.cpp | 43 | ||||
-rw-r--r-- | llvm/test/Transforms/GVN/flags.ll | 18 |
3 files changed, 58 insertions, 32 deletions
diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp index dd28b5c506a..f90ebec06bd 100644 --- a/llvm/lib/IR/Instruction.cpp +++ b/llvm/lib/IR/Instruction.cpp @@ -217,32 +217,41 @@ void Instruction::copyFastMathFlags(const Instruction *I) { void Instruction::copyIRFlags(const Value *V) { // Copy the wrapping flags. if (auto *OB = dyn_cast<OverflowingBinaryOperator>(V)) { - setHasNoSignedWrap(OB->hasNoSignedWrap()); - setHasNoUnsignedWrap(OB->hasNoUnsignedWrap()); + if (isa<OverflowingBinaryOperator>(this)) { + setHasNoSignedWrap(OB->hasNoSignedWrap()); + setHasNoUnsignedWrap(OB->hasNoUnsignedWrap()); + } } // Copy the exact flag. if (auto *PE = dyn_cast<PossiblyExactOperator>(V)) - setIsExact(PE->isExact()); + if (isa<PossiblyExactOperator>(this)) + setIsExact(PE->isExact()); // Copy the fast-math flags. if (auto *FP = dyn_cast<FPMathOperator>(V)) - copyFastMathFlags(FP->getFastMathFlags()); + if (isa<FPMathOperator>(this)) + 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 (isa<OverflowingBinaryOperator>(this)) { + setHasNoSignedWrap(hasNoSignedWrap() & OB->hasNoSignedWrap()); + setHasNoUnsignedWrap(hasNoUnsignedWrap() & OB->hasNoUnsignedWrap()); + } } if (auto *PE = dyn_cast<PossiblyExactOperator>(V)) - setIsExact(isExact() & PE->isExact()); + if (isa<PossiblyExactOperator>(this)) + setIsExact(isExact() & PE->isExact()); if (auto *FP = dyn_cast<FPMathOperator>(V)) { - FastMathFlags FM = getFastMathFlags(); - FM &= FP->getFastMathFlags(); - copyFastMathFlags(FM); + if (isa<FPMathOperator>(this)) { + FastMathFlags FM = getFastMathFlags(); + FM &= FP->getFastMathFlags(); + copyFastMathFlags(FM); + } } } diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp index 02e18abd332..2d4af732520 100644 --- a/llvm/lib/Transforms/Scalar/GVN.cpp +++ b/llvm/lib/Transforms/Scalar/GVN.cpp @@ -1725,30 +1725,29 @@ bool GVN::processAssumeIntrinsic(IntrinsicInst *IntrinsicI) { } static void patchReplacementInstruction(Instruction *I, Value *Repl) { + auto *ReplInst = dyn_cast<Instruction>(Repl); + if (!ReplInst) + return; + // Patch the replacement so that it is not more restrictive than the value // being replaced. - BinaryOperator *Op = dyn_cast<BinaryOperator>(I); - BinaryOperator *ReplOp = dyn_cast<BinaryOperator>(Repl); - if (Op && ReplOp) - ReplOp->andIRFlags(Op); - - if (Instruction *ReplInst = dyn_cast<Instruction>(Repl)) { - // FIXME: If both the original and replacement value are part of the - // same control-flow region (meaning that the execution of one - // guarantees the execution of the other), then we can combine the - // noalias scopes here and do better than the general conservative - // answer used in combineMetadata(). - - // In general, GVN unifies expressions over different control-flow - // regions, and so we need a conservative combination of the noalias - // scopes. - static const unsigned KnownIDs[] = { - LLVMContext::MD_tbaa, LLVMContext::MD_alias_scope, - LLVMContext::MD_noalias, LLVMContext::MD_range, - LLVMContext::MD_fpmath, LLVMContext::MD_invariant_load, - LLVMContext::MD_invariant_group}; - combineMetadata(ReplInst, I, KnownIDs); - } + ReplInst->andIRFlags(I); + + // FIXME: If both the original and replacement value are part of the + // same control-flow region (meaning that the execution of one + // guarantees the execution of the other), then we can combine the + // noalias scopes here and do better than the general conservative + // answer used in combineMetadata(). + + // In general, GVN unifies expressions over different control-flow + // regions, and so we need a conservative combination of the noalias + // scopes. + static const unsigned KnownIDs[] = { + LLVMContext::MD_tbaa, LLVMContext::MD_alias_scope, + LLVMContext::MD_noalias, LLVMContext::MD_range, + LLVMContext::MD_fpmath, LLVMContext::MD_invariant_load, + LLVMContext::MD_invariant_group}; + combineMetadata(ReplInst, I, KnownIDs); } static void patchAndReplaceAllUsesWith(Instruction *I, Value *Repl) { diff --git a/llvm/test/Transforms/GVN/flags.ll b/llvm/test/Transforms/GVN/flags.ll new file mode 100644 index 00000000000..1b44905bb5c --- /dev/null +++ b/llvm/test/Transforms/GVN/flags.ll @@ -0,0 +1,18 @@ +; RUN: opt -gvn -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 |