[OperandBundles] Have DeadArgElim play nice with operand bundles
authorDavid Majnemer <david.majnemer@gmail.com>
Wed, 23 Dec 2015 09:58:36 +0000 (09:58 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Wed, 23 Dec 2015 09:58:36 +0000 (09:58 +0000)
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

include/llvm/IR/CallSite.h
lib/Transforms/IPO/DeadArgumentElimination.cpp
test/Transforms/DeadArgElim/operandbundle.ll [new file with mode: 0644]

index 7d9902f..a0ff2cb 100644 (file)
@@ -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());
   }
 
index e81c83e..4de3d95 100644 (file)
@@ -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 (file)
index 0000000..aa112b1
--- /dev/null
@@ -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()