1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2 ; RUN: opt -S -passes=guard-widening < %s | FileCheck %s
4 ; Hot loop, frequently entered, should widen.
5 define i32 @test_intrinsic_very_profitable(i32 %n, i1 %cond.1, i1 %cond.2) {
6 ; CHECK-LABEL: define i32 @test_intrinsic_very_profitable
7 ; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {
9 ; CHECK-NEXT: [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]
10 ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]
11 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
12 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
13 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0:![0-9]+]]
15 ; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
16 ; CHECK-NEXT: ret i32 [[DEOPTCALL]]
18 ; CHECK-NEXT: [[LOOP_PRECONDITION:%.*]] = icmp uge i32 [[N]], 100
19 ; CHECK-NEXT: br i1 [[LOOP_PRECONDITION]], label [[LOOP:%.*]], label [[FAILED:%.*]], !prof [[PROF0]]
21 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[GUARDED]] ], [ [[IV_NEXT:%.*]], [[GUARDED1:%.*]] ]
22 ; CHECK-NEXT: [[WIDENABLE_COND4:%.*]] = call i1 @llvm.experimental.widenable.condition()
23 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND5:%.*]] = and i1 [[COND_2_GW_FR]], [[WIDENABLE_COND4]]
24 ; CHECK-NEXT: br i1 true, label [[GUARDED1]], label [[DEOPT2:%.*]], !prof [[PROF0]]
26 ; CHECK-NEXT: [[DEOPTCALL3:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
27 ; CHECK-NEXT: ret i32 [[DEOPTCALL3]]
29 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
30 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 100
31 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]], !prof [[PROF1:![0-9]+]]
33 ; CHECK-NEXT: ret i32 0
35 ; CHECK-NEXT: ret i32 -1
38 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
39 %exiplicit_guard_cond = and i1 %cond.1, %widenable_cond
40 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
42 deopt: ; preds = %entry
43 %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
46 guarded: ; preds = %entry
47 %loop.precondition = icmp uge i32 %n, 100
48 br i1 %loop.precondition, label %loop, label %failed, !prof !0
50 loop: ; preds = %guarded1, %guarded
51 %iv = phi i32 [ 0, %guarded ], [ %iv.next, %guarded1 ]
52 %widenable_cond4 = call i1 @llvm.experimental.widenable.condition()
53 %exiplicit_guard_cond5 = and i1 %cond.2, %widenable_cond4
54 br i1 %exiplicit_guard_cond5, label %guarded1, label %deopt2, !prof !0
56 deopt2: ; preds = %loop
57 %deoptcall3 = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
60 guarded1: ; preds = %loop
61 %iv.next = add nuw nsw i32 %iv, 1
62 %loop.cond = icmp ult i32 %iv.next, 100
63 br i1 %loop.cond, label %loop, label %exit, !prof !1
65 exit: ; preds = %guarded1
68 failed: ; preds = %guarded
72 ; Even though the loop is rarely entered, it has so many iterations that the widening
73 ; is still profitable.
74 define i32 @test_intrinsic_profitable(i32 %n, i1 %cond.1, i1 %cond.2) {
75 ; CHECK-LABEL: define i32 @test_intrinsic_profitable
76 ; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {
78 ; CHECK-NEXT: [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]
79 ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]
80 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
81 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
82 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
84 ; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
85 ; CHECK-NEXT: ret i32 [[DEOPTCALL]]
87 ; CHECK-NEXT: [[LOOP_PRECONDITION:%.*]] = icmp uge i32 [[N]], 100
88 ; CHECK-NEXT: br i1 [[LOOP_PRECONDITION]], label [[LOOP:%.*]], label [[FAILED:%.*]], !prof [[PROF2:![0-9]+]]
90 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[GUARDED]] ], [ [[IV_NEXT:%.*]], [[GUARDED1:%.*]] ]
91 ; CHECK-NEXT: [[WIDENABLE_COND4:%.*]] = call i1 @llvm.experimental.widenable.condition()
92 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND5:%.*]] = and i1 [[COND_2_GW_FR]], [[WIDENABLE_COND4]]
93 ; CHECK-NEXT: br i1 true, label [[GUARDED1]], label [[DEOPT2:%.*]], !prof [[PROF0]]
95 ; CHECK-NEXT: [[DEOPTCALL3:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
96 ; CHECK-NEXT: ret i32 [[DEOPTCALL3]]
98 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
99 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 100
100 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]], !prof [[PROF1]]
102 ; CHECK-NEXT: ret i32 0
104 ; CHECK-NEXT: ret i32 -1
107 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
108 %exiplicit_guard_cond = and i1 %cond.1, %widenable_cond
109 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
111 deopt: ; preds = %entry
112 %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
115 guarded: ; preds = %entry
116 %loop.precondition = icmp uge i32 %n, 100
117 br i1 %loop.precondition, label %loop, label %failed, !prof !2
119 loop: ; preds = %guarded1, %guarded
120 %iv = phi i32 [ 0, %guarded ], [ %iv.next, %guarded1 ]
121 %widenable_cond4 = call i1 @llvm.experimental.widenable.condition()
122 %exiplicit_guard_cond5 = and i1 %cond.2, %widenable_cond4
123 br i1 %exiplicit_guard_cond5, label %guarded1, label %deopt2, !prof !0
125 deopt2: ; preds = %loop
126 %deoptcall3 = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
129 guarded1: ; preds = %loop
130 %iv.next = add nuw nsw i32 %iv, 1
131 %loop.cond = icmp ult i32 %iv.next, 100
132 br i1 %loop.cond, label %loop, label %exit, !prof !1
134 exit: ; preds = %guarded1
137 failed: ; preds = %guarded
141 ; Loop's hotness compensates rareness of its entrance. We still want to widen, because
142 ; it may open up some optimization opportunities.
143 define i32 @test_intrinsic_neutral(i32 %n, i1 %cond.1, i1 %cond.2) {
144 ; CHECK-LABEL: define i32 @test_intrinsic_neutral
145 ; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {
147 ; CHECK-NEXT: [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]
148 ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]
149 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
150 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
151 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
153 ; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
154 ; CHECK-NEXT: ret i32 [[DEOPTCALL]]
156 ; CHECK-NEXT: [[LOOP_PRECONDITION:%.*]] = icmp uge i32 [[N]], 100
157 ; CHECK-NEXT: br i1 [[LOOP_PRECONDITION]], label [[LOOP:%.*]], label [[FAILED:%.*]], !prof [[PROF3:![0-9]+]]
159 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[GUARDED]] ], [ [[IV_NEXT:%.*]], [[GUARDED1:%.*]] ]
160 ; CHECK-NEXT: [[WIDENABLE_COND4:%.*]] = call i1 @llvm.experimental.widenable.condition()
161 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND5:%.*]] = and i1 [[COND_2_GW_FR]], [[WIDENABLE_COND4]]
162 ; CHECK-NEXT: br i1 true, label [[GUARDED1]], label [[DEOPT2:%.*]], !prof [[PROF0]]
164 ; CHECK-NEXT: [[DEOPTCALL3:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
165 ; CHECK-NEXT: ret i32 [[DEOPTCALL3]]
167 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
168 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 100
169 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]], !prof [[PROF1]]
171 ; CHECK-NEXT: ret i32 0
173 ; CHECK-NEXT: ret i32 -1
176 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
177 %exiplicit_guard_cond = and i1 %cond.1, %widenable_cond
178 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
180 deopt: ; preds = %entry
181 %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
184 guarded: ; preds = %entry
185 %loop.precondition = icmp uge i32 %n, 100
186 br i1 %loop.precondition, label %loop, label %failed, !prof !3
188 loop: ; preds = %guarded1, %guarded
189 %iv = phi i32 [ 0, %guarded ], [ %iv.next, %guarded1 ]
190 %widenable_cond4 = call i1 @llvm.experimental.widenable.condition()
191 %exiplicit_guard_cond5 = and i1 %cond.2, %widenable_cond4
192 br i1 %exiplicit_guard_cond5, label %guarded1, label %deopt2, !prof !0
194 deopt2: ; preds = %loop
195 %deoptcall3 = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
198 guarded1: ; preds = %loop
199 %iv.next = add nuw nsw i32 %iv, 1
200 %loop.cond = icmp ult i32 %iv.next, 100
201 br i1 %loop.cond, label %loop, label %exit, !prof !1
203 exit: ; preds = %guarded1
206 failed: ; preds = %guarded
210 ; FIXME: This loop is so rarely entered, that we don't want to widen here.
211 define i32 @test_intrinsic_very_unprofitable(i32 %n, i1 %cond.1, i1 %cond.2) {
212 ; CHECK-LABEL: define i32 @test_intrinsic_very_unprofitable
213 ; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {
215 ; CHECK-NEXT: [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]
216 ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]
217 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
218 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
219 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
221 ; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
222 ; CHECK-NEXT: ret i32 [[DEOPTCALL]]
224 ; CHECK-NEXT: [[LOOP_PRECONDITION:%.*]] = icmp uge i32 [[N]], 100
225 ; CHECK-NEXT: br i1 [[LOOP_PRECONDITION]], label [[LOOP:%.*]], label [[FAILED:%.*]], !prof [[PROF4:![0-9]+]]
227 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[GUARDED]] ], [ [[IV_NEXT:%.*]], [[GUARDED1:%.*]] ]
228 ; CHECK-NEXT: [[WIDENABLE_COND4:%.*]] = call i1 @llvm.experimental.widenable.condition()
229 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND5:%.*]] = and i1 [[COND_2_GW_FR]], [[WIDENABLE_COND4]]
230 ; CHECK-NEXT: br i1 true, label [[GUARDED1]], label [[DEOPT2:%.*]], !prof [[PROF0]]
232 ; CHECK-NEXT: [[DEOPTCALL3:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
233 ; CHECK-NEXT: ret i32 [[DEOPTCALL3]]
235 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
236 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 100
237 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]], !prof [[PROF1]]
239 ; CHECK-NEXT: ret i32 0
241 ; CHECK-NEXT: ret i32 -1
244 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
245 %exiplicit_guard_cond = and i1 %cond.1, %widenable_cond
246 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
248 deopt: ; preds = %entry
249 %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
252 guarded: ; preds = %entry
253 %loop.precondition = icmp uge i32 %n, 100
254 br i1 %loop.precondition, label %loop, label %failed, !prof !4
256 loop: ; preds = %guarded1, %guarded
257 %iv = phi i32 [ 0, %guarded ], [ %iv.next, %guarded1 ]
258 %widenable_cond4 = call i1 @llvm.experimental.widenable.condition()
259 %exiplicit_guard_cond5 = and i1 %cond.2, %widenable_cond4
260 br i1 %exiplicit_guard_cond5, label %guarded1, label %deopt2, !prof !0
262 deopt2: ; preds = %loop
263 %deoptcall3 = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
266 guarded1: ; preds = %loop
267 %iv.next = add nuw nsw i32 %iv, 1
268 %loop.cond = icmp ult i32 %iv.next, 100
269 br i1 %loop.cond, label %loop, label %exit, !prof !1
271 exit: ; preds = %guarded1
274 failed: ; preds = %guarded
278 ; FIXME: This loop is so rarely entered, that we don't want to widen here.
279 define i32 @test_intrinsic_unprofitable(i32 %n, i1 %cond.1, i1 %cond.2) {
280 ; CHECK-LABEL: define i32 @test_intrinsic_unprofitable
281 ; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {
283 ; CHECK-NEXT: [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]
284 ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]
285 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
286 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
287 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
289 ; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
290 ; CHECK-NEXT: ret i32 [[DEOPTCALL]]
292 ; CHECK-NEXT: [[LOOP_PRECONDITION:%.*]] = icmp uge i32 [[N]], 100
293 ; CHECK-NEXT: br i1 [[LOOP_PRECONDITION]], label [[LOOP:%.*]], label [[FAILED:%.*]], !prof [[PROF5:![0-9]+]]
295 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[GUARDED]] ], [ [[IV_NEXT:%.*]], [[GUARDED1:%.*]] ]
296 ; CHECK-NEXT: [[WIDENABLE_COND4:%.*]] = call i1 @llvm.experimental.widenable.condition()
297 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND5:%.*]] = and i1 [[COND_2_GW_FR]], [[WIDENABLE_COND4]]
298 ; CHECK-NEXT: br i1 true, label [[GUARDED1]], label [[DEOPT2:%.*]], !prof [[PROF0]]
300 ; CHECK-NEXT: [[DEOPTCALL3:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
301 ; CHECK-NEXT: ret i32 [[DEOPTCALL3]]
303 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
304 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 100
305 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]], !prof [[PROF1]]
307 ; CHECK-NEXT: ret i32 0
309 ; CHECK-NEXT: ret i32 -1
312 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
313 %exiplicit_guard_cond = and i1 %cond.1, %widenable_cond
314 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
316 deopt: ; preds = %entry
317 %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
320 guarded: ; preds = %entry
321 %loop.precondition = icmp uge i32 %n, 100
322 br i1 %loop.precondition, label %loop, label %failed, !prof !5
324 loop: ; preds = %guarded1, %guarded
325 %iv = phi i32 [ 0, %guarded ], [ %iv.next, %guarded1 ]
326 %widenable_cond4 = call i1 @llvm.experimental.widenable.condition()
327 %exiplicit_guard_cond5 = and i1 %cond.2, %widenable_cond4
328 br i1 %exiplicit_guard_cond5, label %guarded1, label %deopt2, !prof !0
330 deopt2: ; preds = %loop
331 %deoptcall3 = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
334 guarded1: ; preds = %loop
335 %iv.next = add nuw nsw i32 %iv, 1
336 %loop.cond = icmp ult i32 %iv.next, 100
337 br i1 %loop.cond, label %loop, label %exit, !prof !1
339 exit: ; preds = %guarded1
342 failed: ; preds = %guarded
346 declare i32 @llvm.experimental.deoptimize.i32(...)
348 ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(inaccessiblemem: readwrite)
349 declare noundef i1 @llvm.experimental.widenable.condition() #1
351 attributes #0 = { nocallback nofree nosync willreturn }
352 attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(inaccessiblemem: readwrite) }
354 !0 = !{!"branch_weights", i32 1048576, i32 1}
355 !1 = !{!"branch_weights", i32 99, i32 1}
356 !2 = !{!"branch_weights", i32 1, i32 10}
357 !3 = !{!"branch_weights", i32 1, i32 99}
358 !4 = !{!"branch_weights", i32 1, i32 1048576}
359 !5 = !{!"branch_weights", i32 1, i32 1000}