Teach haveSameSpecialState about operand bundles
authorSanjoy Das <sanjoy@playingwithpointers.com>
Mon, 14 Dec 2015 19:11:35 +0000 (19:11 +0000)
committerSanjoy Das <sanjoy@playingwithpointers.com>
Mon, 14 Dec 2015 19:11:35 +0000 (19:11 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@255527 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/IR/InstrTypes.h
lib/IR/Instruction.cpp
test/Feature/OperandBundles/special-state.ll [new file with mode: 0644]

index d5a6b6b2fb215375aae420ad3630cc0fb4eed049..5173658b5218129b680bd18a4b351183965ec043 100644 (file)
@@ -1447,6 +1447,18 @@ public:
     return OBU.operandHasAttr(OpIdx - BOI.Begin, A);
   }
 
+  /// \brief Return true if \p Other has the same sequence of operand bundle
+  /// tags with the same number of operands on each one of them as this
+  /// OperandBundleUser.
+  bool hasIdenticalOperandBundleSchema(
+      const OperandBundleUser<InstrTy, OpIteratorTy> &Other) const {
+    if (getNumOperandBundles() != Other.getNumOperandBundles())
+      return false;
+
+    return std::equal(bundle_op_info_begin(), bundle_op_info_end(),
+                      Other.bundle_op_info_begin());
+  };
+
 protected:
   /// \brief Is the function attribute S disallowed by some operand bundle on
   /// this operand bundle user?
@@ -1490,6 +1502,10 @@ protected:
     /// \brief The index in the Use& vector where operands for this operand
     /// bundle ends.
     uint32_t End;
+
+    bool operator==(const BundleOpInfo &Other) const {
+      return Tag == Other.Tag && Begin == Other.Begin && End == Other.End;
+    }
   };
 
   /// \brief Simple helper function to map a BundleOpInfo to an
index c219121104b4ff606e4b12e9820d5dc5d05d22be..a0bd2c9698e8d55a03e2631ec9e9ee54f621e441 100644 (file)
@@ -296,11 +296,12 @@ static bool haveSameSpecialState(const Instruction *I1, const Instruction *I2,
   if (const CallInst *CI = dyn_cast<CallInst>(I1))
     return CI->isTailCall() == cast<CallInst>(I2)->isTailCall() &&
            CI->getCallingConv() == cast<CallInst>(I2)->getCallingConv() &&
-           CI->getAttributes() == cast<CallInst>(I2)->getAttributes();
+           CI->getAttributes() == cast<CallInst>(I2)->getAttributes() &&
+           CI->hasIdenticalOperandBundleSchema(*cast<CallInst>(I2));
   if (const InvokeInst *CI = dyn_cast<InvokeInst>(I1))
     return CI->getCallingConv() == cast<InvokeInst>(I2)->getCallingConv() &&
-           CI->getAttributes() ==
-             cast<InvokeInst>(I2)->getAttributes();
+           CI->getAttributes() == cast<InvokeInst>(I2)->getAttributes() &&
+           CI->hasIdenticalOperandBundleSchema(*cast<InvokeInst>(I2));
   if (const InsertValueInst *IVI = dyn_cast<InsertValueInst>(I1))
     return IVI->getIndices() == cast<InsertValueInst>(I2)->getIndices();
   if (const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(I1))
diff --git a/test/Feature/OperandBundles/special-state.ll b/test/Feature/OperandBundles/special-state.ll
new file mode 100644 (file)
index 0000000..56e337c
--- /dev/null
@@ -0,0 +1,21 @@
+; RUN: opt -S -early-cse < %s | FileCheck %s
+
+; This test isn't directly related to EarlyCSE or varargs.  It is just
+; using these as a vehicle for testing the correctness of
+; haveSameSpecialState around operand bundles.
+
+declare i32 @foo(...)
+
+define i32 @f() {
+; CHECK-LABEL: @f(
+ entry:
+; CHECK: %v0 = call i32 (...) @foo(
+; CHECK: %v1 = call i32 (...) @foo(
+; CHECK: %v = add i32 %v0, %v1
+; CHECK: ret i32 %v
+
+  %v0 = call i32 (...) @foo(i32 10) readonly [ "foo"(i32 20) ]
+  %v1 = call i32 (...) @foo() readonly [ "foo"(i32 10, i32 20) ]
+  %v = add i32 %v0, %v1
+  ret i32 %v
+}