xref: /llvm-project/llvm/test/Transforms/IRCE/unsigned_comparisons_ugt.ll (revision 483e92468e597b73c646182bd755a0d5ef67d327)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
2; RUN: opt -verify-loop-info -irce-print-changed-loops -passes=irce -S < %s 2>&1 | FileCheck %s
3; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,irce' -S < %s 2>&1 | FileCheck %s
4
5; CHECK: irce: in function test_01: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
6; CHECK: irce: in function test_02: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
7; CHECK: irce: in function test_03: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
8; CHECK: irce: in function test_04: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
9; CHECK-NOT: irce: in function test_05: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
10; CHECK: irce: in function test_06: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
11
12; UGT condition for increasing loop.
13define void @test_01(ptr %arr, ptr %a_len_ptr) #0 {
14; CHECK-LABEL: define void @test_01
15; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
16; CHECK-NEXT:  entry:
17; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0:![0-9]+]]
18; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 0, [[EXIT_MAINLOOP_AT]]
19; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
20; CHECK:       loop.preheader:
21; CHECK-NEXT:    br label [[LOOP:%.*]]
22; CHECK:       loop:
23; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
24; CHECK-NEXT:    [[IDX_NEXT]] = add nuw nsw i32 [[IDX]], 1
25; CHECK-NEXT:    [[ABC:%.*]] = icmp ult i32 [[IDX]], [[EXIT_MAINLOOP_AT]]
26; CHECK-NEXT:    br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
27; CHECK:       in.bounds:
28; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
29; CHECK-NEXT:    store i32 0, ptr [[ADDR]], align 4
30; CHECK-NEXT:    [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], 100
31; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
32; CHECK-NEXT:    [[TMP2:%.*]] = xor i1 [[TMP1]], true
33; CHECK-NEXT:    br i1 [[TMP2]], label [[MAIN_EXIT_SELECTOR:%.*]], label [[LOOP]]
34; CHECK:       main.exit.selector:
35; CHECK-NEXT:    [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]
36; CHECK-NEXT:    [[TMP3:%.*]] = icmp ult i32 [[IDX_NEXT_LCSSA]], 101
37; CHECK-NEXT:    br i1 [[TMP3]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
38; CHECK:       main.pseudo.exit:
39; CHECK-NEXT:    [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
40; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
41; CHECK-NEXT:    br label [[POSTLOOP:%.*]]
42; CHECK:       out.of.bounds.loopexit:
43; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
44; CHECK:       out.of.bounds.loopexit1:
45; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
46; CHECK:       out.of.bounds:
47; CHECK-NEXT:    ret void
48; CHECK:       exit.loopexit:
49; CHECK-NEXT:    br label [[EXIT]]
50; CHECK:       exit:
51; CHECK-NEXT:    ret void
52; CHECK:       postloop:
53; CHECK-NEXT:    br label [[LOOP_POSTLOOP:%.*]]
54; CHECK:       loop.postloop:
55; CHECK-NEXT:    [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ]
56; CHECK-NEXT:    [[IDX_NEXT_POSTLOOP]] = add nuw nsw i32 [[IDX_POSTLOOP]], 1
57; CHECK-NEXT:    [[ABC_POSTLOOP:%.*]] = icmp ult i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]]
58; CHECK-NEXT:    br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
59; CHECK:       in.bounds.postloop:
60; CHECK-NEXT:    [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]]
61; CHECK-NEXT:    store i32 0, ptr [[ADDR_POSTLOOP]], align 4
62; CHECK-NEXT:    [[NEXT_POSTLOOP:%.*]] = icmp ugt i32 [[IDX_NEXT_POSTLOOP]], 100
63; CHECK-NEXT:    br i1 [[NEXT_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_POSTLOOP]], !llvm.loop [[LOOP1:![0-9]+]], !loop_constrainer.loop.clone [[META6:![0-9]+]]
64;
65
66entry:
67  %len = load i32, ptr %a_len_ptr, !range !0
68  br label %loop
69
70loop:
71  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
72  %idx.next = add nsw nuw i32 %idx, 1
73  %abc = icmp ult i32 %idx, %len
74  br i1 %abc, label %in.bounds, label %out.of.bounds
75
76in.bounds:
77  %addr = getelementptr i32, ptr %arr, i32 %idx
78  store i32 0, ptr %addr
79  %next = icmp ugt i32 %idx.next, 100
80  br i1 %next, label %exit, label %loop
81
82out.of.bounds:
83  ret void
84
85exit:
86  ret void
87}
88
89; UGT condition for decreasing loop.
90define void @test_02(ptr %arr, ptr %a_len_ptr) #0 {
91; CHECK-LABEL: define void @test_02
92; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
93; CHECK-NEXT:  entry:
94; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
95; CHECK-NEXT:    [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[LEN]], i32 1)
96; CHECK-NEXT:    [[EXIT_PRELOOP_AT:%.*]] = add nsw i32 [[UMAX]], -1
97; CHECK-NEXT:    [[TMP0:%.*]] = icmp ugt i32 100, [[EXIT_PRELOOP_AT]]
98; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]
99; CHECK:       loop.preloop.preheader:
100; CHECK-NEXT:    br label [[LOOP_PRELOOP:%.*]]
101; CHECK:       mainloop:
102; CHECK-NEXT:    br label [[LOOP:%.*]]
103; CHECK:       loop:
104; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_PRELOOP_COPY:%.*]], [[MAINLOOP:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ]
105; CHECK-NEXT:    [[IDX_NEXT]] = add i32 [[IDX]], -1
106; CHECK-NEXT:    [[ABC:%.*]] = icmp ult i32 [[IDX]], [[LEN]]
107; CHECK-NEXT:    br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
108; CHECK:       in.bounds:
109; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
110; CHECK-NEXT:    store i32 0, ptr [[ADDR]], align 4
111; CHECK-NEXT:    [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], 0
112; CHECK-NEXT:    br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
113; CHECK:       out.of.bounds.loopexit:
114; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
115; CHECK:       out.of.bounds.loopexit1:
116; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
117; CHECK:       out.of.bounds:
118; CHECK-NEXT:    ret void
119; CHECK:       exit.loopexit:
120; CHECK-NEXT:    br label [[EXIT:%.*]]
121; CHECK:       exit:
122; CHECK-NEXT:    ret void
123; CHECK:       loop.preloop:
124; CHECK-NEXT:    [[IDX_PRELOOP:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP:%.*]], [[IN_BOUNDS_PRELOOP:%.*]] ], [ 100, [[LOOP_PRELOOP_PREHEADER]] ]
125; CHECK-NEXT:    [[IDX_NEXT_PRELOOP]] = add i32 [[IDX_PRELOOP]], -1
126; CHECK-NEXT:    [[ABC_PRELOOP:%.*]] = icmp ult i32 [[IDX_PRELOOP]], [[LEN]]
127; CHECK-NEXT:    br i1 [[ABC_PRELOOP]], label [[IN_BOUNDS_PRELOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
128; CHECK:       in.bounds.preloop:
129; CHECK-NEXT:    [[ADDR_PRELOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_PRELOOP]]
130; CHECK-NEXT:    store i32 0, ptr [[ADDR_PRELOOP]], align 4
131; CHECK-NEXT:    [[NEXT_PRELOOP:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], 0
132; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], [[EXIT_PRELOOP_AT]]
133; CHECK-NEXT:    br i1 [[TMP1]], label [[LOOP_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop [[LOOP7:![0-9]+]], !loop_constrainer.loop.clone [[META6]]
134; CHECK:       preloop.exit.selector:
135; CHECK-NEXT:    [[IDX_NEXT_PRELOOP_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP]], [[IN_BOUNDS_PRELOOP]] ]
136; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP_LCSSA]], 0
137; CHECK-NEXT:    br i1 [[TMP2]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT]]
138; CHECK:       preloop.pseudo.exit:
139; CHECK-NEXT:    [[IDX_PRELOOP_COPY]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
140; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ 100, [[ENTRY]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
141; CHECK-NEXT:    br label [[MAINLOOP]]
142;
143
144entry:
145  %len = load i32, ptr %a_len_ptr, !range !0
146  br label %loop
147
148loop:
149  %idx = phi i32 [ 100, %entry ], [ %idx.next, %in.bounds ]
150  %idx.next = add i32 %idx, -1
151  %abc = icmp ult i32 %idx, %len
152  br i1 %abc, label %in.bounds, label %out.of.bounds
153
154in.bounds:
155  %addr = getelementptr i32, ptr %arr, i32 %idx
156  store i32 0, ptr %addr
157  %next = icmp ugt i32 %idx.next, 0
158  br i1 %next, label %loop, label %exit
159
160out.of.bounds:
161  ret void
162
163exit:
164  ret void
165}
166
167; Check SINT_MAX + 1, test is similar to test_01.
168define void @test_03(ptr %arr, ptr %a_len_ptr) #0 {
169; CHECK-LABEL: define void @test_03
170; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
171; CHECK-NEXT:  entry:
172; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
173; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 0, [[EXIT_MAINLOOP_AT]]
174; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
175; CHECK:       loop.preheader:
176; CHECK-NEXT:    br label [[LOOP:%.*]]
177; CHECK:       loop:
178; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
179; CHECK-NEXT:    [[IDX_NEXT]] = add nuw nsw i32 [[IDX]], 1
180; CHECK-NEXT:    [[ABC:%.*]] = icmp ult i32 [[IDX]], [[EXIT_MAINLOOP_AT]]
181; CHECK-NEXT:    br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
182; CHECK:       in.bounds:
183; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
184; CHECK-NEXT:    store i32 0, ptr [[ADDR]], align 4
185; CHECK-NEXT:    [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], -2147483648
186; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
187; CHECK-NEXT:    [[TMP2:%.*]] = xor i1 [[TMP1]], true
188; CHECK-NEXT:    br i1 [[TMP2]], label [[MAIN_EXIT_SELECTOR:%.*]], label [[LOOP]]
189; CHECK:       main.exit.selector:
190; CHECK-NEXT:    [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]
191; CHECK-NEXT:    [[TMP3:%.*]] = icmp ult i32 [[IDX_NEXT_LCSSA]], -2147483647
192; CHECK-NEXT:    br i1 [[TMP3]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
193; CHECK:       main.pseudo.exit:
194; CHECK-NEXT:    [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
195; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
196; CHECK-NEXT:    br label [[POSTLOOP:%.*]]
197; CHECK:       out.of.bounds.loopexit:
198; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
199; CHECK:       out.of.bounds.loopexit1:
200; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
201; CHECK:       out.of.bounds:
202; CHECK-NEXT:    ret void
203; CHECK:       exit.loopexit:
204; CHECK-NEXT:    br label [[EXIT]]
205; CHECK:       exit:
206; CHECK-NEXT:    ret void
207; CHECK:       postloop:
208; CHECK-NEXT:    br label [[LOOP_POSTLOOP:%.*]]
209; CHECK:       loop.postloop:
210; CHECK-NEXT:    [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ]
211; CHECK-NEXT:    [[IDX_NEXT_POSTLOOP]] = add nuw nsw i32 [[IDX_POSTLOOP]], 1
212; CHECK-NEXT:    [[ABC_POSTLOOP:%.*]] = icmp ult i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]]
213; CHECK-NEXT:    br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
214; CHECK:       in.bounds.postloop:
215; CHECK-NEXT:    [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]]
216; CHECK-NEXT:    store i32 0, ptr [[ADDR_POSTLOOP]], align 4
217; CHECK-NEXT:    [[NEXT_POSTLOOP:%.*]] = icmp ugt i32 [[IDX_NEXT_POSTLOOP]], -2147483648
218; CHECK-NEXT:    br i1 [[NEXT_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_POSTLOOP]], !llvm.loop [[LOOP8:![0-9]+]], !loop_constrainer.loop.clone [[META6]]
219;
220
221entry:
222  %len = load i32, ptr %a_len_ptr, !range !0
223  br label %loop
224
225loop:
226  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
227  %idx.next = add nsw nuw i32 %idx, 1
228  %abc = icmp ult i32 %idx, %len
229  br i1 %abc, label %in.bounds, label %out.of.bounds
230
231in.bounds:
232  %addr = getelementptr i32, ptr %arr, i32 %idx
233  store i32 0, ptr %addr
234  %next = icmp ugt i32 %idx.next, 2147483648
235  br i1 %next, label %exit, label %loop
236
237out.of.bounds:
238  ret void
239
240exit:
241  ret void
242}
243
244; Check SINT_MAX + 1, test is similar to test_02.
245define void @test_04(ptr %arr, ptr %a_len_ptr) #0 {
246; CHECK-LABEL: define void @test_04
247; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
248; CHECK-NEXT:  entry:
249; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
250; CHECK-NEXT:    [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[LEN]], i32 1)
251; CHECK-NEXT:    [[EXIT_PRELOOP_AT:%.*]] = add nsw i32 [[UMAX]], -1
252; CHECK-NEXT:    [[TMP0:%.*]] = icmp ugt i32 -2147483648, [[EXIT_PRELOOP_AT]]
253; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]
254; CHECK:       loop.preloop.preheader:
255; CHECK-NEXT:    br label [[LOOP_PRELOOP:%.*]]
256; CHECK:       mainloop:
257; CHECK-NEXT:    br label [[LOOP:%.*]]
258; CHECK:       loop:
259; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_PRELOOP_COPY:%.*]], [[MAINLOOP:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ]
260; CHECK-NEXT:    [[IDX_NEXT]] = add i32 [[IDX]], -1
261; CHECK-NEXT:    [[ABC:%.*]] = icmp ult i32 [[IDX]], [[LEN]]
262; CHECK-NEXT:    br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
263; CHECK:       in.bounds:
264; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
265; CHECK-NEXT:    store i32 0, ptr [[ADDR]], align 4
266; CHECK-NEXT:    [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], 0
267; CHECK-NEXT:    br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
268; CHECK:       out.of.bounds.loopexit:
269; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
270; CHECK:       out.of.bounds.loopexit1:
271; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
272; CHECK:       out.of.bounds:
273; CHECK-NEXT:    ret void
274; CHECK:       exit.loopexit:
275; CHECK-NEXT:    br label [[EXIT:%.*]]
276; CHECK:       exit:
277; CHECK-NEXT:    ret void
278; CHECK:       loop.preloop:
279; CHECK-NEXT:    [[IDX_PRELOOP:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP:%.*]], [[IN_BOUNDS_PRELOOP:%.*]] ], [ -2147483648, [[LOOP_PRELOOP_PREHEADER]] ]
280; CHECK-NEXT:    [[IDX_NEXT_PRELOOP]] = add i32 [[IDX_PRELOOP]], -1
281; CHECK-NEXT:    [[ABC_PRELOOP:%.*]] = icmp ult i32 [[IDX_PRELOOP]], [[LEN]]
282; CHECK-NEXT:    br i1 [[ABC_PRELOOP]], label [[IN_BOUNDS_PRELOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
283; CHECK:       in.bounds.preloop:
284; CHECK-NEXT:    [[ADDR_PRELOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_PRELOOP]]
285; CHECK-NEXT:    store i32 0, ptr [[ADDR_PRELOOP]], align 4
286; CHECK-NEXT:    [[NEXT_PRELOOP:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], 0
287; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], [[EXIT_PRELOOP_AT]]
288; CHECK-NEXT:    br i1 [[TMP1]], label [[LOOP_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop [[LOOP9:![0-9]+]], !loop_constrainer.loop.clone [[META6]]
289; CHECK:       preloop.exit.selector:
290; CHECK-NEXT:    [[IDX_NEXT_PRELOOP_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP]], [[IN_BOUNDS_PRELOOP]] ]
291; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP_LCSSA]], 0
292; CHECK-NEXT:    br i1 [[TMP2]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT]]
293; CHECK:       preloop.pseudo.exit:
294; CHECK-NEXT:    [[IDX_PRELOOP_COPY]] = phi i32 [ -2147483648, [[ENTRY:%.*]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
295; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ -2147483648, [[ENTRY]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
296; CHECK-NEXT:    br label [[MAINLOOP]]
297;
298
299entry:
300  %len = load i32, ptr %a_len_ptr, !range !0
301  br label %loop
302
303loop:
304  %idx = phi i32 [ 2147483648, %entry ], [ %idx.next, %in.bounds ]
305  %idx.next = add i32 %idx, -1
306  %abc = icmp ult i32 %idx, %len
307  br i1 %abc, label %in.bounds, label %out.of.bounds
308
309in.bounds:
310  %addr = getelementptr i32, ptr %arr, i32 %idx
311  store i32 0, ptr %addr
312  %next = icmp ugt i32 %idx.next, 0
313  br i1 %next, label %loop, label %exit
314
315out.of.bounds:
316  ret void
317
318exit:
319  ret void
320}
321
322; Increasing loop, UINT_MAX. Negative test: we cannot add 1 to UINT_MAX.
323define void @test_05(ptr %arr, ptr %a_len_ptr) #0 {
324; CHECK-LABEL: define void @test_05
325; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
326; CHECK-NEXT:  entry:
327; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
328; CHECK-NEXT:    br label [[LOOP:%.*]]
329; CHECK:       loop:
330; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ]
331; CHECK-NEXT:    [[IDX_NEXT]] = add nuw nsw i32 [[IDX]], 1
332; CHECK-NEXT:    [[ABC:%.*]] = icmp ult i32 [[IDX]], [[LEN]]
333; CHECK-NEXT:    br i1 [[ABC]], label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS:%.*]]
334; CHECK:       in.bounds:
335; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
336; CHECK-NEXT:    store i32 0, ptr [[ADDR]], align 4
337; CHECK-NEXT:    [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], -1
338; CHECK-NEXT:    br i1 [[NEXT]], label [[EXIT:%.*]], label [[LOOP]]
339; CHECK:       out.of.bounds:
340; CHECK-NEXT:    ret void
341; CHECK:       exit:
342; CHECK-NEXT:    ret void
343;
344
345entry:
346  %len = load i32, ptr %a_len_ptr, !range !0
347  br label %loop
348
349loop:
350  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
351  %idx.next = add nsw nuw i32 %idx, 1
352  %abc = icmp ult i32 %idx, %len
353  br i1 %abc, label %in.bounds, label %out.of.bounds
354
355in.bounds:
356  %addr = getelementptr i32, ptr %arr, i32 %idx
357  store i32 0, ptr %addr
358  %next = icmp ugt i32 %idx.next, 4294967295
359  br i1 %next, label %exit, label %loop
360
361out.of.bounds:
362  ret void
363
364exit:
365  ret void
366}
367
368; Decreasing loop, UINT_MAX. Positive test.
369define void @test_06(ptr %arr, ptr %a_len_ptr) #0 {
370; CHECK-LABEL: define void @test_06
371; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
372; CHECK-NEXT:  entry:
373; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
374; CHECK-NEXT:    br i1 true, label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]
375; CHECK:       loop.preloop.preheader:
376; CHECK-NEXT:    br label [[LOOP_PRELOOP:%.*]]
377; CHECK:       mainloop:
378; CHECK-NEXT:    br label [[LOOP:%.*]]
379; CHECK:       loop:
380; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_PRELOOP_COPY:%.*]], [[MAINLOOP:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ]
381; CHECK-NEXT:    [[IDX_NEXT]] = add nuw i32 [[IDX]], -1
382; CHECK-NEXT:    [[ABC:%.*]] = icmp ult i32 [[IDX]], [[LEN]]
383; CHECK-NEXT:    br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
384; CHECK:       in.bounds:
385; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
386; CHECK-NEXT:    store i32 0, ptr [[ADDR]], align 4
387; CHECK-NEXT:    [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], 0
388; CHECK-NEXT:    br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
389; CHECK:       out.of.bounds.loopexit:
390; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
391; CHECK:       out.of.bounds.loopexit1:
392; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
393; CHECK:       out.of.bounds:
394; CHECK-NEXT:    ret void
395; CHECK:       exit.loopexit:
396; CHECK-NEXT:    br label [[EXIT:%.*]]
397; CHECK:       exit:
398; CHECK-NEXT:    ret void
399; CHECK:       loop.preloop:
400; CHECK-NEXT:    [[IDX_PRELOOP:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP:%.*]], [[IN_BOUNDS_PRELOOP:%.*]] ], [ -1, [[LOOP_PRELOOP_PREHEADER]] ]
401; CHECK-NEXT:    [[IDX_NEXT_PRELOOP]] = add nuw i32 [[IDX_PRELOOP]], -1
402; CHECK-NEXT:    [[ABC_PRELOOP:%.*]] = icmp ult i32 [[IDX_PRELOOP]], [[LEN]]
403; CHECK-NEXT:    br i1 [[ABC_PRELOOP]], label [[IN_BOUNDS_PRELOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
404; CHECK:       in.bounds.preloop:
405; CHECK-NEXT:    [[ADDR_PRELOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_PRELOOP]]
406; CHECK-NEXT:    store i32 0, ptr [[ADDR_PRELOOP]], align 4
407; CHECK-NEXT:    [[NEXT_PRELOOP:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], 0
408; CHECK-NEXT:    [[TMP0:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], 0
409; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop [[LOOP10:![0-9]+]], !loop_constrainer.loop.clone [[META6]]
410; CHECK:       preloop.exit.selector:
411; CHECK-NEXT:    [[IDX_NEXT_PRELOOP_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP]], [[IN_BOUNDS_PRELOOP]] ]
412; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP_LCSSA]], 0
413; CHECK-NEXT:    br i1 [[TMP1]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT]]
414; CHECK:       preloop.pseudo.exit:
415; CHECK-NEXT:    [[IDX_PRELOOP_COPY]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
416; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ -1, [[ENTRY]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
417; CHECK-NEXT:    br label [[MAINLOOP]]
418;
419
420entry:
421  %len = load i32, ptr %a_len_ptr, !range !0
422  br label %loop
423
424loop:
425  %idx = phi i32 [ 4294967295, %entry ], [ %idx.next, %in.bounds ]
426  %idx.next = add nuw i32 %idx, -1
427  %abc = icmp ult i32 %idx, %len
428  br i1 %abc, label %in.bounds, label %out.of.bounds
429
430in.bounds:
431  %addr = getelementptr i32, ptr %arr, i32 %idx
432  store i32 0, ptr %addr
433  %next = icmp ugt i32 %idx.next, 0
434  br i1 %next, label %loop, label %exit
435
436out.of.bounds:
437  ret void
438
439exit:
440  ret void
441}
442
443!0 = !{i32 0, i32 50}
444;.
445; CHECK: [[RNG0]] = !{i32 0, i32 50}
446; CHECK: [[LOOP1]] = distinct !{[[LOOP1]], [[META2:![0-9]+]], [[META3:![0-9]+]], [[META4:![0-9]+]], [[META5:![0-9]+]]}
447; CHECK: [[META2]] = !{!"llvm.loop.unroll.disable"}
448; CHECK: [[META3]] = !{!"llvm.loop.vectorize.enable", i1 false}
449; CHECK: [[META4]] = !{!"llvm.loop.licm_versioning.disable"}
450; CHECK: [[META5]] = !{!"llvm.loop.distribute.enable", i1 false}
451; CHECK: [[META6]] = !{}
452; CHECK: [[LOOP7]] = distinct !{[[LOOP7]], [[META2]], [[META3]], [[META4]], [[META5]]}
453; CHECK: [[LOOP8]] = distinct !{[[LOOP8]], [[META2]], [[META3]], [[META4]], [[META5]]}
454; CHECK: [[LOOP9]] = distinct !{[[LOOP9]], [[META2]], [[META3]], [[META4]], [[META5]]}
455; CHECK: [[LOOP10]] = distinct !{[[LOOP10]], [[META2]], [[META3]], [[META4]], [[META5]]}
456;.
457