[PATCH] D14408: [FunctionAttrs] Add handling for operand bundles

Sanjoy Das via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 5 17:29:57 PST 2015


sanjoy created this revision.
sanjoy added reviewers: reames, chandlerc.
sanjoy added a subscriber: llvm-commits.

Teach the FunctionAttrs to do the right thing for IR with operand
bundles.

http://reviews.llvm.org/D14408

Files:
  lib/Transforms/IPO/FunctionAttrs.cpp
  test/Feature/OperandBundles/function-attrs.ll

Index: test/Feature/OperandBundles/function-attrs.ll
===================================================================
--- /dev/null
+++ test/Feature/OperandBundles/function-attrs.ll
@@ -0,0 +1,24 @@
+; RUN: opt -S -functionattrs < %s | FileCheck %s
+
+declare void @f_readonly() readonly
+declare void @f_readnone() readnone
+
+define void @test_0(i32* %x) {
+; FunctionAttrs must not infer readonly / readnone for %x
+
+; CHECK-LABEL: define void @test_0(i32* %x) {
+ entry:
+ ; CHECK: call void @f_readonly() [ "foo"(i32* %x) ]
+  call void @f_readonly() [ "foo"(i32* %x) ]
+  ret void
+}
+
+define void @test_1(i32* %x) {
+; FunctionAttrs must not infer readonly / readnone for %x
+
+; CHECK-LABEL: define void @test_1(i32* %x) {
+ entry:
+ ; CHECK: call void @f_readnone() [ "foo"(i32* %x) ]
+  call void @f_readnone() [ "foo"(i32* %x) ]
+  ret void
+}
Index: lib/Transforms/IPO/FunctionAttrs.cpp
===================================================================
--- lib/Transforms/IPO/FunctionAttrs.cpp
+++ lib/Transforms/IPO/FunctionAttrs.cpp
@@ -328,7 +328,21 @@
     unsigned UseIndex =
         std::distance(const_cast<const Use *>(CS.arg_begin()), U);
 
-    assert(UseIndex < CS.arg_size() && "Non-argument use?");
+    assert(UseIndex < CS.data_operands_size() &&
+           "Indirect function calls should have been filtered above!");
+
+    if (UseIndex >= CS.getNumArgOperands()) {
+      // Data operand, but not a argument operand -- must be a bundle operand
+      assert(CS.hasOperandBundles() && "Must be!");
+
+      // CaptureTracking told us that we're being captured by an operand bundle
+      // use.  In this case it does not matter if the callee is within our SCC
+      // or not -- we've been captured in some unknown way, and we have to be
+      // conservative.
+      Captured = true;
+      return true;
+    }
+
     if (UseIndex >= F->arg_size()) {
       assert(F->isVarArg() && "More params than args in non-varargs call");
       Captured = true;
@@ -443,14 +457,27 @@
 
       unsigned UseIndex = std::distance(CS.arg_begin(), U);
 
-      assert(UseIndex < CS.arg_size() && "Non-argument use?");
-      if (UseIndex >= F->arg_size()) {
+      assert(UseIndex < CS.data_operands_size() && "Non-argument use?");
+
+      bool IsOperandBundleUse = UseIndex >= CS.getNumArgOperands();
+
+      if (UseIndex >= F->arg_size() && !IsOperandBundleUse) {
         assert(F->isVarArg() && "More params than args in non-varargs call");
         return Attribute::None;
       }
 
       Captures &= !CS.doesNotCapture(UseIndex);
-      if (!SCCNodes.count(std::next(F->arg_begin(), UseIndex))) {
+
+      // Since the optimizer (by design) cannot see the data flow corresponding
+      // to a operand bundle use, these cannot participate in the optimistic SCC
+      // analysis.  Instead, we model the operand bundle uses as arguments in
+      // call to a function external to the SCC.
+      if (!SCCNodes.count(std::next(F->arg_begin(), UseIndex)) ||
+          IsOperandBundleUse) {
+
+        // The accessors used on CallSite here do the right thing for calls and
+        // invokes with operand bundles.
+
         if (!CS.onlyReadsMemory() && !CS.onlyReadsMemory(UseIndex))
           return Attribute::None;
         if (!CS.doesNotAccessMemory(UseIndex))


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D14408.39451.patch
Type: text/x-patch
Size: 3307 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20151106/450f9019/attachment.bin>


More information about the llvm-commits mailing list