summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/IR/CallSite.h40
-rw-r--r--llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp4
-rw-r--r--llvm/test/Transforms/DeadArgElim/operandbundle.ll12
3 files changed, 52 insertions, 4 deletions
diff --git a/llvm/include/llvm/IR/CallSite.h b/llvm/include/llvm/IR/CallSite.h
index 7d9902f944e..a0ff2cb6c7e 100644
--- a/llvm/include/llvm/IR/CallSite.h
+++ b/llvm/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/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp b/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp
index e81c83e6b0c..4de3d95ab11 100644
--- a/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp
+++ b/llvm/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/llvm/test/Transforms/DeadArgElim/operandbundle.ll b/llvm/test/Transforms/DeadArgElim/operandbundle.ll
new file mode 100644
index 00000000000..aa112b1c050
--- /dev/null
+++ b/llvm/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()
OpenPOWER on IntegriCloud