[llvm] r290649 - [PM] Teach the inliner's call graph update to handle inserting new edges

Chandler Carruth via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 27 19:13:12 PST 2016


Author: chandlerc
Date: Tue Dec 27 21:13:12 2016
New Revision: 290649

URL: http://llvm.org/viewvc/llvm-project?rev=290649&view=rev
Log:
[PM] Teach the inliner's call graph update to handle inserting new edges
when they are call edges at the leaf but may (transitively) be reached
via ref edges.

It turns out there is a simple rule: insert everything as a ref edge
which is a safe conservative default. Then we let the existing update
logic handle promoting some of those to call edges.

Note that it would be fairly cheap to make these call edges right away
if that is desirable by testing whether there is some existing call path
from the source to the target. It just seemed like slightly more
complexity in this code path that isn't strictly necessary. If anyone
feels strongly about handling this differently I'm happy to change it.

Modified:
    llvm/trunk/lib/Transforms/IPO/Inliner.cpp
    llvm/trunk/test/Transforms/Inline/cgscc-update.ll

Modified: llvm/trunk/lib/Transforms/IPO/Inliner.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/Inliner.cpp?rev=290649&r1=290648&r2=290649&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/Inliner.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/Inliner.cpp Tue Dec 27 21:13:12 2016
@@ -886,16 +886,18 @@ PreservedAnalyses InlinerPass::run(LazyC
       continue;
     Changed = true;
 
-    // Add all the inlined callees' edges to the caller. These are by
-    // definition trivial edges as we already had a transitive call edge to the
-    // callee.
+    // Add all the inlined callees' edges as ref edges to the caller. These are
+    // by definition trivial edges as we always have *some* transitive ref edge
+    // chain. While in some cases these edges are direct calls inside the
+    // callee, they have to be modeled in the inliner as reference edges as
+    // there may be a reference edge anywhere along the chain from the current
+    // caller to the callee that causes the whole thing to appear like
+    // a (transitive) reference edge that will require promotion to a call edge
+    // below.
     for (Function *InlinedCallee : InlinedCallees) {
       LazyCallGraph::Node &CalleeN = *CG.lookup(*InlinedCallee);
       for (LazyCallGraph::Edge &E : CalleeN)
-        if (E.isCall())
-          RC->insertTrivialCallEdge(N, *E.getNode());
-        else
-          RC->insertTrivialRefEdge(N, *E.getNode());
+        RC->insertTrivialRefEdge(N, *E.getNode());
     }
     InlinedCallees.clear();
 

Modified: llvm/trunk/test/Transforms/Inline/cgscc-update.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/cgscc-update.ll?rev=290649&r1=290648&r2=290649&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/Inline/cgscc-update.ll (original)
+++ llvm/trunk/test/Transforms/Inline/cgscc-update.ll Tue Dec 27 21:13:12 2016
@@ -143,3 +143,42 @@ exit:
   call void @test3_maybe_unknown(i1 false)
   ret void
 }
+
+
+; The 'test4_' prefixed functions are designed to trigger forming a new direct
+; call in the inlined body of the function similar to 'test1_'. However, after
+; that we continue to inline another edge of the graph forcing us to do a more
+; interesting call graph update for the new call edge. Eventually, we still
+; form a new SCC and should use that can deduce precise function attrs.
+
+; This function should have had 'readnone' deduced for its SCC.
+; CHECK: Function Attrs: noinline readnone
+; CHECK-NEXT: define void @test4_f1()
+define void @test4_f1() noinline {
+entry:
+  call void @test4_h()
+  ret void
+}
+
+; CHECK-NOT: @test4_f2
+define internal void @test4_f2() {
+entry:
+  call void @test4_f1()
+  ret void
+}
+
+; CHECK-NOT: @test4_g
+define internal void @test4_g(void()* %p) {
+entry:
+  call void %p()
+  ret void
+}
+
+; This function should have had 'readnone' deduced for its SCC.
+; CHECK: Function Attrs: noinline readnone
+; CHECK-NEXT: define void @test4_h()
+define void @test4_h() noinline {
+entry:
+  call void @test4_g(void()* @test4_f2)
+  ret void
+}




More information about the llvm-commits mailing list