Skip to content

Commit d803a93

Browse files
[Inliner] Report inlining decision before deleting Callee contents (#153616)
Call `recordInliningWithCalleeDeleted` before dropping the contents of the Callee. Otherwise the handlers don't have access to e.g. the DebugLoc, so the Callee DebugLoc was missing in inlining remarks for functions with internal linkage. The test is the same as `optimization-remarks-passed-yaml.ll` except that the function `foo` has internal linkage instead of external linkage.
1 parent 3b27d50 commit d803a93

File tree

3 files changed

+106
-6
lines changed

3 files changed

+106
-6
lines changed

llvm/lib/Transforms/IPO/Inliner.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,9 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
459459
}),
460460
Calls.end());
461461

462+
// Report inlining decision BEFORE deleting function contents, so we
463+
// can still access e.g. the DebugLoc
464+
Advice->recordInliningWithCalleeDeleted();
462465
// Clear the body and queue the function itself for call graph
463466
// updating when we finish inlining.
464467
makeFunctionBodyUnreachable(Callee);
@@ -470,9 +473,7 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
470473
DeadFunctionsInComdats.push_back(&Callee);
471474
}
472475
}
473-
if (CalleeWasDeleted)
474-
Advice->recordInliningWithCalleeDeleted();
475-
else
476+
if (!CalleeWasDeleted)
476477
Advice->recordInlining();
477478
}
478479

llvm/lib/Transforms/IPO/ModuleInliner.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,10 @@ PreservedAnalyses ModuleInlinerPass::run(Module &M,
284284
Calls->erase_if([&](const std::pair<CallBase *, int> &Call) {
285285
return Call.first->getCaller() == &Callee;
286286
});
287+
288+
// Report inlining decision BEFORE deleting function contents, so we
289+
// can still access e.g. the DebugLoc
290+
Advice->recordInliningWithCalleeDeleted();
287291
// Clear the body and queue the function itself for deletion when we
288292
// finish inlining.
289293
// Note that after this point, it is an error to do anything other
@@ -295,9 +299,7 @@ PreservedAnalyses ModuleInlinerPass::run(Module &M,
295299
CalleeWasDeleted = true;
296300
}
297301
}
298-
if (CalleeWasDeleted)
299-
Advice->recordInliningWithCalleeDeleted();
300-
else
302+
if (!CalleeWasDeleted)
301303
Advice->recordInlining();
302304
}
303305

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
; RUN: opt < %s -S -passes=inline -pass-remarks-output=%t -pass-remarks=inline \
2+
; RUN: -pass-remarks-missed=inline -pass-remarks-analysis=inline \
3+
; RUN: -pass-remarks-with-hotness 2>&1 | FileCheck %s
4+
; RUN: cat %t | FileCheck -check-prefixes=YAML,YAML-NO-ANNOTATE %s
5+
6+
; RUN: opt < %s -S -passes=inline -pass-remarks-output=%t -pass-remarks=inline \
7+
; RUN: -pass-remarks-missed=inline -pass-remarks-analysis=inline \
8+
; RUN: -pass-remarks-with-hotness 2>&1 | FileCheck %s
9+
; RUN: cat %t | FileCheck -check-prefixes=YAML,YAML-NO-ANNOTATE %s
10+
11+
; RUN: opt < %s -S -passes=inliner-wrapper -pass-remarks-output=%t -pass-remarks=inline \
12+
; RUN: -pass-remarks-missed=inline -pass-remarks-analysis=inline \
13+
; RUN: -annotate-inline-phase=false \
14+
; RUN: -pass-remarks-with-hotness 2>&1 | FileCheck %s
15+
; RUN: cat %t | FileCheck -check-prefixes=YAML,YAML-NO-ANNOTATE %s
16+
17+
; RUN: opt < %s -S -passes=inliner-wrapper -pass-remarks-output=%t -pass-remarks=inline \
18+
; RUN: -pass-remarks-missed=inline -pass-remarks-analysis=inline \
19+
; RUN: -annotate-inline-phase \
20+
; RUN: -pass-remarks-with-hotness 2>&1 | FileCheck %s
21+
; RUN: cat %t | FileCheck -check-prefixes=YAML,YAML-ANNOTATE %s
22+
23+
; Same as optimization-remarks-passed-yaml.ll, but here foo has internal linkage
24+
; instead of external linkage. This exercises a different hook for reporting the inlining decision,
25+
; because foo is deleted after it is inlined (due to internal linkage).
26+
; Make sure that the Remark correctly emits the DebugLoc for foo before it is deleted.
27+
28+
; CHECK: remark: /tmp/s.c:4:10: 'foo' inlined into 'bar' with (cost={{[0-9\-]+}}, threshold={{[0-9]+}}) at callsite bar:1:10; (hotness: 30)
29+
30+
; YAML: --- !Passed
31+
; YAML-NO-ANNOTATE-NEXT: Pass: inline
32+
; YAML-ANNOTATE-NEXT: Pass: main-always-inline
33+
; YAML-NEXT: Name: Inlined
34+
; YAML-NEXT: DebugLoc: { File: '/tmp/s.c', Line: 4, Column: 10 }
35+
; YAML-NEXT: Function: bar
36+
; YAML-NEXT: Hotness: 30
37+
; YAML-NEXT: Args:
38+
; YAML-NEXT: - String: ''''
39+
; YAML-NEXT: - Callee: foo
40+
; YAML-NEXT: DebugLoc: { File: '/tmp/s.c', Line: 1, Column: 0 }
41+
; YAML-NEXT: - String: ''' inlined into '''
42+
; YAML-NEXT: - Caller: bar
43+
; YAML-NEXT: DebugLoc: { File: '/tmp/s.c', Line: 3, Column: 0 }
44+
; YAML-NEXT: - String: ''''
45+
; YAML-NEXT: - String: ' with '
46+
; YAML-NEXT: - String: '(cost='
47+
; YAML-NEXT: - Cost: '{{[0-9\-]+}}'
48+
; YAML-NEXT: - String: ', threshold='
49+
; YAML-NEXT: - Threshold: '{{[0-9]+}}'
50+
; YAML-NEXT: - String: ')'
51+
; YAML-NEXT: - String: ' at callsite '
52+
; YAML-NEXT: - String: bar
53+
; YAML-NEXT: - String: ':'
54+
; YAML-NEXT: - Line: '1'
55+
; YAML-NEXT: - String: ':'
56+
; YAML-NEXT: - Column: '10'
57+
; YAML-NEXT: - String: ';'
58+
; YAML-NEXT: ...
59+
60+
; ModuleID = '/tmp/s.c'
61+
source_filename = "/tmp/s.c"
62+
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
63+
target triple = "x86_64-apple-macosx10.11.0"
64+
65+
; Function Attrs: nounwind ssp uwtable
66+
define internal i32 @foo() #0 !dbg !7 {
67+
entry:
68+
ret i32 1, !dbg !9
69+
}
70+
71+
; Function Attrs: nounwind ssp uwtable
72+
define i32 @bar() #0 !dbg !10 !prof !13 {
73+
entry:
74+
%call = call i32 @foo(), !dbg !11
75+
ret i32 %call, !dbg !12
76+
}
77+
78+
attributes #0 = { nounwind ssp uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "frame-pointer"="all" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
79+
80+
!llvm.dbg.cu = !{!0}
81+
!llvm.module.flags = !{!3, !4, !5}
82+
!llvm.ident = !{!6}
83+
84+
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.0 (trunk 282540) (llvm/trunk 282542)", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2)
85+
!1 = !DIFile(filename: "/tmp/s.c", directory: "/tmp")
86+
!2 = !{}
87+
!3 = !{i32 2, !"Dwarf Version", i32 4}
88+
!4 = !{i32 2, !"Debug Info Version", i32 3}
89+
!5 = !{i32 1, !"PIC Level", i32 2}
90+
!6 = !{!"clang version 4.0.0 (trunk 282540) (llvm/trunk 282542)"}
91+
!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: true, unit: !0, retainedNodes: !2)
92+
!8 = !DISubroutineType(types: !2)
93+
!9 = !DILocation(line: 1, column: 13, scope: !7)
94+
!10 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 3, type: !8, isLocal: false, isDefinition: true, scopeLine: 3, isOptimized: true, unit: !0, retainedNodes: !2)
95+
!11 = !DILocation(line: 4, column: 10, scope: !10)
96+
!12 = !DILocation(line: 4, column: 3, scope: !10)
97+
!13 = !{!"function_entry_count", i64 30}

0 commit comments

Comments
 (0)