xref: /llvm-project/llvm/test/Analysis/CtxProfAnalysis/inline.ll (revision b15845c0059b06f406e33f278127d7eb41ff5ab6)
1; REQUIRES: x86_64-linux
2; RUN: rm -rf %t
3; RUN: split-file %s %t
4; RUN: llvm-ctxprof-util fromYAML --input=%t/profile.yaml --output=%t/profile.ctxprofdata
5
6; RUN: opt -passes='module-inline,print<ctx-prof-analysis>' -ctx-profile-printer-level=everything %t/module.ll -S \
7; RUN:   -use-ctx-profile=%t/profile.ctxprofdata -ctx-profile-printer-level=yaml \
8; RUN:   -o - 2> %t/profile-final.yaml | FileCheck %s
9; RUN: diff %t/profile-final.yaml %t/expected.yaml
10
11; There are 2 calls to @a from @entrypoint. We only inline the one callsite
12; marked as alwaysinline, the rest are blocked (marked noinline). After the inline,
13; the updated contextual profile should still have the same tree for the non-inlined case.
14; For the inlined case, we should observe, for the @entrypoint context:
15;  - an empty callsite where the inlined one was (first one, i.e. 0)
16;  - more counters appended to the old counter list (because we ingested the
17;    ones from @a). The values are copied.
18;  - a new callsite to @b
19; CHECK-LABEL: @entrypoint
20; CHECK-LABEL: yes:
21; CHECK:         call void @llvm.instrprof.increment(ptr @entrypoint, i64 0, i32 3, i32 1)
22; CHECK-NEXT:    br label %loop.i
23; CHECK-LABEL:  loop.i:
24; CHECK-NEXT:    %indvar.i = phi i32 [ %indvar.next.i, %loop.i ], [ 0, %yes ]
25; CHECK-NEXT:    call void @llvm.instrprof.increment(ptr @entrypoint, i64 0, i32 2, i32 3)
26; CHECK-NEXT:    %b.i = add i32 %x, %indvar.i
27; CHECK-NEXT:    call void @llvm.instrprof.callsite(ptr @entrypoint, i64 0, i32 1, i32 2, ptr @b)
28; CHECK-NEXT:    %call3.i = call i32 @b() #1
29; CHECK-LABEL: no:
30; CHECK-NEXT:    call void @llvm.instrprof.increment(ptr @entrypoint, i64 0, i32 3, i32 2)
31; CHECK-NEXT:    call void @llvm.instrprof.callsite(ptr @entrypoint, i64 0, i32 2, i32 1, ptr @a)
32; CHECK-NEXT:    %call2 = call i32 @a(i32 %x) #1
33; CHECK-NEXT:    br label %exit
34
35; Make sure the postlink thinlto pipeline is aware of ctxprof
36; RUN: opt -passes='thinlto<O2>' -use-ctx-profile=%t/profile.ctxprofdata \
37; RUN:   %t/module.ll -S -o - | FileCheck %s --check-prefix=PIPELINE
38
39; PIPELINE-LABEL: define i32 @entrypoint
40; PIPELINE-SAME: !prof ![[ENTRYPOINT_COUNT:[0-9]+]]
41; PIPELINE-LABEL: loop.i:
42; PIPELINE:         br i1 %cond.i, label %loop.i, label %exit, !prof ![[LOOP_BW_INL:[0-9]+]]
43; PIPELINE-LABEL: define i32 @a
44; PIPELINE-LABEL: loop:
45; PIPELINE:         br i1 %cond, label %loop, label %exit, !prof ![[LOOP_BW_ORIG:[0-9]+]]
46
47; PIPELINE: ![[ENTRYPOINT_COUNT]] = !{!"function_entry_count", i64 10}
48; These are the weights of the inlined @a, where the counters were 2, 100 (2 for entry, 100 for loop)
49; PIPELINE: ![[LOOP_BW_INL]] = !{!"branch_weights", i32 98, i32 2}
50; These are the weights of the un-inlined @a, where the counters were 8, 500 (8 for entry, 500 for loop)
51; PIPELINE: ![[LOOP_BW_ORIG]] = !{!"branch_weights", i32 492, i32 8}
52
53;--- module.ll
54define i32 @entrypoint(i32 %x) !guid !0 {
55  call void @llvm.instrprof.increment(ptr @entrypoint, i64 0, i32 3, i32 0)
56  %t = icmp eq i32 %x, 0
57  br i1 %t, label %yes, label %no
58yes:
59  call void @llvm.instrprof.increment(ptr @entrypoint, i64 0, i32 3, i32 1)
60  call void @llvm.instrprof.callsite(ptr @entrypoint, i64 0, i32 2, i32 0, ptr @a)
61  %call1 = call i32 @a(i32 %x) alwaysinline
62  br label %exit
63no:
64  call void @llvm.instrprof.increment(ptr @entrypoint, i64 0, i32 3, i32 2)
65  call void @llvm.instrprof.callsite(ptr @entrypoint, i64 0, i32 2, i32 1, ptr @a)
66  %call2 = call i32 @a(i32 %x) noinline
67  br label %exit
68exit:
69  %ret = phi i32 [%call1, %yes], [%call2, %no]
70  ret i32 %ret
71}
72
73define i32 @a(i32 %x) !guid !1 {
74entry:
75  call void @llvm.instrprof.increment(ptr @a, i64 0, i32 2, i32 0)
76  br label %loop
77loop:
78  %indvar = phi i32 [%indvar.next, %loop], [0, %entry]
79  call void @llvm.instrprof.increment(ptr @a, i64 0, i32 2, i32 1)
80  %b = add i32 %x, %indvar
81  call void @llvm.instrprof.callsite(ptr @a, i64 0, i32 1, i32 0, ptr @b)
82  %call3 = call i32 @b() noinline
83  %indvar.next = add i32 %indvar, %call3
84  %cond = icmp slt i32 %indvar.next, %x
85  br i1 %cond, label %loop, label %exit
86exit:
87  ret i32 8
88}
89
90define i32 @b() !guid !2 {
91  call void @llvm.instrprof.increment(ptr @b, i64 0, i32 1, i32 0)
92  ret i32 1
93}
94
95!0 = !{i64 1000}
96!1 = !{i64 1001}
97!2 = !{i64 1002}
98;--- profile.yaml
99- Guid: 1000
100  Counters: [10, 2, 8]
101  Callsites:  -
102                - Guid: 1001
103                  Counters: [2, 100]
104                  Callsites:  -
105                                - Guid: 1002
106                                  Counters: [100]
107              -
108                - Guid: 1001
109                  Counters: [8, 500]
110                  Callsites:  -
111                                - Guid: 1002
112                                  Counters: [500]
113;--- expected.yaml
114
115- Guid:            1000
116  Counters:        [ 10, 2, 8, 100 ]
117  Callsites:
118    - [  ]
119    - - Guid:            1001
120        Counters:        [ 8, 500 ]
121        Callsites:
122          - - Guid:            1002
123              Counters:        [ 500 ]
124    - - Guid:            1002
125        Counters:        [ 100 ]
126