xref: /llvm-project/llvm/test/Transforms/IndVarSimplify/backedge-on-min-max.ll (revision e390c229a438ed1eb3396df8fbeeda89c49474e6)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2; RUN: opt < %s -passes=indvars -S | FileCheck %s
3; RUN: opt -passes=lcssa,loop-simplify -S < %s | opt -S -passes='require<target-ir>,require<scalar-evolution>,require<domtree>,loop(indvars)'
4
5;; --- signed ---
6
7define void @min.signed.1(ptr %a, i32 %a_len, i32 %n) {
8; CHECK-LABEL: define void @min.signed.1(
9; CHECK-SAME: ptr [[A:%.*]], i32 [[A_LEN:%.*]], i32 [[N:%.*]]) {
10; CHECK-NEXT:  entry:
11; CHECK-NEXT:    [[SMIN_CMP:%.*]] = icmp slt i32 [[A_LEN]], [[N]]
12; CHECK-NEXT:    [[SMIN:%.*]] = select i1 [[SMIN_CMP]], i32 [[A_LEN]], i32 [[N]]
13; CHECK-NEXT:    [[ENTRY_COND:%.*]] = icmp slt i32 0, [[SMIN]]
14; CHECK-NEXT:    br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
15; CHECK:       loop.preheader:
16; CHECK-NEXT:    br label [[LOOP:%.*]]
17; CHECK:       loop:
18; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
19; CHECK-NEXT:    [[IDX_INC]] = add nuw nsw i32 [[IDX]], 1
20; CHECK-NEXT:    br i1 true, label [[OK:%.*]], label [[LATCH]]
21; CHECK:       ok:
22; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]]
23; CHECK-NEXT:    store i32 [[IDX]], ptr [[ADDR]], align 4
24; CHECK-NEXT:    br label [[LATCH]]
25; CHECK:       latch:
26; CHECK-NEXT:    [[BE_COND:%.*]] = icmp slt i32 [[IDX_INC]], [[SMIN]]
27; CHECK-NEXT:    br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
28; CHECK:       exit.loopexit:
29; CHECK-NEXT:    br label [[EXIT]]
30; CHECK:       exit:
31; CHECK-NEXT:    ret void
32;
33entry:
34  %smin.cmp = icmp slt i32 %a_len, %n
35  %smin = select i1 %smin.cmp, i32 %a_len, i32 %n
36  %entry.cond = icmp slt i32 0, %smin
37  br i1 %entry.cond, label %loop, label %exit
38
39loop:
40  %idx = phi i32 [ 0, %entry ], [ %idx.inc, %latch ]
41  %idx.inc = add i32 %idx, 1
42  %in.bounds = icmp slt i32 %idx, %a_len
43  br i1 %in.bounds, label %ok, label %latch
44
45ok:
46  %addr = getelementptr i32, ptr %a, i32 %idx
47  store i32 %idx, ptr %addr
48  br label %latch
49
50latch:
51  %be.cond = icmp slt i32 %idx.inc, %smin
52  br i1 %be.cond, label %loop, label %exit
53
54exit:
55  ret void
56}
57
58define void @min.signed.2(ptr %a, i32 %a_len, i32 %n) {
59; CHECK-LABEL: define void @min.signed.2(
60; CHECK-SAME: ptr [[A:%.*]], i32 [[A_LEN:%.*]], i32 [[N:%.*]]) {
61; CHECK-NEXT:  entry:
62; CHECK-NEXT:    [[SMIN_CMP:%.*]] = icmp slt i32 [[A_LEN]], [[N]]
63; CHECK-NEXT:    [[SMIN:%.*]] = select i1 [[SMIN_CMP]], i32 [[A_LEN]], i32 [[N]]
64; CHECK-NEXT:    [[ENTRY_COND:%.*]] = icmp slt i32 0, [[SMIN]]
65; CHECK-NEXT:    br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
66; CHECK:       loop.preheader:
67; CHECK-NEXT:    br label [[LOOP:%.*]]
68; CHECK:       loop:
69; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
70; CHECK-NEXT:    [[IDX_INC]] = add nuw nsw i32 [[IDX]], 1
71; CHECK-NEXT:    br i1 true, label [[OK:%.*]], label [[LATCH]]
72; CHECK:       ok:
73; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]]
74; CHECK-NEXT:    store i32 [[IDX]], ptr [[ADDR]], align 4
75; CHECK-NEXT:    br label [[LATCH]]
76; CHECK:       latch:
77; CHECK-NEXT:    [[BE_COND:%.*]] = icmp slt i32 [[IDX_INC]], [[SMIN]]
78; CHECK-NEXT:    br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
79; CHECK:       exit.loopexit:
80; CHECK-NEXT:    br label [[EXIT]]
81; CHECK:       exit:
82; CHECK-NEXT:    ret void
83;
84entry:
85  %smin.cmp = icmp slt i32 %a_len, %n
86  %smin = select i1 %smin.cmp, i32 %a_len, i32 %n
87  %entry.cond = icmp slt i32 0, %smin
88  br i1 %entry.cond, label %loop, label %exit
89
90loop:
91  %idx = phi i32 [ 0, %entry ], [ %idx.inc, %latch ]
92  %idx.inc = add i32 %idx, 1
93  %in.bounds = icmp sgt i32 %a_len, %idx
94  br i1 %in.bounds, label %ok, label %latch
95
96ok:
97  %addr = getelementptr i32, ptr %a, i32 %idx
98  store i32 %idx, ptr %addr
99  br label %latch
100
101latch:
102  %be.cond = icmp slt i32 %idx.inc, %smin
103  br i1 %be.cond, label %loop, label %exit
104
105exit:
106  ret void
107}
108
109define void @min.signed.3(ptr %a, i32 %n) {
110; CHECK-LABEL: define void @min.signed.3(
111; CHECK-SAME: ptr [[A:%.*]], i32 [[N:%.*]]) {
112; CHECK-NEXT:  entry:
113; CHECK-NEXT:    [[SMIN_CMP:%.*]] = icmp slt i32 42, [[N]]
114; CHECK-NEXT:    [[SMIN:%.*]] = select i1 [[SMIN_CMP]], i32 42, i32 [[N]]
115; CHECK-NEXT:    [[ENTRY_COND:%.*]] = icmp slt i32 0, [[SMIN]]
116; CHECK-NEXT:    br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
117; CHECK:       loop.preheader:
118; CHECK-NEXT:    br label [[LOOP:%.*]]
119; CHECK:       loop:
120; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
121; CHECK-NEXT:    [[IDX_INC]] = add nuw nsw i32 [[IDX]], 1
122; CHECK-NEXT:    br i1 true, label [[OK:%.*]], label [[LATCH]]
123; CHECK:       ok:
124; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]]
125; CHECK-NEXT:    store i32 [[IDX]], ptr [[ADDR]], align 4
126; CHECK-NEXT:    br label [[LATCH]]
127; CHECK:       latch:
128; CHECK-NEXT:    [[BE_COND:%.*]] = icmp slt i32 [[IDX_INC]], [[SMIN]]
129; CHECK-NEXT:    br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
130; CHECK:       exit.loopexit:
131; CHECK-NEXT:    br label [[EXIT]]
132; CHECK:       exit:
133; CHECK-NEXT:    ret void
134;
135entry:
136  %smin.cmp = icmp slt i32 42, %n
137  %smin = select i1 %smin.cmp, i32 42, i32 %n
138  %entry.cond = icmp slt i32 0, %smin
139  br i1 %entry.cond, label %loop, label %exit
140
141loop:
142  %idx = phi i32 [ 0, %entry ], [ %idx.inc, %latch ]
143  %idx.inc = add i32 %idx, 1
144  %in.bounds = icmp slt i32 %idx, 42
145  br i1 %in.bounds, label %ok, label %latch
146
147ok:
148  %addr = getelementptr i32, ptr %a, i32 %idx
149  store i32 %idx, ptr %addr
150  br label %latch
151
152latch:
153  %be.cond = icmp slt i32 %idx.inc, %smin
154  br i1 %be.cond, label %loop, label %exit
155
156exit:
157  ret void
158}
159
160define void @min.signed.4(ptr %a, i32 %n) {
161; CHECK-LABEL: define void @min.signed.4(
162; CHECK-SAME: ptr [[A:%.*]], i32 [[N:%.*]]) {
163; CHECK-NEXT:  entry:
164; CHECK-NEXT:    [[SMIN_CMP:%.*]] = icmp slt i32 42, [[N]]
165; CHECK-NEXT:    [[SMIN:%.*]] = select i1 [[SMIN_CMP]], i32 42, i32 [[N]]
166; CHECK-NEXT:    [[ENTRY_COND:%.*]] = icmp slt i32 0, [[SMIN]]
167; CHECK-NEXT:    br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
168; CHECK:       loop.preheader:
169; CHECK-NEXT:    br label [[LOOP:%.*]]
170; CHECK:       loop:
171; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
172; CHECK-NEXT:    [[IDX_INC]] = add nuw nsw i32 [[IDX]], 1
173; CHECK-NEXT:    br i1 true, label [[OK:%.*]], label [[LATCH]]
174; CHECK:       ok:
175; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]]
176; CHECK-NEXT:    store i32 [[IDX]], ptr [[ADDR]], align 4
177; CHECK-NEXT:    br label [[LATCH]]
178; CHECK:       latch:
179; CHECK-NEXT:    [[BE_COND:%.*]] = icmp slt i32 [[IDX_INC]], [[SMIN]]
180; CHECK-NEXT:    br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
181; CHECK:       exit.loopexit:
182; CHECK-NEXT:    br label [[EXIT]]
183; CHECK:       exit:
184; CHECK-NEXT:    ret void
185;
186entry:
187  %smin.cmp = icmp slt i32 42, %n
188  %smin = select i1 %smin.cmp, i32 42, i32 %n
189  %entry.cond = icmp slt i32 0, %smin
190  br i1 %entry.cond, label %loop, label %exit
191
192loop:
193  %idx = phi i32 [ 0, %entry ], [ %idx.inc, %latch ]
194  %idx.inc = add i32 %idx, 1
195  %in.bounds = icmp sgt i32 42, %idx
196  br i1 %in.bounds, label %ok, label %latch
197
198ok:
199  %addr = getelementptr i32, ptr %a, i32 %idx
200  store i32 %idx, ptr %addr
201  br label %latch
202
203latch:
204  %be.cond = icmp slt i32 %idx.inc, %smin
205  br i1 %be.cond, label %loop, label %exit
206
207exit:
208  ret void
209}
210
211define void @max.signed.1(ptr %a, i32 %a_len, i32 %n) {
212; CHECK-LABEL: define void @max.signed.1(
213; CHECK-SAME: ptr [[A:%.*]], i32 [[A_LEN:%.*]], i32 [[N:%.*]]) {
214; CHECK-NEXT:  entry:
215; CHECK-NEXT:    [[SMAX_CMP:%.*]] = icmp sgt i32 [[A_LEN]], [[N]]
216; CHECK-NEXT:    [[SMAX:%.*]] = select i1 [[SMAX_CMP]], i32 [[A_LEN]], i32 [[N]]
217; CHECK-NEXT:    [[ENTRY_COND:%.*]] = icmp sgt i32 0, [[SMAX]]
218; CHECK-NEXT:    br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
219; CHECK:       loop.preheader:
220; CHECK-NEXT:    br label [[LOOP:%.*]]
221; CHECK:       loop:
222; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
223; CHECK-NEXT:    [[IDX_INC]] = add i32 [[IDX]], 1
224; CHECK-NEXT:    br i1 true, label [[OK:%.*]], label [[LATCH]]
225; CHECK:       ok:
226; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]]
227; CHECK-NEXT:    store i32 [[IDX]], ptr [[ADDR]], align 4
228; CHECK-NEXT:    br label [[LATCH]]
229; CHECK:       latch:
230; CHECK-NEXT:    [[BE_COND:%.*]] = icmp sgt i32 [[IDX_INC]], [[SMAX]]
231; CHECK-NEXT:    br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
232; CHECK:       exit.loopexit:
233; CHECK-NEXT:    br label [[EXIT]]
234; CHECK:       exit:
235; CHECK-NEXT:    ret void
236;
237entry:
238  %smax.cmp = icmp sgt i32 %a_len, %n
239  %smax = select i1 %smax.cmp, i32 %a_len, i32 %n
240  %entry.cond = icmp sgt i32 0, %smax
241  br i1 %entry.cond, label %loop, label %exit
242
243loop:
244  %idx = phi i32 [ 0, %entry ], [ %idx.inc, %latch ]
245  %idx.inc = add i32 %idx, 1
246  %in.bounds = icmp sgt i32 %idx, %a_len
247  br i1 %in.bounds, label %ok, label %latch
248
249ok:
250  %addr = getelementptr i32, ptr %a, i32 %idx
251  store i32 %idx, ptr %addr
252  br label %latch
253
254latch:
255  %be.cond = icmp sgt i32 %idx.inc, %smax
256  br i1 %be.cond, label %loop, label %exit
257
258exit:
259  ret void
260}
261
262define void @max.signed.2(ptr %a, i32 %a_len, i32 %n) {
263; CHECK-LABEL: define void @max.signed.2(
264; CHECK-SAME: ptr [[A:%.*]], i32 [[A_LEN:%.*]], i32 [[N:%.*]]) {
265; CHECK-NEXT:  entry:
266; CHECK-NEXT:    [[SMAX_CMP:%.*]] = icmp sgt i32 [[A_LEN]], [[N]]
267; CHECK-NEXT:    [[SMAX:%.*]] = select i1 [[SMAX_CMP]], i32 [[A_LEN]], i32 [[N]]
268; CHECK-NEXT:    [[ENTRY_COND:%.*]] = icmp sgt i32 0, [[SMAX]]
269; CHECK-NEXT:    br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
270; CHECK:       loop.preheader:
271; CHECK-NEXT:    br label [[LOOP:%.*]]
272; CHECK:       loop:
273; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
274; CHECK-NEXT:    [[IDX_INC]] = add i32 [[IDX]], 1
275; CHECK-NEXT:    br i1 true, label [[OK:%.*]], label [[LATCH]]
276; CHECK:       ok:
277; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]]
278; CHECK-NEXT:    store i32 [[IDX]], ptr [[ADDR]], align 4
279; CHECK-NEXT:    br label [[LATCH]]
280; CHECK:       latch:
281; CHECK-NEXT:    [[BE_COND:%.*]] = icmp sgt i32 [[IDX_INC]], [[SMAX]]
282; CHECK-NEXT:    br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
283; CHECK:       exit.loopexit:
284; CHECK-NEXT:    br label [[EXIT]]
285; CHECK:       exit:
286; CHECK-NEXT:    ret void
287;
288entry:
289  %smax.cmp = icmp sgt i32 %a_len, %n
290  %smax = select i1 %smax.cmp, i32 %a_len, i32 %n
291  %entry.cond = icmp sgt i32 0, %smax
292  br i1 %entry.cond, label %loop, label %exit
293
294loop:
295  %idx = phi i32 [ 0, %entry ], [ %idx.inc, %latch ]
296  %idx.inc = add i32 %idx, 1
297  %in.bounds = icmp slt i32 %a_len, %idx
298  br i1 %in.bounds, label %ok, label %latch
299
300ok:
301  %addr = getelementptr i32, ptr %a, i32 %idx
302  store i32 %idx, ptr %addr
303  br label %latch
304
305latch:
306  %be.cond = icmp sgt i32 %idx.inc, %smax
307  br i1 %be.cond, label %loop, label %exit
308
309exit:
310  ret void
311}
312
313define void @max.signed.3(ptr %a, i32 %n, i32 %init) {
314; CHECK-LABEL: define void @max.signed.3(
315; CHECK-SAME: ptr [[A:%.*]], i32 [[N:%.*]], i32 [[INIT:%.*]]) {
316; CHECK-NEXT:  entry:
317; CHECK-NEXT:    [[SMAX_CMP:%.*]] = icmp sgt i32 42, [[N]]
318; CHECK-NEXT:    [[SMAX:%.*]] = select i1 [[SMAX_CMP]], i32 42, i32 [[N]]
319; CHECK-NEXT:    [[ENTRY_COND:%.*]] = icmp sgt i32 [[INIT]], [[SMAX]]
320; CHECK-NEXT:    br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
321; CHECK:       loop.preheader:
322; CHECK-NEXT:    br label [[LOOP:%.*]]
323; CHECK:       loop:
324; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ [[INIT]], [[LOOP_PREHEADER]] ]
325; CHECK-NEXT:    [[IDX_INC]] = add nuw i32 [[IDX]], 1
326; CHECK-NEXT:    br i1 true, label [[OK:%.*]], label [[LATCH]]
327; CHECK:       ok:
328; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]]
329; CHECK-NEXT:    store i32 [[IDX]], ptr [[ADDR]], align 4
330; CHECK-NEXT:    br label [[LATCH]]
331; CHECK:       latch:
332; CHECK-NEXT:    [[BE_COND:%.*]] = icmp sgt i32 [[IDX_INC]], [[SMAX]]
333; CHECK-NEXT:    br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
334; CHECK:       exit.loopexit:
335; CHECK-NEXT:    br label [[EXIT]]
336; CHECK:       exit:
337; CHECK-NEXT:    ret void
338;
339entry:
340  %smax.cmp = icmp sgt i32 42, %n
341  %smax = select i1 %smax.cmp, i32 42, i32 %n
342  %entry.cond = icmp sgt i32 %init, %smax
343  br i1 %entry.cond, label %loop, label %exit
344
345loop:
346  %idx = phi i32 [ %init, %entry ], [ %idx.inc, %latch ]
347  %idx.inc = add i32 %idx, 1
348  %in.bounds = icmp sgt i32 %idx, 42
349  br i1 %in.bounds, label %ok, label %latch
350
351ok:
352  %addr = getelementptr i32, ptr %a, i32 %idx
353  store i32 %idx, ptr %addr
354  br label %latch
355
356latch:
357  %be.cond = icmp sgt i32 %idx.inc, %smax
358  br i1 %be.cond, label %loop, label %exit
359
360exit:
361  ret void
362}
363
364define void @max.signed.4(ptr %a, i32 %n, i32 %init) {
365; CHECK-LABEL: define void @max.signed.4(
366; CHECK-SAME: ptr [[A:%.*]], i32 [[N:%.*]], i32 [[INIT:%.*]]) {
367; CHECK-NEXT:  entry:
368; CHECK-NEXT:    [[SMAX_CMP:%.*]] = icmp sgt i32 42, [[N]]
369; CHECK-NEXT:    [[SMAX:%.*]] = select i1 [[SMAX_CMP]], i32 42, i32 [[N]]
370; CHECK-NEXT:    [[ENTRY_COND:%.*]] = icmp sgt i32 [[INIT]], [[SMAX]]
371; CHECK-NEXT:    br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
372; CHECK:       loop.preheader:
373; CHECK-NEXT:    br label [[LOOP:%.*]]
374; CHECK:       loop:
375; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ [[INIT]], [[LOOP_PREHEADER]] ]
376; CHECK-NEXT:    [[IDX_INC]] = add nuw i32 [[IDX]], 1
377; CHECK-NEXT:    br i1 true, label [[OK:%.*]], label [[LATCH]]
378; CHECK:       ok:
379; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]]
380; CHECK-NEXT:    store i32 [[IDX]], ptr [[ADDR]], align 4
381; CHECK-NEXT:    br label [[LATCH]]
382; CHECK:       latch:
383; CHECK-NEXT:    [[BE_COND:%.*]] = icmp sgt i32 [[IDX_INC]], [[SMAX]]
384; CHECK-NEXT:    br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
385; CHECK:       exit.loopexit:
386; CHECK-NEXT:    br label [[EXIT]]
387; CHECK:       exit:
388; CHECK-NEXT:    ret void
389;
390entry:
391  %smax.cmp = icmp sgt i32 42, %n
392  %smax = select i1 %smax.cmp, i32 42, i32 %n
393  %entry.cond = icmp sgt i32 %init, %smax
394  br i1 %entry.cond, label %loop, label %exit
395
396loop:
397  %idx = phi i32 [ %init, %entry ], [ %idx.inc, %latch ]
398  %idx.inc = add i32 %idx, 1
399  %in.bounds = icmp slt i32 42, %idx
400  br i1 %in.bounds, label %ok, label %latch
401
402ok:
403  %addr = getelementptr i32, ptr %a, i32 %idx
404  store i32 %idx, ptr %addr
405  br label %latch
406
407latch:
408  %be.cond = icmp sgt i32 %idx.inc, %smax
409  br i1 %be.cond, label %loop, label %exit
410
411exit:
412  ret void
413}
414
415;; --- unsigned ---
416
417define void @min.unsigned.1(ptr %a, i32 %a_len, i32 %n) {
418; CHECK-LABEL: define void @min.unsigned.1(
419; CHECK-SAME: ptr [[A:%.*]], i32 [[A_LEN:%.*]], i32 [[N:%.*]]) {
420; CHECK-NEXT:  entry:
421; CHECK-NEXT:    [[UMIN_CMP:%.*]] = icmp ult i32 [[A_LEN]], [[N]]
422; CHECK-NEXT:    [[UMIN:%.*]] = select i1 [[UMIN_CMP]], i32 [[A_LEN]], i32 [[N]]
423; CHECK-NEXT:    [[ENTRY_COND:%.*]] = icmp ult i32 5, [[UMIN]]
424; CHECK-NEXT:    br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
425; CHECK:       loop.preheader:
426; CHECK-NEXT:    br label [[LOOP:%.*]]
427; CHECK:       loop:
428; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ 5, [[LOOP_PREHEADER]] ]
429; CHECK-NEXT:    [[IDX_INC]] = add nuw i32 [[IDX]], 1
430; CHECK-NEXT:    br i1 true, label [[OK:%.*]], label [[LATCH]]
431; CHECK:       ok:
432; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]]
433; CHECK-NEXT:    store i32 [[IDX]], ptr [[ADDR]], align 4
434; CHECK-NEXT:    br label [[LATCH]]
435; CHECK:       latch:
436; CHECK-NEXT:    [[BE_COND:%.*]] = icmp ult i32 [[IDX_INC]], [[UMIN]]
437; CHECK-NEXT:    br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
438; CHECK:       exit.loopexit:
439; CHECK-NEXT:    br label [[EXIT]]
440; CHECK:       exit:
441; CHECK-NEXT:    ret void
442;
443entry:
444  %umin.cmp = icmp ult i32 %a_len, %n
445  %umin = select i1 %umin.cmp, i32 %a_len, i32 %n
446  %entry.cond = icmp ult i32 5, %umin
447  br i1 %entry.cond, label %loop, label %exit
448
449loop:
450  %idx = phi i32 [ 5, %entry ], [ %idx.inc, %latch ]
451  %idx.inc = add i32 %idx, 1
452  %in.bounds = icmp ult i32 %idx, %a_len
453  br i1 %in.bounds, label %ok, label %latch
454
455ok:
456  %addr = getelementptr i32, ptr %a, i32 %idx
457  store i32 %idx, ptr %addr
458  br label %latch
459
460latch:
461  %be.cond = icmp ult i32 %idx.inc, %umin
462  br i1 %be.cond, label %loop, label %exit
463
464exit:
465  ret void
466}
467
468define void @min.unsigned.2(ptr %a, i32 %a_len, i32 %n) {
469; CHECK-LABEL: define void @min.unsigned.2(
470; CHECK-SAME: ptr [[A:%.*]], i32 [[A_LEN:%.*]], i32 [[N:%.*]]) {
471; CHECK-NEXT:  entry:
472; CHECK-NEXT:    [[UMIN_CMP:%.*]] = icmp ult i32 [[A_LEN]], [[N]]
473; CHECK-NEXT:    [[UMIN:%.*]] = select i1 [[UMIN_CMP]], i32 [[A_LEN]], i32 [[N]]
474; CHECK-NEXT:    [[ENTRY_COND:%.*]] = icmp ult i32 5, [[UMIN]]
475; CHECK-NEXT:    br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
476; CHECK:       loop.preheader:
477; CHECK-NEXT:    br label [[LOOP:%.*]]
478; CHECK:       loop:
479; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ 5, [[LOOP_PREHEADER]] ]
480; CHECK-NEXT:    [[IDX_INC]] = add nuw i32 [[IDX]], 1
481; CHECK-NEXT:    br i1 true, label [[OK:%.*]], label [[LATCH]]
482; CHECK:       ok:
483; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]]
484; CHECK-NEXT:    store i32 [[IDX]], ptr [[ADDR]], align 4
485; CHECK-NEXT:    br label [[LATCH]]
486; CHECK:       latch:
487; CHECK-NEXT:    [[BE_COND:%.*]] = icmp ult i32 [[IDX_INC]], [[UMIN]]
488; CHECK-NEXT:    br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
489; CHECK:       exit.loopexit:
490; CHECK-NEXT:    br label [[EXIT]]
491; CHECK:       exit:
492; CHECK-NEXT:    ret void
493;
494entry:
495  %umin.cmp = icmp ult i32 %a_len, %n
496  %umin = select i1 %umin.cmp, i32 %a_len, i32 %n
497  %entry.cond = icmp ult i32 5, %umin
498  br i1 %entry.cond, label %loop, label %exit
499
500loop:
501  %idx = phi i32 [ 5, %entry ], [ %idx.inc, %latch ]
502  %idx.inc = add i32 %idx, 1
503  %in.bounds = icmp ugt i32 %a_len, %idx
504  br i1 %in.bounds, label %ok, label %latch
505
506ok:
507  %addr = getelementptr i32, ptr %a, i32 %idx
508  store i32 %idx, ptr %addr
509  br label %latch
510
511latch:
512  %be.cond = icmp ult i32 %idx.inc, %umin
513  br i1 %be.cond, label %loop, label %exit
514
515exit:
516  ret void
517}
518
519define void @min.unsigned.3(ptr %a, i32 %n) {
520; CHECK-LABEL: define void @min.unsigned.3(
521; CHECK-SAME: ptr [[A:%.*]], i32 [[N:%.*]]) {
522; CHECK-NEXT:  entry:
523; CHECK-NEXT:    [[UMIN_CMP:%.*]] = icmp ult i32 42, [[N]]
524; CHECK-NEXT:    [[UMIN:%.*]] = select i1 [[UMIN_CMP]], i32 42, i32 [[N]]
525; CHECK-NEXT:    [[ENTRY_COND:%.*]] = icmp ult i32 5, [[UMIN]]
526; CHECK-NEXT:    br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
527; CHECK:       loop.preheader:
528; CHECK-NEXT:    br label [[LOOP:%.*]]
529; CHECK:       loop:
530; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ 5, [[LOOP_PREHEADER]] ]
531; CHECK-NEXT:    [[IDX_INC]] = add nuw nsw i32 [[IDX]], 1
532; CHECK-NEXT:    br i1 true, label [[OK:%.*]], label [[LATCH]]
533; CHECK:       ok:
534; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]]
535; CHECK-NEXT:    store i32 [[IDX]], ptr [[ADDR]], align 4
536; CHECK-NEXT:    br label [[LATCH]]
537; CHECK:       latch:
538; CHECK-NEXT:    [[BE_COND:%.*]] = icmp ult i32 [[IDX_INC]], [[UMIN]]
539; CHECK-NEXT:    br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
540; CHECK:       exit.loopexit:
541; CHECK-NEXT:    br label [[EXIT]]
542; CHECK:       exit:
543; CHECK-NEXT:    ret void
544;
545entry:
546  %umin.cmp = icmp ult i32 42, %n
547  %umin = select i1 %umin.cmp, i32 42, i32 %n
548  %entry.cond = icmp ult i32 5, %umin
549  br i1 %entry.cond, label %loop, label %exit
550
551loop:
552  %idx = phi i32 [ 5, %entry ], [ %idx.inc, %latch ]
553  %idx.inc = add i32 %idx, 1
554  %in.bounds = icmp ult i32 %idx, 42
555  br i1 %in.bounds, label %ok, label %latch
556
557ok:
558  %addr = getelementptr i32, ptr %a, i32 %idx
559  store i32 %idx, ptr %addr
560  br label %latch
561
562latch:
563  %be.cond = icmp ult i32 %idx.inc, %umin
564  br i1 %be.cond, label %loop, label %exit
565
566exit:
567  ret void
568}
569
570define void @min.unsigned.4(ptr %a, i32 %n) {
571; CHECK-LABEL: define void @min.unsigned.4(
572; CHECK-SAME: ptr [[A:%.*]], i32 [[N:%.*]]) {
573; CHECK-NEXT:  entry:
574; CHECK-NEXT:    [[UMIN_CMP:%.*]] = icmp ult i32 42, [[N]]
575; CHECK-NEXT:    [[UMIN:%.*]] = select i1 [[UMIN_CMP]], i32 42, i32 [[N]]
576; CHECK-NEXT:    [[ENTRY_COND:%.*]] = icmp ult i32 5, [[UMIN]]
577; CHECK-NEXT:    br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
578; CHECK:       loop.preheader:
579; CHECK-NEXT:    br label [[LOOP:%.*]]
580; CHECK:       loop:
581; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ 5, [[LOOP_PREHEADER]] ]
582; CHECK-NEXT:    [[IDX_INC]] = add nuw nsw i32 [[IDX]], 1
583; CHECK-NEXT:    br i1 true, label [[OK:%.*]], label [[LATCH]]
584; CHECK:       ok:
585; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]]
586; CHECK-NEXT:    store i32 [[IDX]], ptr [[ADDR]], align 4
587; CHECK-NEXT:    br label [[LATCH]]
588; CHECK:       latch:
589; CHECK-NEXT:    [[BE_COND:%.*]] = icmp ult i32 [[IDX_INC]], [[UMIN]]
590; CHECK-NEXT:    br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
591; CHECK:       exit.loopexit:
592; CHECK-NEXT:    br label [[EXIT]]
593; CHECK:       exit:
594; CHECK-NEXT:    ret void
595;
596entry:
597  %umin.cmp = icmp ult i32 42, %n
598  %umin = select i1 %umin.cmp, i32 42, i32 %n
599  %entry.cond = icmp ult i32 5, %umin
600  br i1 %entry.cond, label %loop, label %exit
601
602loop:
603  %idx = phi i32 [ 5, %entry ], [ %idx.inc, %latch ]
604  %idx.inc = add i32 %idx, 1
605  %in.bounds = icmp ugt i32 42, %idx
606  br i1 %in.bounds, label %ok, label %latch
607
608ok:
609  %addr = getelementptr i32, ptr %a, i32 %idx
610  store i32 %idx, ptr %addr
611  br label %latch
612
613latch:
614  %be.cond = icmp ult i32 %idx.inc, %umin
615  br i1 %be.cond, label %loop, label %exit
616
617exit:
618  ret void
619}
620
621define void @max.unsigned.1(ptr %a, i32 %a_len, i32 %n) {
622; CHECK-LABEL: define void @max.unsigned.1(
623; CHECK-SAME: ptr [[A:%.*]], i32 [[A_LEN:%.*]], i32 [[N:%.*]]) {
624; CHECK-NEXT:  entry:
625; CHECK-NEXT:    [[UMAX_CMP:%.*]] = icmp ugt i32 [[A_LEN]], [[N]]
626; CHECK-NEXT:    [[UMAX:%.*]] = select i1 [[UMAX_CMP]], i32 [[A_LEN]], i32 [[N]]
627; CHECK-NEXT:    [[ENTRY_COND:%.*]] = icmp ugt i32 5, [[UMAX]]
628; CHECK-NEXT:    br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
629; CHECK:       loop.preheader:
630; CHECK-NEXT:    br label [[LOOP:%.*]]
631; CHECK:       loop:
632; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ 5, [[LOOP_PREHEADER]] ]
633; CHECK-NEXT:    [[IDX_INC]] = add i32 [[IDX]], 1
634; CHECK-NEXT:    br i1 true, label [[OK:%.*]], label [[LATCH]]
635; CHECK:       ok:
636; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]]
637; CHECK-NEXT:    store i32 [[IDX]], ptr [[ADDR]], align 4
638; CHECK-NEXT:    br label [[LATCH]]
639; CHECK:       latch:
640; CHECK-NEXT:    [[BE_COND:%.*]] = icmp ugt i32 [[IDX_INC]], [[UMAX]]
641; CHECK-NEXT:    br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
642; CHECK:       exit.loopexit:
643; CHECK-NEXT:    br label [[EXIT]]
644; CHECK:       exit:
645; CHECK-NEXT:    ret void
646;
647entry:
648  %umax.cmp = icmp ugt i32 %a_len, %n
649  %umax = select i1 %umax.cmp, i32 %a_len, i32 %n
650  %entry.cond = icmp ugt i32 5, %umax
651  br i1 %entry.cond, label %loop, label %exit
652
653loop:
654  %idx = phi i32 [ 5, %entry ], [ %idx.inc, %latch ]
655  %idx.inc = add i32 %idx, 1
656  %in.bounds = icmp ugt i32 %idx, %a_len
657  br i1 %in.bounds, label %ok, label %latch
658
659ok:
660  %addr = getelementptr i32, ptr %a, i32 %idx
661  store i32 %idx, ptr %addr
662  br label %latch
663
664latch:
665  %be.cond = icmp ugt i32 %idx.inc, %umax
666  br i1 %be.cond, label %loop, label %exit
667
668exit:
669  ret void
670}
671
672define void @max.unsigned.2(ptr %a, i32 %a_len, i32 %n) {
673; CHECK-LABEL: define void @max.unsigned.2(
674; CHECK-SAME: ptr [[A:%.*]], i32 [[A_LEN:%.*]], i32 [[N:%.*]]) {
675; CHECK-NEXT:  entry:
676; CHECK-NEXT:    [[UMAX_CMP:%.*]] = icmp ugt i32 [[A_LEN]], [[N]]
677; CHECK-NEXT:    [[UMAX:%.*]] = select i1 [[UMAX_CMP]], i32 [[A_LEN]], i32 [[N]]
678; CHECK-NEXT:    [[ENTRY_COND:%.*]] = icmp ugt i32 5, [[UMAX]]
679; CHECK-NEXT:    br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
680; CHECK:       loop.preheader:
681; CHECK-NEXT:    br label [[LOOP:%.*]]
682; CHECK:       loop:
683; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ 5, [[LOOP_PREHEADER]] ]
684; CHECK-NEXT:    [[IDX_INC]] = add i32 [[IDX]], 1
685; CHECK-NEXT:    br i1 true, label [[OK:%.*]], label [[LATCH]]
686; CHECK:       ok:
687; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]]
688; CHECK-NEXT:    store i32 [[IDX]], ptr [[ADDR]], align 4
689; CHECK-NEXT:    br label [[LATCH]]
690; CHECK:       latch:
691; CHECK-NEXT:    [[BE_COND:%.*]] = icmp ugt i32 [[IDX_INC]], [[UMAX]]
692; CHECK-NEXT:    br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
693; CHECK:       exit.loopexit:
694; CHECK-NEXT:    br label [[EXIT]]
695; CHECK:       exit:
696; CHECK-NEXT:    ret void
697;
698entry:
699  %umax.cmp = icmp ugt i32 %a_len, %n
700  %umax = select i1 %umax.cmp, i32 %a_len, i32 %n
701  %entry.cond = icmp ugt i32 5, %umax
702  br i1 %entry.cond, label %loop, label %exit
703
704loop:
705  %idx = phi i32 [ 5, %entry ], [ %idx.inc, %latch ]
706  %idx.inc = add i32 %idx, 1
707  %in.bounds = icmp ult i32 %a_len, %idx
708  br i1 %in.bounds, label %ok, label %latch
709
710ok:
711  %addr = getelementptr i32, ptr %a, i32 %idx
712  store i32 %idx, ptr %addr
713  br label %latch
714
715latch:
716  %be.cond = icmp ugt i32 %idx.inc, %umax
717  br i1 %be.cond, label %loop, label %exit
718
719exit:
720  ret void
721}
722
723define void @max.unsigned.3(ptr %a, i32 %n, i32 %init) {
724; CHECK-LABEL: define void @max.unsigned.3(
725; CHECK-SAME: ptr [[A:%.*]], i32 [[N:%.*]], i32 [[INIT:%.*]]) {
726; CHECK-NEXT:  entry:
727; CHECK-NEXT:    [[UMAX_CMP:%.*]] = icmp ugt i32 42, [[N]]
728; CHECK-NEXT:    [[UMAX:%.*]] = select i1 [[UMAX_CMP]], i32 42, i32 [[N]]
729; CHECK-NEXT:    [[ENTRY_COND:%.*]] = icmp ugt i32 [[INIT]], [[UMAX]]
730; CHECK-NEXT:    br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
731; CHECK:       loop.preheader:
732; CHECK-NEXT:    br label [[LOOP:%.*]]
733; CHECK:       loop:
734; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ [[INIT]], [[LOOP_PREHEADER]] ]
735; CHECK-NEXT:    [[IDX_INC]] = add i32 [[IDX]], 1
736; CHECK-NEXT:    br i1 true, label [[OK:%.*]], label [[LATCH]]
737; CHECK:       ok:
738; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]]
739; CHECK-NEXT:    store i32 [[IDX]], ptr [[ADDR]], align 4
740; CHECK-NEXT:    br label [[LATCH]]
741; CHECK:       latch:
742; CHECK-NEXT:    [[BE_COND:%.*]] = icmp ugt i32 [[IDX_INC]], [[UMAX]]
743; CHECK-NEXT:    br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
744; CHECK:       exit.loopexit:
745; CHECK-NEXT:    br label [[EXIT]]
746; CHECK:       exit:
747; CHECK-NEXT:    ret void
748;
749entry:
750  %umax.cmp = icmp ugt i32 42, %n
751  %umax = select i1 %umax.cmp, i32 42, i32 %n
752  %entry.cond = icmp ugt i32 %init, %umax
753  br i1 %entry.cond, label %loop, label %exit
754
755loop:
756  %idx = phi i32 [ %init, %entry ], [ %idx.inc, %latch ]
757  %idx.inc = add i32 %idx, 1
758  %in.bounds = icmp ugt i32 %idx, 42
759  br i1 %in.bounds, label %ok, label %latch
760
761ok:
762  %addr = getelementptr i32, ptr %a, i32 %idx
763  store i32 %idx, ptr %addr
764  br label %latch
765
766latch:
767  %be.cond = icmp ugt i32 %idx.inc, %umax
768  br i1 %be.cond, label %loop, label %exit
769
770exit:
771  ret void
772}
773
774define void @max.unsigned.4(ptr %a, i32 %n, i32 %init) {
775; CHECK-LABEL: define void @max.unsigned.4(
776; CHECK-SAME: ptr [[A:%.*]], i32 [[N:%.*]], i32 [[INIT:%.*]]) {
777; CHECK-NEXT:  entry:
778; CHECK-NEXT:    [[UMAX_CMP:%.*]] = icmp ugt i32 42, [[N]]
779; CHECK-NEXT:    [[UMAX:%.*]] = select i1 [[UMAX_CMP]], i32 42, i32 [[N]]
780; CHECK-NEXT:    [[ENTRY_COND:%.*]] = icmp ugt i32 [[INIT]], [[UMAX]]
781; CHECK-NEXT:    br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
782; CHECK:       loop.preheader:
783; CHECK-NEXT:    br label [[LOOP:%.*]]
784; CHECK:       loop:
785; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ [[INIT]], [[LOOP_PREHEADER]] ]
786; CHECK-NEXT:    [[IDX_INC]] = add i32 [[IDX]], 1
787; CHECK-NEXT:    br i1 true, label [[OK:%.*]], label [[LATCH]]
788; CHECK:       ok:
789; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]]
790; CHECK-NEXT:    store i32 [[IDX]], ptr [[ADDR]], align 4
791; CHECK-NEXT:    br label [[LATCH]]
792; CHECK:       latch:
793; CHECK-NEXT:    [[BE_COND:%.*]] = icmp ugt i32 [[IDX_INC]], [[UMAX]]
794; CHECK-NEXT:    br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
795; CHECK:       exit.loopexit:
796; CHECK-NEXT:    br label [[EXIT]]
797; CHECK:       exit:
798; CHECK-NEXT:    ret void
799;
800entry:
801  %umax.cmp = icmp ugt i32 42, %n
802  %umax = select i1 %umax.cmp, i32 42, i32 %n
803  %entry.cond = icmp ugt i32 %init, %umax
804  br i1 %entry.cond, label %loop, label %exit
805
806loop:
807  %idx = phi i32 [ %init, %entry ], [ %idx.inc, %latch ]
808  %idx.inc = add i32 %idx, 1
809  %in.bounds = icmp ult i32 42, %idx
810  br i1 %in.bounds, label %ok, label %latch
811
812ok:
813  %addr = getelementptr i32, ptr %a, i32 %idx
814  store i32 %idx, ptr %addr
815  br label %latch
816
817latch:
818  %be.cond = icmp ugt i32 %idx.inc, %umax
819  br i1 %be.cond, label %loop, label %exit
820
821exit:
822  ret void
823}
824