xref: /llvm-project/llvm/test/Transforms/PGOProfile/ctx-instrumentation.ll (revision 82266d3a2b33f49165c0f24d3db5ea9875cc706c)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 4
2; RUN: opt -passes=ctx-instr-gen -profile-context-root=an_entrypoint \
3; RUN:   -S < %s | FileCheck --check-prefix=INSTRUMENT %s
4; RUN: opt -passes=ctx-instr-gen,assign-guid,ctx-instr-lower -profile-context-root=an_entrypoint \
5; RUN:   -profile-context-root=another_entrypoint_no_callees \
6; RUN:   -S < %s | FileCheck --check-prefix=LOWERING %s
7
8
9declare void @bar()
10
11;.
12; LOWERING: @an_entrypoint_ctx_root = global { ptr, ptr, ptr, i8 } zeroinitializer
13; LOWERING: @another_entrypoint_no_callees_ctx_root = global { ptr, ptr, ptr, i8 } zeroinitializer
14; LOWERING: @__llvm_ctx_profile_callsite = external hidden thread_local global ptr
15; LOWERING: @__llvm_ctx_profile_expected_callee = external hidden thread_local global ptr
16;.
17define void @foo(i32 %a, ptr %fct) {
18; INSTRUMENT-LABEL: define void @foo(
19; INSTRUMENT-SAME: i32 [[A:%.*]], ptr [[FCT:%.*]]) {
20; INSTRUMENT-NEXT:    call void @llvm.instrprof.increment(ptr @foo, i64 728453322856651412, i32 2, i32 0)
21; INSTRUMENT-NEXT:    [[T:%.*]] = icmp eq i32 [[A]], 0
22; INSTRUMENT-NEXT:    br i1 [[T]], label [[YES:%.*]], label [[NO:%.*]]
23; INSTRUMENT:       yes:
24; INSTRUMENT-NEXT:    call void @llvm.instrprof.increment(ptr @foo, i64 728453322856651412, i32 2, i32 1)
25; INSTRUMENT-NEXT:    call void @llvm.instrprof.callsite(ptr @foo, i64 728453322856651412, i32 2, i32 0, ptr [[FCT]])
26; INSTRUMENT-NEXT:    call void [[FCT]](i32 [[A]])
27; INSTRUMENT-NEXT:    br label [[EXIT:%.*]]
28; INSTRUMENT:       no:
29; INSTRUMENT-NEXT:    call void @llvm.instrprof.callsite(ptr @foo, i64 728453322856651412, i32 2, i32 1, ptr @bar)
30; INSTRUMENT-NEXT:    call void @bar()
31; INSTRUMENT-NEXT:    br label [[EXIT]]
32; INSTRUMENT:       exit:
33; INSTRUMENT-NEXT:    ret void
34;
35; LOWERING-LABEL: define void @foo(
36; LOWERING-SAME: i32 [[A:%.*]], ptr [[FCT:%.*]]) !guid [[META0:![0-9]+]] {
37; LOWERING-NEXT:    [[TMP1:%.*]] = call ptr @__llvm_ctx_profile_get_context(ptr @foo, i64 6699318081062747564, i32 2, i32 2)
38; LOWERING-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64
39; LOWERING-NEXT:    [[TMP3:%.*]] = and i64 [[TMP2]], 1
40; LOWERING-NEXT:    [[TMP4:%.*]] = call ptr @llvm.threadlocal.address.p0(ptr @__llvm_ctx_profile_expected_callee)
41; LOWERING-NEXT:    [[TMP5:%.*]] = getelementptr ptr, ptr [[TMP4]], i64 [[TMP3]]
42; LOWERING-NEXT:    [[TMP6:%.*]] = call ptr @llvm.threadlocal.address.p0(ptr @__llvm_ctx_profile_callsite)
43; LOWERING-NEXT:    [[TMP7:%.*]] = getelementptr i32, ptr [[TMP6]], i64 [[TMP3]]
44; LOWERING-NEXT:    [[TMP8:%.*]] = and i64 [[TMP2]], -2
45; LOWERING-NEXT:    [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr
46; LOWERING-NEXT:    [[T:%.*]] = icmp eq i32 [[A]], 0
47; LOWERING-NEXT:    br i1 [[T]], label [[YES:%.*]], label [[NO:%.*]]
48; LOWERING:       yes:
49; LOWERING-NEXT:    [[TMP10:%.*]] = getelementptr { { i64, ptr, i32, i32 }, [2 x i64], [2 x ptr] }, ptr [[TMP9]], i32 0, i32 1, i32 1
50; LOWERING-NEXT:    [[TMP11:%.*]] = load i64, ptr [[TMP10]], align 4
51; LOWERING-NEXT:    [[TMP12:%.*]] = add i64 [[TMP11]], 1
52; LOWERING-NEXT:    store i64 [[TMP12]], ptr [[TMP10]], align 4
53; LOWERING-NEXT:    store volatile ptr [[FCT]], ptr [[TMP5]], align 8
54; LOWERING-NEXT:    [[TMP13:%.*]] = getelementptr { { i64, ptr, i32, i32 }, [2 x i64], [2 x ptr] }, ptr [[TMP1]], i32 0, i32 2, i32 0
55; LOWERING-NEXT:    store volatile ptr [[TMP13]], ptr [[TMP7]], align 8
56; LOWERING-NEXT:    call void [[FCT]](i32 [[A]])
57; LOWERING-NEXT:    br label [[EXIT:%.*]]
58; LOWERING:       no:
59; LOWERING-NEXT:    store volatile ptr @bar, ptr [[TMP5]], align 8
60; LOWERING-NEXT:    [[TMP14:%.*]] = getelementptr { { i64, ptr, i32, i32 }, [2 x i64], [2 x ptr] }, ptr [[TMP1]], i32 0, i32 2, i32 1
61; LOWERING-NEXT:    store volatile ptr [[TMP14]], ptr [[TMP7]], align 8
62; LOWERING-NEXT:    call void @bar()
63; LOWERING-NEXT:    br label [[EXIT]]
64; LOWERING:       exit:
65; LOWERING-NEXT:    ret void
66;
67  %t = icmp eq i32 %a, 0
68  br i1 %t, label %yes, label %no
69yes:
70  call void %fct(i32 %a)
71  br label %exit
72no:
73  call void @bar()
74  br label %exit
75exit:
76  ret void
77}
78
79define void @an_entrypoint(i32 %a) {
80; INSTRUMENT-LABEL: define void @an_entrypoint(
81; INSTRUMENT-SAME: i32 [[A:%.*]]) {
82; INSTRUMENT-NEXT:    call void @llvm.instrprof.increment(ptr @an_entrypoint, i64 784007058953177093, i32 2, i32 0)
83; INSTRUMENT-NEXT:    [[T:%.*]] = icmp eq i32 [[A]], 0
84; INSTRUMENT-NEXT:    br i1 [[T]], label [[YES:%.*]], label [[NO:%.*]]
85; INSTRUMENT:       yes:
86; INSTRUMENT-NEXT:    call void @llvm.instrprof.increment(ptr @an_entrypoint, i64 784007058953177093, i32 2, i32 1)
87; INSTRUMENT-NEXT:    call void @llvm.instrprof.callsite(ptr @an_entrypoint, i64 784007058953177093, i32 1, i32 0, ptr @foo)
88; INSTRUMENT-NEXT:    call void @foo(i32 1, ptr null)
89; INSTRUMENT-NEXT:    ret void
90; INSTRUMENT:       no:
91; INSTRUMENT-NEXT:    ret void
92;
93; LOWERING-LABEL: define void @an_entrypoint(
94; LOWERING-SAME: i32 [[A:%.*]]) !guid [[META1:![0-9]+]] {
95; LOWERING-NEXT:    [[TMP1:%.*]] = call ptr @__llvm_ctx_profile_start_context(ptr @an_entrypoint_ctx_root, i64 4909520559318251808, i32 2, i32 1)
96; LOWERING-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64
97; LOWERING-NEXT:    [[TMP3:%.*]] = and i64 [[TMP2]], 1
98; LOWERING-NEXT:    [[TMP4:%.*]] = call ptr @llvm.threadlocal.address.p0(ptr @__llvm_ctx_profile_expected_callee)
99; LOWERING-NEXT:    [[TMP5:%.*]] = getelementptr ptr, ptr [[TMP4]], i64 [[TMP3]]
100; LOWERING-NEXT:    [[TMP6:%.*]] = call ptr @llvm.threadlocal.address.p0(ptr @__llvm_ctx_profile_callsite)
101; LOWERING-NEXT:    [[TMP7:%.*]] = getelementptr i32, ptr [[TMP6]], i64 [[TMP3]]
102; LOWERING-NEXT:    [[TMP8:%.*]] = and i64 [[TMP2]], -2
103; LOWERING-NEXT:    [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr
104; LOWERING-NEXT:    [[T:%.*]] = icmp eq i32 [[A]], 0
105; LOWERING-NEXT:    br i1 [[T]], label [[YES:%.*]], label [[NO:%.*]]
106; LOWERING:       yes:
107; LOWERING-NEXT:    [[TMP10:%.*]] = getelementptr { { i64, ptr, i32, i32 }, [2 x i64], [1 x ptr] }, ptr [[TMP9]], i32 0, i32 1, i32 1
108; LOWERING-NEXT:    [[TMP11:%.*]] = load i64, ptr [[TMP10]], align 4
109; LOWERING-NEXT:    [[TMP12:%.*]] = add i64 [[TMP11]], 1
110; LOWERING-NEXT:    store i64 [[TMP12]], ptr [[TMP10]], align 4
111; LOWERING-NEXT:    store volatile ptr @foo, ptr [[TMP5]], align 8
112; LOWERING-NEXT:    [[TMP13:%.*]] = getelementptr { { i64, ptr, i32, i32 }, [2 x i64], [1 x ptr] }, ptr [[TMP1]], i32 0, i32 2, i32 0
113; LOWERING-NEXT:    store volatile ptr [[TMP13]], ptr [[TMP7]], align 8
114; LOWERING-NEXT:    call void @foo(i32 1, ptr null)
115; LOWERING-NEXT:    call void @__llvm_ctx_profile_release_context(ptr @an_entrypoint_ctx_root)
116; LOWERING-NEXT:    ret void
117; LOWERING:       no:
118; LOWERING-NEXT:    call void @__llvm_ctx_profile_release_context(ptr @an_entrypoint_ctx_root)
119; LOWERING-NEXT:    ret void
120;
121  %t = icmp eq i32 %a, 0
122  br i1 %t, label %yes, label %no
123
124yes:
125  call void @foo(i32 1, ptr null)
126  ret void
127no:
128  ret void
129}
130
131define void @another_entrypoint_no_callees(i32 %a) {
132; INSTRUMENT-LABEL: define void @another_entrypoint_no_callees(
133; INSTRUMENT-SAME: i32 [[A:%.*]]) {
134; INSTRUMENT-NEXT:    call void @llvm.instrprof.increment(ptr @another_entrypoint_no_callees, i64 784007058953177093, i32 2, i32 0)
135; INSTRUMENT-NEXT:    [[T:%.*]] = icmp eq i32 [[A]], 0
136; INSTRUMENT-NEXT:    br i1 [[T]], label [[YES:%.*]], label [[NO:%.*]]
137; INSTRUMENT:       yes:
138; INSTRUMENT-NEXT:    call void @llvm.instrprof.increment(ptr @another_entrypoint_no_callees, i64 784007058953177093, i32 2, i32 1)
139; INSTRUMENT-NEXT:    ret void
140; INSTRUMENT:       no:
141; INSTRUMENT-NEXT:    ret void
142;
143; LOWERING-LABEL: define void @another_entrypoint_no_callees(
144; LOWERING-SAME: i32 [[A:%.*]]) !guid [[META2:![0-9]+]] {
145; LOWERING-NEXT:    [[TMP1:%.*]] = call ptr @__llvm_ctx_profile_start_context(ptr @another_entrypoint_no_callees_ctx_root, i64 -6371873725078000974, i32 2, i32 0)
146; LOWERING-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64
147; LOWERING-NEXT:    [[TMP3:%.*]] = and i64 [[TMP2]], -2
148; LOWERING-NEXT:    [[TMP4:%.*]] = inttoptr i64 [[TMP3]] to ptr
149; LOWERING-NEXT:    [[T:%.*]] = icmp eq i32 [[A]], 0
150; LOWERING-NEXT:    br i1 [[T]], label [[YES:%.*]], label [[NO:%.*]]
151; LOWERING:       yes:
152; LOWERING-NEXT:    [[TMP5:%.*]] = getelementptr { { i64, ptr, i32, i32 }, [2 x i64], [0 x ptr] }, ptr [[TMP4]], i32 0, i32 1, i32 1
153; LOWERING-NEXT:    [[TMP6:%.*]] = load i64, ptr [[TMP5]], align 4
154; LOWERING-NEXT:    [[TMP7:%.*]] = add i64 [[TMP6]], 1
155; LOWERING-NEXT:    store i64 [[TMP7]], ptr [[TMP5]], align 4
156; LOWERING-NEXT:    call void @__llvm_ctx_profile_release_context(ptr @another_entrypoint_no_callees_ctx_root)
157; LOWERING-NEXT:    ret void
158; LOWERING:       no:
159; LOWERING-NEXT:    call void @__llvm_ctx_profile_release_context(ptr @another_entrypoint_no_callees_ctx_root)
160; LOWERING-NEXT:    ret void
161;
162  %t = icmp eq i32 %a, 0
163  br i1 %t, label %yes, label %no
164
165yes:
166  ret void
167no:
168  ret void
169}
170
171define void @simple(i32 %a) {
172; INSTRUMENT-LABEL: define void @simple(
173; INSTRUMENT-SAME: i32 [[A:%.*]]) {
174; INSTRUMENT-NEXT:    call void @llvm.instrprof.increment(ptr @simple, i64 742261418966908927, i32 1, i32 0)
175; INSTRUMENT-NEXT:    ret void
176;
177; LOWERING-LABEL: define void @simple(
178; LOWERING-SAME: i32 [[A:%.*]]) !guid [[META3:![0-9]+]] {
179; LOWERING-NEXT:    [[TMP1:%.*]] = call ptr @__llvm_ctx_profile_get_context(ptr @simple, i64 -3006003237940970099, i32 1, i32 0)
180; LOWERING-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64
181; LOWERING-NEXT:    [[TMP3:%.*]] = and i64 [[TMP2]], -2
182; LOWERING-NEXT:    [[TMP4:%.*]] = inttoptr i64 [[TMP3]] to ptr
183; LOWERING-NEXT:    ret void
184;
185  ret void
186}
187
188
189define i32 @no_callsites(i32 %a) {
190; INSTRUMENT-LABEL: define i32 @no_callsites(
191; INSTRUMENT-SAME: i32 [[A:%.*]]) {
192; INSTRUMENT-NEXT:    call void @llvm.instrprof.increment(ptr @no_callsites, i64 784007058953177093, i32 2, i32 0)
193; INSTRUMENT-NEXT:    [[C:%.*]] = icmp eq i32 [[A]], 0
194; INSTRUMENT-NEXT:    br i1 [[C]], label [[YES:%.*]], label [[NO:%.*]]
195; INSTRUMENT:       yes:
196; INSTRUMENT-NEXT:    call void @llvm.instrprof.increment(ptr @no_callsites, i64 784007058953177093, i32 2, i32 1)
197; INSTRUMENT-NEXT:    ret i32 1
198; INSTRUMENT:       no:
199; INSTRUMENT-NEXT:    ret i32 0
200;
201; LOWERING-LABEL: define i32 @no_callsites(
202; LOWERING-SAME: i32 [[A:%.*]]) !guid [[META4:![0-9]+]] {
203; LOWERING-NEXT:    [[TMP1:%.*]] = call ptr @__llvm_ctx_profile_get_context(ptr @no_callsites, i64 5679753335911435902, i32 2, i32 0)
204; LOWERING-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64
205; LOWERING-NEXT:    [[TMP3:%.*]] = and i64 [[TMP2]], -2
206; LOWERING-NEXT:    [[TMP4:%.*]] = inttoptr i64 [[TMP3]] to ptr
207; LOWERING-NEXT:    [[C:%.*]] = icmp eq i32 [[A]], 0
208; LOWERING-NEXT:    br i1 [[C]], label [[YES:%.*]], label [[NO:%.*]]
209; LOWERING:       yes:
210; LOWERING-NEXT:    [[TMP5:%.*]] = getelementptr { { i64, ptr, i32, i32 }, [2 x i64], [0 x ptr] }, ptr [[TMP4]], i32 0, i32 1, i32 1
211; LOWERING-NEXT:    [[TMP6:%.*]] = load i64, ptr [[TMP5]], align 4
212; LOWERING-NEXT:    [[TMP7:%.*]] = add i64 [[TMP6]], 1
213; LOWERING-NEXT:    store i64 [[TMP7]], ptr [[TMP5]], align 4
214; LOWERING-NEXT:    ret i32 1
215; LOWERING:       no:
216; LOWERING-NEXT:    ret i32 0
217;
218  %c = icmp eq i32 %a, 0
219  br i1 %c, label %yes, label %no
220yes:
221  ret i32 1
222no:
223  ret i32 0
224}
225
226define void @no_counters() {
227; INSTRUMENT-LABEL: define void @no_counters() {
228; INSTRUMENT-NEXT:    call void @llvm.instrprof.increment(ptr @no_counters, i64 742261418966908927, i32 1, i32 0)
229; INSTRUMENT-NEXT:    call void @llvm.instrprof.callsite(ptr @no_counters, i64 742261418966908927, i32 1, i32 0, ptr @bar)
230; INSTRUMENT-NEXT:    call void @bar()
231; INSTRUMENT-NEXT:    ret void
232;
233; LOWERING-LABEL: define void @no_counters(
234; LOWERING-SAME: ) !guid [[META5:![0-9]+]] {
235; LOWERING-NEXT:    [[TMP1:%.*]] = call ptr @__llvm_ctx_profile_get_context(ptr @no_counters, i64 5458232184388660970, i32 1, i32 1)
236; LOWERING-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64
237; LOWERING-NEXT:    [[TMP3:%.*]] = and i64 [[TMP2]], 1
238; LOWERING-NEXT:    [[TMP4:%.*]] = call ptr @llvm.threadlocal.address.p0(ptr @__llvm_ctx_profile_expected_callee)
239; LOWERING-NEXT:    [[TMP5:%.*]] = getelementptr ptr, ptr [[TMP4]], i64 [[TMP3]]
240; LOWERING-NEXT:    [[TMP6:%.*]] = call ptr @llvm.threadlocal.address.p0(ptr @__llvm_ctx_profile_callsite)
241; LOWERING-NEXT:    [[TMP7:%.*]] = getelementptr i32, ptr [[TMP6]], i64 [[TMP3]]
242; LOWERING-NEXT:    [[TMP8:%.*]] = and i64 [[TMP2]], -2
243; LOWERING-NEXT:    [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr
244; LOWERING-NEXT:    store volatile ptr @bar, ptr [[TMP5]], align 8
245; LOWERING-NEXT:    [[TMP10:%.*]] = getelementptr { { i64, ptr, i32, i32 }, [1 x i64], [1 x ptr] }, ptr [[TMP1]], i32 0, i32 2, i32 0
246; LOWERING-NEXT:    store volatile ptr [[TMP10]], ptr [[TMP7]], align 8
247; LOWERING-NEXT:    call void @bar()
248; LOWERING-NEXT:    ret void
249;
250  call void @bar()
251  ret void
252}
253
254; Ensure "calls" to inline asm don't get callsite-instrumented.
255define void @inlineasm() {
256; INSTRUMENT-LABEL: define void @inlineasm() {
257; INSTRUMENT-NEXT:    call void @llvm.instrprof.increment(ptr @inlineasm, i64 742261418966908927, i32 1, i32 0)
258; INSTRUMENT-NEXT:    call void asm "nop", ""()
259; INSTRUMENT-NEXT:    ret void
260;
261; LOWERING-LABEL: define void @inlineasm(
262; LOWERING-SAME: ) !guid [[META6:![0-9]+]] {
263; LOWERING-NEXT:    [[TMP1:%.*]] = call ptr @__llvm_ctx_profile_get_context(ptr @inlineasm, i64 -3771893999295659109, i32 1, i32 0)
264; LOWERING-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64
265; LOWERING-NEXT:    [[TMP3:%.*]] = and i64 [[TMP2]], -2
266; LOWERING-NEXT:    [[TMP4:%.*]] = inttoptr i64 [[TMP3]] to ptr
267; LOWERING-NEXT:    call void asm "nop", ""()
268; LOWERING-NEXT:    ret void
269;
270  call void asm "nop", ""()
271  ret void
272}
273;.
274; LOWERING: attributes #[[ATTR0:[0-9]+]] = { nounwind }
275; LOWERING: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
276;.
277; INSTRUMENT: attributes #[[ATTR0:[0-9]+]] = { nounwind }
278;.
279; LOWERING: [[META0]] = !{i64 6699318081062747564}
280; LOWERING: [[META1]] = !{i64 4909520559318251808}
281; LOWERING: [[META2]] = !{i64 -6371873725078000974}
282; LOWERING: [[META3]] = !{i64 -3006003237940970099}
283; LOWERING: [[META4]] = !{i64 5679753335911435902}
284; LOWERING: [[META5]] = !{i64 5458232184388660970}
285; LOWERING: [[META6]] = !{i64 -3771893999295659109}
286;.
287