xref: /llvm-project/llvm/test/Transforms/SimplifyCFG/speculatively-execute-block-profmd.ll (revision 07b9d231ff9baa6473b0dd588a3ce5330d3e4871)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -two-entry-phi-node-folding-threshold=0 -phi-node-folding-threshold=4 < %s | FileCheck %s
3
4declare void @sideeffect0()
5declare void @sideeffect1()
6declare void @sideeffect2()
7
8define i32 @unknown(i1 %c, i32 %a, i32 %b) {
9; CHECK-LABEL: @unknown(
10; CHECK-NEXT:  entry:
11; CHECK-NEXT:    call void @sideeffect0()
12; CHECK-NEXT:    br i1 [[C:%.*]], label [[DISPATCH:%.*]], label [[END:%.*]]
13; CHECK:       dispatch:
14; CHECK-NEXT:    call void @sideeffect1()
15; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
16; CHECK-NEXT:    [[VAL:%.*]] = add i32 [[A]], [[B]]
17; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[CMP]], i32 [[VAL]], i32 0
18; CHECK-NEXT:    br label [[END]]
19; CHECK:       end:
20; CHECK-NEXT:    [[RES:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[SPEC_SELECT]], [[DISPATCH]] ]
21; CHECK-NEXT:    call void @sideeffect2()
22; CHECK-NEXT:    ret i32 [[RES]]
23;
24entry:
25  call void @sideeffect0()
26  br i1 %c, label %dispatch, label %end
27
28dispatch:
29  call void @sideeffect1()
30  %cmp = icmp eq i32 %a, %b
31  br i1 %cmp, label %cond.true, label %end
32
33cond.true:
34  %val = add i32 %a, %b
35  br label %end
36
37end:
38  %res = phi i32 [ -1, %entry ], [ 0, %dispatch ], [ %val, %cond.true ]
39  call void @sideeffect2()
40  ret i32 %res
41}
42
43define i32 @predictably_taken(i1 %c, i32 %a, i32 %b) {
44; CHECK-LABEL: @predictably_taken(
45; CHECK-NEXT:  entry:
46; CHECK-NEXT:    call void @sideeffect0()
47; CHECK-NEXT:    br i1 [[C:%.*]], label [[DISPATCH:%.*]], label [[END:%.*]]
48; CHECK:       dispatch:
49; CHECK-NEXT:    call void @sideeffect1()
50; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
51; CHECK-NEXT:    [[VAL:%.*]] = add i32 [[A]], [[B]]
52; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[CMP]], i32 [[VAL]], i32 0, !prof [[PROF0:![0-9]+]]
53; CHECK-NEXT:    br label [[END]]
54; CHECK:       end:
55; CHECK-NEXT:    [[RES:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[SPEC_SELECT]], [[DISPATCH]] ]
56; CHECK-NEXT:    call void @sideeffect2()
57; CHECK-NEXT:    ret i32 [[RES]]
58;
59entry:
60  call void @sideeffect0()
61  br i1 %c, label %dispatch, label %end
62
63dispatch:
64  call void @sideeffect1()
65  %cmp = icmp eq i32 %a, %b
66  br i1 %cmp, label %cond.true, label %end, !prof !0 ; likely branches to %cond.true
67
68cond.true:
69  %val = add i32 %a, %b
70  br label %end
71
72end:
73  %res = phi i32 [ -1, %entry ], [ 0, %dispatch ], [ %val, %cond.true ]
74  call void @sideeffect2()
75  ret i32 %res
76}
77
78define i32 @predictably_nontaken(i1 %c, i32 %a, i32 %b) {
79; CHECK-LABEL: @predictably_nontaken(
80; CHECK-NEXT:  entry:
81; CHECK-NEXT:    call void @sideeffect0()
82; CHECK-NEXT:    br i1 [[C:%.*]], label [[DISPATCH:%.*]], label [[END:%.*]]
83; CHECK:       dispatch:
84; CHECK-NEXT:    call void @sideeffect1()
85; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
86; CHECK-NEXT:    br i1 [[CMP]], label [[END]], label [[COND_TRUE:%.*]], !prof [[PROF0]]
87; CHECK:       cond.true:
88; CHECK-NEXT:    [[VAL:%.*]] = add i32 [[A]], [[B]]
89; CHECK-NEXT:    br label [[END]]
90; CHECK:       end:
91; CHECK-NEXT:    [[RES:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ 0, [[DISPATCH]] ], [ [[VAL]], [[COND_TRUE]] ]
92; CHECK-NEXT:    call void @sideeffect2()
93; CHECK-NEXT:    ret i32 [[RES]]
94;
95entry:
96  call void @sideeffect0()
97  br i1 %c, label %dispatch, label %end
98
99dispatch:
100  call void @sideeffect1()
101  %cmp = icmp eq i32 %a, %b
102  br i1 %cmp, label %end, label %cond.true, !prof !0 ; likely branches to %end
103
104cond.true:
105  %val = add i32 %a, %b
106  br label %end
107
108end:
109  %res = phi i32 [ -1, %entry ], [ 0, %dispatch ], [ %val, %cond.true ]
110  call void @sideeffect2()
111  ret i32 %res
112}
113
114define i32 @almost_predictably_nontaken(i1 %c, i32 %a, i32 %b) {
115; CHECK-LABEL: @almost_predictably_nontaken(
116; CHECK-NEXT:  entry:
117; CHECK-NEXT:    call void @sideeffect0()
118; CHECK-NEXT:    br i1 [[C:%.*]], label [[DISPATCH:%.*]], label [[END:%.*]]
119; CHECK:       dispatch:
120; CHECK-NEXT:    call void @sideeffect1()
121; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
122; CHECK-NEXT:    [[VAL:%.*]] = add i32 [[A]], [[B]]
123; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[CMP]], i32 0, i32 [[VAL]], !prof [[PROF1:![0-9]+]]
124; CHECK-NEXT:    br label [[END]]
125; CHECK:       end:
126; CHECK-NEXT:    [[RES:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[SPEC_SELECT]], [[DISPATCH]] ]
127; CHECK-NEXT:    call void @sideeffect2()
128; CHECK-NEXT:    ret i32 [[RES]]
129;
130entry:
131  call void @sideeffect0()
132  br i1 %c, label %dispatch, label %end
133
134dispatch:
135  call void @sideeffect1()
136  %cmp = icmp eq i32 %a, %b
137  br i1 %cmp, label %end, label %cond.true, !prof !1 ; almost likely branches to %end
138
139cond.true:
140  %val = add i32 %a, %b
141  br label %end
142
143end:
144  %res = phi i32 [ -1, %entry ], [ 0, %dispatch ], [ %val, %cond.true ]
145  call void @sideeffect2()
146  ret i32 %res
147}
148
149define i32 @unpredictable(i1 %c, i32 %a, i32 %b) {
150; CHECK-LABEL: @unpredictable(
151; CHECK-NEXT:  entry:
152; CHECK-NEXT:    call void @sideeffect0()
153; CHECK-NEXT:    br i1 [[C:%.*]], label [[DISPATCH:%.*]], label [[END:%.*]]
154; CHECK:       dispatch:
155; CHECK-NEXT:    call void @sideeffect1()
156; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
157; CHECK-NEXT:    [[VAL:%.*]] = add i32 [[A]], [[B]]
158; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[CMP]], i32 [[VAL]], i32 0, !unpredictable [[META2:![0-9]+]]
159; CHECK-NEXT:    br label [[END]]
160; CHECK:       end:
161; CHECK-NEXT:    [[RES:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[SPEC_SELECT]], [[DISPATCH]] ]
162; CHECK-NEXT:    call void @sideeffect2()
163; CHECK-NEXT:    ret i32 [[RES]]
164;
165entry:
166  call void @sideeffect0()
167  br i1 %c, label %dispatch, label %end
168
169dispatch:
170  call void @sideeffect1()
171  %cmp = icmp eq i32 %a, %b
172  br i1 %cmp, label %cond.true, label %end, !unpredictable !2 ; unpredictable
173
174cond.true:
175  %val = add i32 %a, %b
176  br label %end
177
178end:
179  %res = phi i32 [ -1, %entry ], [ 0, %dispatch ], [ %val, %cond.true ]
180  call void @sideeffect2()
181  ret i32 %res
182}
183
184define i32 @unpredictable_yet_taken(i1 %c, i32 %a, i32 %b) {
185; CHECK-LABEL: @unpredictable_yet_taken(
186; CHECK-NEXT:  entry:
187; CHECK-NEXT:    call void @sideeffect0()
188; CHECK-NEXT:    br i1 [[C:%.*]], label [[DISPATCH:%.*]], label [[END:%.*]]
189; CHECK:       dispatch:
190; CHECK-NEXT:    call void @sideeffect1()
191; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
192; CHECK-NEXT:    [[VAL:%.*]] = add i32 [[A]], [[B]]
193; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[CMP]], i32 [[VAL]], i32 0, !prof [[PROF0]], !unpredictable [[META2]]
194; CHECK-NEXT:    br label [[END]]
195; CHECK:       end:
196; CHECK-NEXT:    [[RES:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[SPEC_SELECT]], [[DISPATCH]] ]
197; CHECK-NEXT:    call void @sideeffect2()
198; CHECK-NEXT:    ret i32 [[RES]]
199;
200entry:
201  call void @sideeffect0()
202  br i1 %c, label %dispatch, label %end
203
204dispatch:
205  call void @sideeffect1()
206  %cmp = icmp eq i32 %a, %b
207  br i1 %cmp, label %cond.true, label %end, !prof !0, !unpredictable !2 ; likely branches to %cond.true, yet unpredictable
208
209cond.true:
210  %val = add i32 %a, %b
211  br label %end
212
213end:
214  %res = phi i32 [ -1, %entry ], [ 0, %dispatch ], [ %val, %cond.true ]
215  call void @sideeffect2()
216  ret i32 %res
217}
218
219define i32 @unpredictable_yet_nontaken(i1 %c, i32 %a, i32 %b) {
220; CHECK-LABEL: @unpredictable_yet_nontaken(
221; CHECK-NEXT:  entry:
222; CHECK-NEXT:    call void @sideeffect0()
223; CHECK-NEXT:    br i1 [[C:%.*]], label [[DISPATCH:%.*]], label [[END:%.*]]
224; CHECK:       dispatch:
225; CHECK-NEXT:    call void @sideeffect1()
226; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
227; CHECK-NEXT:    [[VAL:%.*]] = add i32 [[A]], [[B]]
228; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[CMP]], i32 0, i32 [[VAL]], !prof [[PROF0]], !unpredictable [[META2]]
229; CHECK-NEXT:    br label [[END]]
230; CHECK:       end:
231; CHECK-NEXT:    [[RES:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[SPEC_SELECT]], [[DISPATCH]] ]
232; CHECK-NEXT:    call void @sideeffect2()
233; CHECK-NEXT:    ret i32 [[RES]]
234;
235entry:
236  call void @sideeffect0()
237  br i1 %c, label %dispatch, label %end
238
239dispatch:
240  call void @sideeffect1()
241  %cmp = icmp eq i32 %a, %b
242  br i1 %cmp, label %end, label %cond.true, !prof !0, !unpredictable !2 ; likely branches to %end, yet unpredictable
243
244cond.true:
245  %val = add i32 %a, %b
246  br label %end
247
248end:
249  %res = phi i32 [ -1, %entry ], [ 0, %dispatch ], [ %val, %cond.true ]
250  call void @sideeffect2()
251  ret i32 %res
252}
253
254!0 = !{!"branch_weights", i32 99, i32 1}
255!1 = !{!"branch_weights", i32 70, i32 1}
256!2 = !{}
257
258; CHECK: !0 = !{!"branch_weights", i32 99, i32 1}
259; CHECK: !1 = !{!"branch_weights", i32 70, i32 1}
260; CHECK: !2 = !{}
261