Skip to content
This repository was archived by the owner on Dec 17, 2024. It is now read-only.

Commit 9900d18

Browse files
committed
[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. llvm-svn: 290649
1 parent 28ec346 commit 9900d18

File tree

2 files changed

+48
-7
lines changed

2 files changed

+48
-7
lines changed

llvm/lib/Transforms/IPO/Inliner.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -886,16 +886,18 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
886886
continue;
887887
Changed = true;
888888

889-
// Add all the inlined callees' edges to the caller. These are by
890-
// definition trivial edges as we already had a transitive call edge to the
891-
// callee.
889+
// Add all the inlined callees' edges as ref edges to the caller. These are
890+
// by definition trivial edges as we always have *some* transitive ref edge
891+
// chain. While in some cases these edges are direct calls inside the
892+
// callee, they have to be modeled in the inliner as reference edges as
893+
// there may be a reference edge anywhere along the chain from the current
894+
// caller to the callee that causes the whole thing to appear like
895+
// a (transitive) reference edge that will require promotion to a call edge
896+
// below.
892897
for (Function *InlinedCallee : InlinedCallees) {
893898
LazyCallGraph::Node &CalleeN = *CG.lookup(*InlinedCallee);
894899
for (LazyCallGraph::Edge &E : CalleeN)
895-
if (E.isCall())
896-
RC->insertTrivialCallEdge(N, *E.getNode());
897-
else
898-
RC->insertTrivialRefEdge(N, *E.getNode());
900+
RC->insertTrivialRefEdge(N, *E.getNode());
899901
}
900902
InlinedCallees.clear();
901903

llvm/test/Transforms/Inline/cgscc-update.ll

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,42 @@ exit:
143143
call void @test3_maybe_unknown(i1 false)
144144
ret void
145145
}
146+
147+
148+
; The 'test4_' prefixed functions are designed to trigger forming a new direct
149+
; call in the inlined body of the function similar to 'test1_'. However, after
150+
; that we continue to inline another edge of the graph forcing us to do a more
151+
; interesting call graph update for the new call edge. Eventually, we still
152+
; form a new SCC and should use that can deduce precise function attrs.
153+
154+
; This function should have had 'readnone' deduced for its SCC.
155+
; CHECK: Function Attrs: noinline readnone
156+
; CHECK-NEXT: define void @test4_f1()
157+
define void @test4_f1() noinline {
158+
entry:
159+
call void @test4_h()
160+
ret void
161+
}
162+
163+
; CHECK-NOT: @test4_f2
164+
define internal void @test4_f2() {
165+
entry:
166+
call void @test4_f1()
167+
ret void
168+
}
169+
170+
; CHECK-NOT: @test4_g
171+
define internal void @test4_g(void()* %p) {
172+
entry:
173+
call void %p()
174+
ret void
175+
}
176+
177+
; This function should have had 'readnone' deduced for its SCC.
178+
; CHECK: Function Attrs: noinline readnone
179+
; CHECK-NEXT: define void @test4_h()
180+
define void @test4_h() noinline {
181+
entry:
182+
call void @test4_g(void()* @test4_f2)
183+
ret void
184+
}

0 commit comments

Comments
 (0)