diff options
-rw-r--r-- | llvm/include/llvm/IR/CallSite.h | 4 | ||||
-rw-r--r-- | llvm/include/llvm/IR/InstrTypes.h | 6 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 11 | ||||
-rw-r--r-- | llvm/test/Transforms/SimplifyCFG/sink-common-code.ll | 26 |
4 files changed, 46 insertions, 1 deletions
diff --git a/llvm/include/llvm/IR/CallSite.h b/llvm/include/llvm/IR/CallSite.h index e9d803a0ada..f8f31f6608e 100644 --- a/llvm/include/llvm/IR/CallSite.h +++ b/llvm/include/llvm/IR/CallSite.h @@ -512,6 +512,10 @@ public: CALLSITE_DELEGATE_GETTER(countOperandBundlesOfType(ID)); } + bool isBundleOperand(unsigned Idx) const { + CALLSITE_DELEGATE_GETTER(isBundleOperand(Idx)); + } + IterTy arg_begin() const { CALLSITE_DELEGATE_GETTER(arg_begin()); } diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h index 0abff7d1b8e..282e0637f8a 100644 --- a/llvm/include/llvm/IR/InstrTypes.h +++ b/llvm/include/llvm/IR/InstrTypes.h @@ -1337,6 +1337,12 @@ public: return bundle_op_info_end()[-1].End; } + /// Return true if the operand at index \p Idx is a bundle operand. + bool isBundleOperand(unsigned Idx) const { + return hasOperandBundles() && Idx >= getBundleOperandsStartIndex() && + Idx < getBundleOperandsEndIndex(); + } + /// \brief Return the total number operands (not operand bundles) used by /// every operand bundle in this OperandBundleUser. unsigned getNumTotalBundleOperands() const { diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index 63b9f4061f2..a45a0c75b46 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -1362,7 +1362,16 @@ static bool canReplaceOperandWithVariable(const Instruction *I, // FIXME: many arithmetic intrinsics have no issue taking a // variable, however it's hard to distingish these from // specials such as @llvm.frameaddress that require a constant. - return !isa<IntrinsicInst>(I); + if (isa<IntrinsicInst>(I)) + return false; + + // Constant bundle operands may need to retain their constant-ness for + // correctness. + if (ImmutableCallSite(I).isBundleOperand(OpIdx)) + return false; + + return true; + case Instruction::ShuffleVector: // Shufflevector masks are constant. return OpIdx != 2; diff --git a/llvm/test/Transforms/SimplifyCFG/sink-common-code.ll b/llvm/test/Transforms/SimplifyCFG/sink-common-code.ll index 54f87052c7a..a2639d89f82 100644 --- a/llvm/test/Transforms/SimplifyCFG/sink-common-code.ll +++ b/llvm/test/Transforms/SimplifyCFG/sink-common-code.ll @@ -755,6 +755,32 @@ if.end: ; CHECK-NOT: exact ; CHECK: } +declare i32 @call_target() + +define void @test_operand_bundles(i1 %cond, i32* %ptr) { +entry: + br i1 %cond, label %left, label %right + +left: + %val0 = call i32 @call_target() [ "deopt"(i32 10) ] + store i32 %val0, i32* %ptr + br label %merge + +right: + %val1 = call i32 @call_target() [ "deopt"(i32 20) ] + store i32 %val1, i32* %ptr + br label %merge + +merge: + ret void +} + +; CHECK-LABEL: @test_operand_bundles( +; CHECK: left: +; CHECK-NEXT: %val0 = call i32 @call_target() [ "deopt"(i32 10) ] +; CHECK: right: +; CHECK-NEXT: %val1 = call i32 @call_target() [ "deopt"(i32 20) ] + ; CHECK: !0 = !{!1, !1, i64 0} ; CHECK: !1 = !{!"float", !2} ; CHECK: !2 = !{!"an example type tree"} |