1 ; RUN: opt -loop-unswitch -loop-unswitch-threshold=10 -verify-dom-info -verify-memoryssa -S -enable-new-pm=0 %s | FileCheck %s
3 declare void @clobber()
5 ; Test cases for partial unswitching, where the regular cost-model overestimates
6 ; the cost of unswitching, because it misses the fact that the unswitched paths
10 define i32 @no_partial_unswitch_size_too_large_no_mustprogress(i32* %ptr, i32 %N) {
11 ; CHECK-LABEL: @no_partial_unswitch_size_too_large_no_mustprogress
13 ; CHECK-NEXT: br label %loop.header
19 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
20 %lv = load i32, i32* %ptr
21 %sc = icmp eq i32 %lv, 100
22 br i1 %sc, label %noclobber, label %clobber
40 %c = icmp ult i32 %iv, %N
41 %iv.next = add i32 %iv, 1
42 br i1 %c, label %loop.header, label %exit
48 define i32 @partial_unswitch_shortcut_mustprogress(i32* %ptr, i32 %N) mustprogress {
49 ; CHECK-LABEL: @partial_unswitch_shortcut_mustprogress
51 ; CHECK-NEXT: [[LV:%[0-9]+]] = load i32, i32* %ptr, align 4
52 ; CHECK-NEXT: [[C:%[0-9]+]] = icmp eq i32 [[LV]], 100
53 ; CHECK-NEXT: br i1 [[C]], label %[[CRIT_TO_EXIT:[a-z._]+]], label %[[CRIT_TO_HEADER:[a-z._]+]]
55 ; CHECK: [[CRIT_TO_HEADER]]:
56 ; CHECK-NEXT: br label %loop.header
58 ; CHECK: [[CRIT_TO_EXIT]]:
59 ; CHECK-NEXT: br label %exit
65 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
66 %lv = load i32, i32* %ptr
67 %sc = icmp eq i32 %lv, 100
68 br i1 %sc, label %noclobber, label %clobber
86 %c = icmp ult i32 %iv, %N
87 %iv.next = add i32 %iv, 1
88 br i1 %c, label %loop.header, label %exit
94 define i32 @partial_unswitch_shortcut_mustprogress_single_exit_on_path(i32* %ptr, i32 %N) mustprogress {
95 ; CHECK-LABEL: @partial_unswitch_shortcut_mustprogress_single_exit_on_path
97 ; CHECK-NEXT: [[LV:%[0-9]+]] = load i32, i32* %ptr, align 4
98 ; CHECK-NEXT: [[C:%[0-9]+]] = icmp eq i32 [[LV]], 100
99 ; CHECK-NEXT: br i1 [[C]], label %[[CRIT_TO_EXIT:.+]], label %[[CRIT_TO_HEADER:[a-z._]+]]
101 ; CHECK: [[CRIT_TO_HEADER]]:
102 ; CHECK-NEXT: br label %loop.header
104 ; CHECK: [[CRIT_TO_EXIT]]:
105 ; CHECK-NEXT: br label %exit
108 br label %loop.header
111 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
112 %lv = load i32, i32* %ptr
113 %sc = icmp eq i32 %lv, 100
114 br i1 %sc, label %noclobber, label %clobber
117 %c.1 = icmp ult i32 %iv, 123
118 br i1 %c.1, label %loop.latch, label %exit.1
130 %c = icmp ult i32 %iv, %N
131 br i1 %c, label %loop.latch, label %exit.2
134 %iv.next = add i32 %iv, 1
135 br label %loop.header
144 define i32 @no_partial_unswitch_shortcut_mustprogress_no_exit_on_path(i32* %ptr, i32 %N) mustprogress {
145 ; CHECK-LABEL: @no_partial_unswitch_shortcut_mustprogress_no_exit_on_path
146 ; CHECK-LABEL: entry:
147 ; CHECK-NEXT: br label %loop.header
150 br label %loop.header
153 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
154 %lv = load i32, i32* %ptr
155 %sc = icmp eq i32 %lv, 100
156 br i1 %sc, label %noclobber, label %clobber
171 %c = icmp ult i32 %iv, %N
172 br i1 %c, label %loop.latch, label %exit
175 %iv.next = add i32 %iv, 1
176 br label %loop.header
182 define i32 @no_partial_unswitch_shortcut_mustprogress_exit_value_used(i32* %ptr, i32 %N) mustprogress {
183 ; CHECK-LABEL: @no_partial_unswitch_shortcut_mustprogress_exit_value_use
184 ; CHECK-LABEL: entry:
185 ; CHECK-NEXT: br label %loop.header
188 br label %loop.header
191 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
192 %red = phi i32 [ 0, %entry ], [ %red.next, %loop.latch ]
193 %lv = load i32, i32* %ptr
194 %sc = icmp eq i32 %lv, 100
195 br i1 %sc, label %noclobber, label %clobber
198 %red.add = add i32 %red, %lv
202 %red.mul = mul i32 %red, %lv
215 %red.next = phi i32 [ %red.add, %noclobber ], [ %red.mul, %clobber ]
216 %c = icmp ult i32 %iv, %N
217 %iv.next = add i32 %iv, 1
218 br i1 %c, label %loop.header, label %exit
224 define i32 @partial_unswitch_shortcut_multiple_exiting_blocks(i32* %ptr, i32 %N, i1 %ec.1) mustprogress {
225 ; CHECK-LABEL: @partial_unswitch_shortcut_multiple_exiting_blocks
226 ; CHECK-LABEL: entry:
227 ; CHECK-NEXT: [[LV:%[0-9]+]] = load i32, i32* %ptr, align 4
228 ; CHECK-NEXT: [[C:%[0-9]+]] = icmp eq i32 [[LV]], 100
229 ; CHECK-NEXT: br i1 [[C]], label %[[CRIT_TO_EXIT:.+]], label %[[CRIT_TO_HEADER:[a-z._]+]]
231 ; CHECK: [[CRIT_TO_HEADER]]:
232 ; CHECK-NEXT: br label %loop.header
234 ; CHECK: [[CRIT_TO_EXIT]]:
235 ; CHECK-NEXT: br label %exit
238 br label %loop.header
241 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
242 %lv = load i32, i32* %ptr
243 %sc = icmp eq i32 %lv, 100
244 br i1 %sc, label %noclobber, label %clobber
247 br i1 %ec.1, label %loop.latch, label %exit
262 %c = icmp ult i32 %iv, %N
263 %iv.next = add i32 %iv, 1
264 br i1 %c, label %loop.header, label %exit
270 define i32 @no_partial_unswitch_shortcut_multiple_exit_blocks(i32* %ptr, i32 %N, i1 %ec.1) mustprogress {
271 ; CHECK-LABEL: @no_partial_unswitch_shortcut_multiple_exit_blocks
272 ; CHECK-LABEL: entry:
273 ; CHECK-NEXT: br label %loop.header
276 br label %loop.header
279 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
280 %lv = load i32, i32* %ptr
281 %sc = icmp eq i32 %lv, 100
282 br i1 %sc, label %noclobber, label %clobber
285 br i1 %ec.1, label %loop.latch, label %exit.2
300 %c = icmp ult i32 %iv, %N
301 %iv.next = add i32 %iv, 1
302 br i1 %c, label %loop.header, label %exit.1
311 define i32 @no_partial_unswitch_shortcut_mustprogress_store(i32* %ptr, i32* noalias %dst, i32 %N) mustprogress {
312 ; CHECK-LABEL: @no_partial_unswitch_shortcut_mustprogress_store
313 ; CHECK-LABEL: entry:
314 ; CHECK-NEXT: br label %loop.header
317 br label %loop.header
320 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
321 %lv = load i32, i32* %ptr
322 %sc = icmp eq i32 %lv, 100
323 br i1 %sc, label %noclobber, label %clobber
326 store i32 0, i32* %dst
342 %c = icmp ult i32 %iv, %N
343 %iv.next = add i32 %iv, 1
344 br i1 %c, label %loop.header, label %exit
350 define i32 @no_partial_unswitch_shortcut_mustprogress_store2(i32* %ptr, i32* noalias %dst, i32 %N) mustprogress {
351 ; CHECK-LABEL: @no_partial_unswitch_shortcut_mustprogress_store
352 ; CHECK-LABEL: entry:
353 ; CHECK-NEXT: br label %loop.header
356 br label %loop.header
359 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
360 %lv = load i32, i32* %ptr
361 %sc = icmp eq i32 %lv, 100
362 br i1 %sc, label %noclobber, label %clobber
380 store i32 0, i32* %dst
381 %c = icmp ult i32 %iv, %N
382 %iv.next = add i32 %iv, 1
383 br i1 %c, label %loop.header, label %exit
389 define i32 @no_partial_unswitch_shortcut_mustprogress_store3(i32* %ptr, i32* noalias %dst, i32 %N) mustprogress {
390 ; CHECK-LABEL: @no_partial_unswitch_shortcut_mustprogress_store
391 ; CHECK-LABEL: entry:
392 ; CHECK-NEXT: br label %loop.header
395 br label %loop.header
398 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
399 store i32 0, i32* %dst
400 %lv = load i32, i32* %ptr
401 %sc = icmp eq i32 %lv, 100
402 br i1 %sc, label %noclobber, label %clobber
420 %c = icmp ult i32 %iv, %N
421 %iv.next = add i32 %iv, 1
422 br i1 %c, label %loop.header, label %exit