[llvm] r254118 - [OperandBundles] Treat "deopt" operand bundles specially

Sanjoy Das via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 25 17:16:05 PST 2015


Author: sanjoy
Date: Wed Nov 25 19:16:05 2015
New Revision: 254118

URL: http://llvm.org/viewvc/llvm-project?rev=254118&view=rev
Log:
[OperandBundles] Treat "deopt" operand bundles specially

Teach LLVM optimize to more precisely in the presence of "deopt" operand
bundles.  "deopt" operand bundles imply that the call they're attached
to is at least `readonly` (i.e. they don't imply clobber semantics), and
they don't capture their bundle operands.

Modified:
    llvm/trunk/include/llvm/IR/InstrTypes.h
    llvm/trunk/test/Feature/OperandBundles/adce.ll
    llvm/trunk/test/Feature/OperandBundles/basic-aa-argmemonly.ll
    llvm/trunk/test/Feature/OperandBundles/dse.ll
    llvm/trunk/test/Feature/OperandBundles/early-cse.ll
    llvm/trunk/test/Feature/OperandBundles/function-attrs.ll

Modified: llvm/trunk/include/llvm/IR/InstrTypes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/InstrTypes.h?rev=254118&r1=254117&r2=254118&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/InstrTypes.h (original)
+++ llvm/trunk/include/llvm/IR/InstrTypes.h Wed Nov 25 19:16:05 2015
@@ -21,6 +21,7 @@
 #include "llvm/IR/Attributes.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Instruction.h"
+#include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/OperandTraits.h"
 
 namespace llvm {
@@ -1126,6 +1127,9 @@ struct OperandBundleUse {
   /// Currently there is no way to have attributes on operand bundles differ on
   /// a per operand granularity.
   bool operandsHaveAttr(Attribute::AttrKind A) const {
+    if (isDeoptOperandBundle())
+      return A == Attribute::ReadOnly || A == Attribute::NoCapture;
+
     // Conservative answer:  no operands have any attributes.
     return false;
   };
@@ -1144,6 +1148,11 @@ struct OperandBundleUse {
     return Tag->getValue();
   }
 
+  /// \brief Return true if this is a "deopt" operand bundle.
+  bool isDeoptOperandBundle() const {
+    return getTagID() == LLVMContext::OB_deopt;
+  }
+
 private:
   /// \brief Pointer to an entry in LLVMContextImpl::getOrInsertBundleTag.
   StringMapEntry<uint32_t> *Tag;
@@ -1361,10 +1370,16 @@ public:
   /// \brief Return true if this operand bundle user has operand bundles that
   /// may write to the heap.
   bool hasClobberingOperandBundles() const {
-    // Implementation note: this is a conservative implementation of operand
-    // bundle semantics, where *any* operand bundle forces a callsite to be
-    // read-write.
-    return hasOperandBundles();
+    for (auto &BOI : bundle_op_infos()) {
+      if (BOI.Tag->second == LLVMContext::OB_deopt)
+        continue;
+
+      // This instruction has an operand bundle that is not a "deopt" operand
+      // bundle.  Assume the worst.
+      return true;
+    }
+
+    return false;
   }
 
 protected:

Modified: llvm/trunk/test/Feature/OperandBundles/adce.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Feature/OperandBundles/adce.ll?rev=254118&r1=254117&r2=254118&view=diff
==============================================================================
--- llvm/trunk/test/Feature/OperandBundles/adce.ll (original)
+++ llvm/trunk/test/Feature/OperandBundles/adce.ll Wed Nov 25 19:16:05 2015
@@ -39,3 +39,11 @@ define void @test3() {
   call void @readnone_function() readnone [ "tag"() ]
   ret void
 }
+
+define void @test4() {
+; CHECK-LABEL: @test4(
+ entry:
+; CHECK-NOT: @readonly_function()
+  call void @readonly_function() [ "deopt"() ]
+  ret void
+}

Modified: llvm/trunk/test/Feature/OperandBundles/basic-aa-argmemonly.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Feature/OperandBundles/basic-aa-argmemonly.ll?rev=254118&r1=254117&r2=254118&view=diff
==============================================================================
--- llvm/trunk/test/Feature/OperandBundles/basic-aa-argmemonly.ll (original)
+++ llvm/trunk/test/Feature/OperandBundles/basic-aa-argmemonly.ll Wed Nov 25 19:16:05 2015
@@ -26,3 +26,26 @@ define i32 @test1(i32* %P, i32* noalias
   ret i32 %diff
 ; CHECK: ret i32 0
 }
+
+define i32 @test2(i32* %P, i32* noalias %P2) {
+; Note: in this test we //can// GVN %v1 and %v2 into one value in theory.  Calls
+; with deopt operand bundles are not argmemonly because they *read* the entire
+; heap, but they don't write to any location in the heap if the callee does not
+; deoptimize the caller.  This fact, combined with the fact that
+; @argmemonly_function is, well, an argmemonly function, can be used to conclude
+; that %P is not written to at the callsite.  However LLVM currently cannot
+; describe the "does not write to non-args, and reads the entire heap" effect on
+; a callsite.
+
+; CHECK-LABEL: @test2(
+  %v1 = load i32, i32* %P
+; CHECK: %v1 = load i32, i32* %P
+  call void @argmemonly_function(i32* %P2) [ "deopt"() ]
+; CHECK: call void @argmemonly_function(
+  %v2 = load i32, i32* %P
+; CHECK: %v2 = load i32, i32* %P
+  %diff = sub i32 %v1, %v2
+; CHECK: %diff = sub i32 %v1, %v2
+  ret i32 %diff
+; CHECK: ret i32 %diff
+}

Modified: llvm/trunk/test/Feature/OperandBundles/dse.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Feature/OperandBundles/dse.ll?rev=254118&r1=254117&r2=254118&view=diff
==============================================================================
--- llvm/trunk/test/Feature/OperandBundles/dse.ll (original)
+++ llvm/trunk/test/Feature/OperandBundles/dse.ll Wed Nov 25 19:16:05 2015
@@ -27,3 +27,36 @@ define i8* @test_1() {
 
   ret i8* %m
 }
+
+define void @test_2() {
+; Since the deopt operand bundle does not escape %m (see caveat below), it is
+; legal to elide the final store that location.
+
+; CHECK-LABEL: @test_2(
+  %m = call i8* @malloc(i32 24)
+  tail call void @f() [ "deopt"(i8* %m) ]
+  store i8 -19, i8* %m
+  ret void
+
+; CHECK:  tail call void @f() [ "deopt"(i8* %m) ]
+; CHECK-NEXT  ret void
+}
+
+define i8* @test_3() {
+; Since the deopt operand bundle does not escape %m (see caveat below), @f
+; cannot observe the stores to %m
+
+; CHECK-LABEL: @test_3(
+  %m = call i8* @malloc(i32 24)
+  tail call void @f() [ "deopt"(i8* %m) ]
+  store i8 -19, i8* %m
+  tail call void @f()
+  store i8 101, i8* %m
+  ret i8* %m
+}
+
+
+; Caveat: technically, %m can only escape if the calling function is deoptimized
+; at the call site (i.e. the call returns to the "deopt" continuation).  Since
+; the calling function body will be invalidated in that case, the calling
+; function can be optimized under the assumption that %m does not escape.

Modified: llvm/trunk/test/Feature/OperandBundles/early-cse.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Feature/OperandBundles/early-cse.ll?rev=254118&r1=254117&r2=254118&view=diff
==============================================================================
--- llvm/trunk/test/Feature/OperandBundles/early-cse.ll (original)
+++ llvm/trunk/test/Feature/OperandBundles/early-cse.ll Wed Nov 25 19:16:05 2015
@@ -2,8 +2,8 @@
 
 ; While it is normally okay to do memory optimizations over calls to
 ; @readonly_function and @readnone_function, we cannot do that if
-; they're carrying operand bundles since the presence of unknown
-; operand bundles implies arbitrary memory effects.
+; they're carrying unknown operand bundles since the presence of
+; unknown operand bundles implies arbitrary memory effects.
 
 declare void @readonly_function() readonly nounwind
 declare void @readnone_function() readnone nounwind
@@ -69,3 +69,21 @@ define void @test5(i32* %x) {
 ; CHECK: store i32 200, i32* %x
   ret void
 }
+
+define void @test6(i32* %x) {
+; The "deopt" operand bundle does not make the call to
+; @readonly_function read-write; and so the nounwind readonly call can
+; be deleted.
+
+; CHECK-LABEL: @test6(
+ entry:
+
+; CHECK-NEXT: entry:
+; CHECK-NEXT:  store i32 200, i32* %x
+; CHECK-NEXT:  ret void
+
+  store i32 100, i32* %x
+  call void @readonly_function() [ "deopt"() ]
+  store i32 200, i32* %x
+  ret void
+}

Modified: llvm/trunk/test/Feature/OperandBundles/function-attrs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Feature/OperandBundles/function-attrs.ll?rev=254118&r1=254117&r2=254118&view=diff
==============================================================================
--- llvm/trunk/test/Feature/OperandBundles/function-attrs.ll (original)
+++ llvm/trunk/test/Feature/OperandBundles/function-attrs.ll Wed Nov 25 19:16:05 2015
@@ -22,3 +22,12 @@ define void @test_1(i32* %x) {
   call void @f_readnone() [ "foo"(i32* %x) ]
   ret void
 }
+
+define void @test_2(i32* %x) {
+; The "deopt" operand bundle does not capture or write to %x.
+
+; CHECK-LABEL: define void @test_2(i32* nocapture readonly %x)
+ entry:
+  call void @f_readonly() [ "deopt"(i32* %x) ]
+  ret void
+}




More information about the llvm-commits mailing list