From: David Majnemer Date: Wed, 23 Dec 2015 09:58:36 +0000 (+0000) Subject: [OperandBundles] Have DeadArgElim play nice with operand bundles X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=688b5df9e2910ecb5ec5c053b8b4365576d6a5aa [OperandBundles] Have DeadArgElim play nice with operand bundles A call site's use of a Value might not correspond to an argument operand but to a bundle operand. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@256326 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/IR/CallSite.h b/include/llvm/IR/CallSite.h index 7d9902f944e..a0ff2cb6c7e 100644 --- a/include/llvm/IR/CallSite.h +++ b/include/llvm/IR/CallSite.h @@ -118,6 +118,31 @@ public: /// Determine whether this Use is the callee operand's Use. bool isCallee(const Use *U) const { return getCallee() == U; } + /// \brief Determine whether the passed iterator points to an argument + /// operand. + bool isArgOperand(Value::const_user_iterator UI) const { + return isArgOperand(&UI.getUse()); + } + + /// \brief Determine whether the passed use points to an argument operand. + bool isArgOperand(const Use *U) const { + return arg_begin() <= U && U < arg_end(); + } + + /// \brief Determine whether the passed iterator points to a bundle operand. + bool isBundleOperand(Value::const_user_iterator UI) const { + return isBundleOperand(&UI.getUse()); + } + + /// \brief Determine whether the passed use points to a bundle operand. + bool isBundleOperand(const Use *U) const { + if (!hasOperandBundles()) + return false; + unsigned OperandNo = U->getOperandNo(); + return getBundleOperandsStartIndex() <= OperandNo && + OperandNo < getBundleOperandsEndIndex(); + } + ValTy *getArgument(unsigned ArgNo) const { assert(arg_begin() + ArgNo < arg_end() && "Argument # out of range!"); return *(arg_begin() + ArgNo); @@ -139,8 +164,7 @@ public: /// it. unsigned getArgumentNo(const Use *U) const { assert(getInstruction() && "Not a call or invoke instruction!"); - assert(arg_begin() <= U && U < arg_end() - && "Argument # out of range!"); + assert(isArgOperand(U) && "Argument # out of range!"); return U - arg_begin(); } @@ -354,7 +378,7 @@ public: CALLSITE_DELEGATE_SETTER(setDoesNotThrow()); } - int getNumOperandBundles() const { + unsigned getNumOperandBundles() const { CALLSITE_DELEGATE_GETTER(getNumOperandBundles()); } @@ -362,7 +386,15 @@ public: CALLSITE_DELEGATE_GETTER(hasOperandBundles()); } - int getNumTotalBundleOperands() const { + unsigned getBundleOperandsStartIndex() const { + CALLSITE_DELEGATE_GETTER(getBundleOperandsStartIndex()); + } + + unsigned getBundleOperandsEndIndex() const { + CALLSITE_DELEGATE_GETTER(getBundleOperandsEndIndex()); + } + + unsigned getNumTotalBundleOperands() const { CALLSITE_DELEGATE_GETTER(getNumTotalBundleOperands()); } diff --git a/lib/Transforms/IPO/DeadArgumentElimination.cpp b/lib/Transforms/IPO/DeadArgumentElimination.cpp index e81c83e6b0c..4de3d95ab11 100644 --- a/lib/Transforms/IPO/DeadArgumentElimination.cpp +++ b/lib/Transforms/IPO/DeadArgumentElimination.cpp @@ -480,6 +480,10 @@ DAE::Liveness DAE::SurveyUse(const Use *U, if (F) { // Used in a direct call. + // The function argument is live if it is used as a bundle operand. + if (CS.isBundleOperand(U)) + return Live; + // Find the argument number. We know for sure that this use is an // argument, since if it was the function argument this would be an // indirect call and the we know can't be looking at a value of the diff --git a/test/Transforms/DeadArgElim/operandbundle.ll b/test/Transforms/DeadArgElim/operandbundle.ll new file mode 100644 index 00000000000..aa112b1c050 --- /dev/null +++ b/test/Transforms/DeadArgElim/operandbundle.ll @@ -0,0 +1,12 @@ +; RUN: opt < %s -deadargelim -S | FileCheck %s + +define internal void @f(i32 %arg) { +entry: + call void @g() [ "foo"(i32 %arg) ] + ret void +} + +; CHECK-LABEL: define internal void @f( +; CHECK: call void @g() [ "foo"(i32 %arg) ] + +declare void @g()