[lld-link] Use COFFSyncStream
[llvm-project.git] / llvm / test / Transforms / MemProfContextDisambiguation / overlapping-contexts.ll
blob7fe9dc96921c6a4f04eb07936215691a84348ee2
1 ;; This test ensures that the logic which assigns calls to stack nodes
2 ;; correctly handles cloning of a callsite for a trimmed cold context
3 ;; that partially overlaps with a longer context for a different allocation.
5 ;; The profile data and call stacks were all manually added, but the code
6 ;; would be structured something like the following (fairly contrived to
7 ;; result in the type of control flow needed to test):
9 ;; void A(bool b) {
10 ;;   if (b)
11 ;;     // cold: stack ids 10, 12, 13, 15 (trimmed ids 19, 20)
12 ;;     // not cold: stack ids 10, 12, 13, 14 (trimmed id 21)
13 ;;     new char[10]; // stack id 10
14 ;;   else
15 ;;     // not cold: stack ids 11, 12, 13, 15, 16, 17 (trimmed id 22)
16 ;;     // cold: stack ids 11, 12, 13, 15, 16, 18 (trimmed id 23)
17 ;;     new char[10]; // stack id 11
18 ;; }
20 ;; void X(bool b) {
21 ;;   A(b); // stack ids 12
22 ;; }
24 ;; void B(bool b) {
25 ;;   X(b); // stack id 13
26 ;; }
28 ;; void D() {
29 ;;   B(true); // stack id 14
30 ;; }
32 ;; void C(bool b) {
33 ;;   B(b); // stack id 15
34 ;; }
36 ;; void E(bool b) {
37 ;;   C(b); // stack id 16
38 ;; }
40 ;; void F() {
41 ;;   E(false); // stack id 17
42 ;; }
44 ;; void G() {
45 ;;   E(false); // stack id 18
46 ;; }
48 ;; void M() {
49 ;;   C(true); // stack id 19
50 ;; }
52 ;; int main() {
53 ;;   D(); // stack id 20 (leads to not cold allocation)
54 ;;   M(); // stack id 21 (leads to cold allocation)
55 ;;   F(); // stack id 22 (leads to not cold allocation)
56 ;;   G(); // stack id 23 (leads to cold allocation)
57 ;; }
59 ;; -stats requires asserts
60 ; REQUIRES: asserts
62 ; RUN: opt -passes=memprof-context-disambiguation -supports-hot-cold-new \
63 ; RUN:  -memprof-verify-ccg -memprof-verify-nodes \
64 ; RUN:  -stats -pass-remarks=memprof-context-disambiguation \
65 ; RUN:  %s -S 2>&1 | FileCheck %s --check-prefix=IR \
66 ; RUN:  --check-prefix=STATS --check-prefix=REMARKS
68 ; REMARKS: created clone _Z1Ab.memprof.1
69 ; REMARKS: created clone _Z1Xb.memprof.1
70 ; REMARKS: created clone _Z1Bb.memprof.1
71 ; REMARKS: created clone _Z1Cb.memprof.1
72 ; REMARKS: created clone _Z1Eb.memprof.1
73 ; REMARKS: call in clone _Z1Gv assigned to call function clone _Z1Eb.memprof.1
74 ; REMARKS: call in clone _Z1Eb.memprof.1 assigned to call function clone _Z1Cb.memprof.1
75 ;; If we don't perform cloning for each allocation separately, we will miss
76 ;; cloning _Z1Cb for the trimmed cold allocation context leading to the
77 ;; allocation at stack id 10.
78 ; REMARKS: call in clone _Z1Cb.memprof.1 assigned to call function clone _Z1Bb.memprof.1
79 ; REMARKS: call in clone _Z1Fv assigned to call function clone _Z1Eb
80 ; REMARKS: call in clone _Z1Eb assigned to call function clone _Z1Cb
81 ; REMARKS: call in clone _Z1Cb assigned to call function clone _Z1Bb.memprof.1
82 ; REMARKS: call in clone _Z1Bb.memprof.1 assigned to call function clone _Z1Xb.memprof.1
83 ; REMARKS: call in clone _Z1Xb.memprof.1 assigned to call function clone _Z1Ab.memprof.1
84 ; REMARKS: call in clone _Z1Ab.memprof.1 marked with memprof allocation attribute cold
85 ; REMARKS: call in clone _Z1Bb.memprof.1 assigned to call function clone _Z1Xb
86 ; REMARKS: call in clone _Z1Dv assigned to call function clone _Z1Bb
87 ; REMARKS: call in clone _Z1Bb assigned to call function clone _Z1Xb
88 ; REMARKS: call in clone _Z1Xb assigned to call function clone _Z1Ab
89 ; REMARKS: call in clone _Z1Ab marked with memprof allocation attribute notcold
90 ; REMARKS: call in clone _Z1Ab.memprof.1 marked with memprof allocation attribute cold
91 ; REMARKS: call in clone _Z1Ab marked with memprof allocation attribute notcold
94 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
95 target triple = "x86_64-unknown-linux-gnu"
97 define dso_local void @_Z1Ab(i1 noundef zeroext %b) {
98 entry:
99   br i1 %b, label %if.then, label %if.else
101 if.then:
102   %call = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #7, !memprof !0, !callsite !10
103   br label %if.end
105 if.else:
106   %call2 = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #7, !memprof !5, !callsite !11
107   br label %if.end
109 if.end:
110   ret void
113 ; Function Attrs: nobuiltin
114 declare ptr @_Znam(i64) #0
116 define dso_local void @_Z1Xb(i1 noundef zeroext %b) {
117 entry:
118   tail call void @_Z1Ab(i1 noundef zeroext %b), !callsite !12
119   ret void
122 define dso_local void @_Z1Bb(i1 noundef zeroext %b) {
123 entry:
124   tail call void @_Z1Xb(i1 noundef zeroext %b), !callsite !13
125   ret void
128 define dso_local void @_Z1Dv() {
129 entry:
130   tail call void @_Z1Bb(i1 noundef zeroext true), !callsite !14
131   ret void
134 define dso_local void @_Z1Cb(i1 noundef zeroext %b) {
135 entry:
136   tail call void @_Z1Bb(i1 noundef zeroext %b), !callsite !15
137   ret void
140 define dso_local void @_Z1Eb(i1 noundef zeroext %b) {
141 entry:
142   tail call void @_Z1Cb(i1 noundef zeroext %b), !callsite !16
143   ret void
146 define dso_local void @_Z1Fv() {
147 entry:
148   tail call void @_Z1Eb(i1 noundef zeroext false), !callsite !17
149   ret void
152 define dso_local void @_Z1Gv() {
153 entry:
154   tail call void @_Z1Eb(i1 noundef zeroext false), !callsite !18
155   ret void
158 define dso_local void @_Z1Mv() {
159 entry:
160   tail call void @_Z1Cb(i1 noundef zeroext true), !callsite !19
161   ret void
164 define dso_local noundef i32 @main() local_unnamed_addr {
165 entry:
166   tail call void @_Z1Dv(), !callsite !20 ;; Not cold context
167   tail call void @_Z1Mv(), !callsite !21 ;; Cold context
168   tail call void @_Z1Fv(), !callsite !22 ;; Not cold context
169   tail call void @_Z1Gv(), !callsite !23 ;; Cold context
170   ret i32 0
173 attributes #0 = { nobuiltin }
174 attributes #7 = { builtin }
176 !0 = !{!1, !3}
177 ;; Cold (trimmed) context via call to _Z1Dv in main
178 !1 = !{!2, !"cold"}
179 !2 = !{i64 10, i64 12, i64 13, i64 15}
180 ;; Not cold (trimmed) context via call to _Z1Mv in main
181 !3 = !{!4, !"notcold"}
182 !4 = !{i64 10, i64 12, i64 13, i64 14}
183 !5 = !{!6, !8}
184 ;; Not cold (trimmed) context via call to _Z1Fv in main
185 !6 = !{!7, !"notcold"}
186 !7 = !{i64 11, i64 12, i64 13, i64 15, i64 16, i64 17}
187 ;; Cold (trimmed) context via call to _Z1Gv in main
188 !8 = !{!9, !"cold"}
189 !9 = !{i64 11, i64 12, i64 13, i64 15, i64 16, i64 18}
190 !10 = !{i64 10}
191 !11 = !{i64 11}
192 !12 = !{i64 12}
193 !13 = !{i64 13}
194 !14 = !{i64 14}
195 !15 = !{i64 15}
196 !16 = !{i64 16}
197 !17 = !{i64 17}
198 !18 = !{i64 18}
199 !19 = !{i64 19}
200 !20 = !{i64 20}
201 !21 = !{i64 21}
202 !22 = !{i64 22}
203 !23 = !{i64 23}
205 ; IR: define {{.*}} @_Z1Cb(i1 noundef zeroext %b)
206 ; IR-NEXT: entry:
207 ; IR-NEXT:   call {{.*}} @_Z1Bb.memprof.1(i1 noundef zeroext %b)
209 ; IR: define {{.*}} @_Z1Ab.memprof.1(i1 noundef zeroext %b)
210 ; IR-NEXT: entry:
211 ; IR-NEXT:   br i1 %b, label %if.then, label %if.else
212 ; IR-EMPTY:
213 ; IR-NEXT: if.then:
214 ; IR-NEXT:   call {{.*}} @_Znam(i64 noundef 10) #[[COLD:[0-9]+]]
215 ; IR-NEXT:   br label %if.end
216 ; IR-EMPTY:
217 ; IR-NEXT: if.else:
218 ; IR-NEXT:   call {{.*}} @_Znam(i64 noundef 10) #[[COLD]]
220 ; IR: define {{.*}} @_Z1Xb.memprof.1(i1 noundef zeroext %b)
221 ; IR-NEXT: entry:
222 ; IR-NEXT:   call {{.*}} @_Z1Ab.memprof.1(i1 noundef zeroext %b)
224 ; IR: define {{.*}} @_Z1Bb.memprof.1(i1 noundef zeroext %b)
225 ; IR-NEXT: entry:
226 ; IR-NEXT:   call {{.*}} @_Z1Xb.memprof.1(i1 noundef zeroext %b)
228 ; IR: attributes #[[COLD]] = { builtin "memprof"="cold" }
230 ; STATS: 2 memprof-context-disambiguation - Number of cold static allocations (possibly cloned)
231 ; STATS: 2 memprof-context-disambiguation - Number of not cold static allocations (possibly cloned)
232 ; STATS: 5 memprof-context-disambiguation - Number of function clones created during whole program analysis