[FunctionAttrs] Fix SCC logic around operand bundles
authorSanjoy Das <sanjoy@playingwithpointers.com>
Tue, 9 Feb 2016 18:40:40 +0000 (18:40 +0000)
committerSanjoy Das <sanjoy@playingwithpointers.com>
Tue, 9 Feb 2016 18:40:40 +0000 (18:40 +0000)
FunctionAttrs does an "optimistic" analysis of SCCs as a unit, which
means normally it is able to disregard calls from an SCC into itself.
However, calls and invokes with operand bundles are allowed to have
memory effects not fully described by the memory effects on the call
target, so we can't be optimistic around operand-bundled calls from an
SCC into itself.

llvm-svn: 260244

llvm/lib/Transforms/IPO/FunctionAttrs.cpp
llvm/test/Transforms/FunctionAttrs/operand-bundles-scc.ll [new file with mode: 0644]

index b84620c..60cc874 100644 (file)
@@ -120,8 +120,12 @@ static MemoryAccessKind checkFunctionMemoryAccess(Function &F, AAResults &AAR,
     // Detect these now, skipping to the next instruction if one is found.
     CallSite CS(cast<Value>(I));
     if (CS) {
-      // Ignore calls to functions in the same SCC.
-      if (CS.getCalledFunction() && SCCNodes.count(CS.getCalledFunction()))
+      // Ignore calls to functions in the same SCC, as long as the call sites
+      // don't have operand bundles.  Calls with operand bundles are allowed to
+      // have memory effects not described by the memory effects of the call
+      // target.
+      if (!CS.hasOperandBundles() && CS.getCalledFunction() &&
+          SCCNodes.count(CS.getCalledFunction()))
         continue;
       FunctionModRefBehavior MRB = AAR.getModRefBehavior(CS);
 
diff --git a/llvm/test/Transforms/FunctionAttrs/operand-bundles-scc.ll b/llvm/test/Transforms/FunctionAttrs/operand-bundles-scc.ll
new file mode 100644 (file)
index 0000000..2502ea7
--- /dev/null
@@ -0,0 +1,13 @@
+; RUN: opt -S -functionattrs < %s | FileCheck %s
+
+define void @f() {
+; CHECK-LABEL:  define void @f() {
+ call void @g() [ "unknown"() ]
+ ret void
+}
+
+define void @g() {
+; CHECK-LABEL:  define void @g() {
+ call void @f()
+ ret void
+}