blob: 8944d2b1a6bb96c4fcbdb7998ec470662e6a1204 [file] [log] [blame]
Jingyue Wu42f1d672015-07-28 18:22:40 +00001; RUN: opt < %s -S -analyze -scalar-evolution | FileCheck %s
2
3; Positive and negative tests for inferring flags like nsw from
4; reasoning about how a poison value from overflow would trigger
5; undefined behavior.
6
7define void @foo() {
8 ret void
9}
10
11; Example where an add should get the nsw flag, so that a sext can be
12; distributed over the add.
13define void @test-add-nsw(float* %input, i32 %offset, i32 %numIterations) {
14; CHECK-LABEL: @test-add-nsw
15entry:
16 br label %loop
17loop:
18 %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
19
20; CHECK: %index32 =
21; CHECK: --> {%offset,+,1}<nsw>
22 %index32 = add nsw i32 %i, %offset
23
24; CHECK: %index64 =
25; CHECK: --> {(sext i32 %offset to i64),+,1}<nsw>
26 %index64 = sext i32 %index32 to i64
27
28 %ptr = getelementptr inbounds float, float* %input, i64 %index64
29 %nexti = add nsw i32 %i, 1
30 %f = load float, float* %ptr, align 4
31 call void @foo()
32 %exitcond = icmp eq i32 %nexti, %numIterations
33 br i1 %exitcond, label %exit, label %loop
34exit:
35 ret void
36}
37
38; Example where an add should get the nuw flag.
39define void @test-add-nuw(float* %input, i32 %offset, i32 %numIterations) {
40; CHECK-LABEL: @test-add-nuw
41entry:
42 br label %loop
43loop:
44 %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
45
46; CHECK: %index32 =
47; CHECK: --> {%offset,+,1}<nuw>
48 %index32 = add nuw i32 %i, %offset
49
50 %ptr = getelementptr inbounds float, float* %input, i32 %index32
51 %nexti = add nuw i32 %i, 1
52 %f = load float, float* %ptr, align 4
53 %exitcond = icmp eq i32 %nexti, %numIterations
54 br i1 %exitcond, label %exit, label %loop
55
56exit:
57 ret void
58}
59
60; With no load to trigger UB from poison, we cannot infer nsw.
61define void @test-add-no-load(float* %input, i32 %offset, i32 %numIterations) {
62; CHECK-LABEL: @test-add-no-load
63entry:
64 br label %loop
65loop:
66 %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
67
68; CHECK: %index32 =
69; CHECK: --> {%offset,+,1}<nw>
70 %index32 = add nsw i32 %i, %offset
71
72 %ptr = getelementptr inbounds float, float* %input, i32 %index32
73 %nexti = add nuw i32 %i, 1
74 %exitcond = icmp eq i32 %nexti, %numIterations
75 br i1 %exitcond, label %exit, label %loop
76
77exit:
78 ret void
79}
80
81; The current code is only supposed to look at the loop header, so
82; it should not infer nsw in this case, as that would require looking
83; outside the loop header.
84define void @test-add-not-header(float* %input, i32 %offset, i32 %numIterations) {
85; CHECK-LABEL: @test-add-not-header
86entry:
87 br label %loop
88loop:
89 %i = phi i32 [ %nexti, %loop2 ], [ 0, %entry ]
90 br label %loop2
91loop2:
92
93; CHECK: %index32 =
94; CHECK: --> {%offset,+,1}<nw>
95 %index32 = add nsw i32 %i, %offset
96
97 %ptr = getelementptr inbounds float, float* %input, i32 %index32
98 %nexti = add nsw i32 %i, 1
99 %f = load float, float* %ptr, align 4
100 %exitcond = icmp eq i32 %nexti, %numIterations
101 br i1 %exitcond, label %exit, label %loop
102exit:
103 ret void
104}
105
106; Same thing as test-add-not-header, but in this case only the load
107; instruction is outside the loop header.
108define void @test-add-not-header2(float* %input, i32 %offset, i32 %numIterations) {
109; CHECK-LABEL: @test-add-not-header2
110entry:
111 br label %loop
112loop:
113 %i = phi i32 [ %nexti, %loop2 ], [ 0, %entry ]
114
115; CHECK: %index32 =
Sanjoy Dasa6155b62016-04-22 17:41:06 +0000116; CHECK: --> {%offset,+,1}<nsw>
Jingyue Wu42f1d672015-07-28 18:22:40 +0000117 %index32 = add nsw i32 %i, %offset
118
119 %ptr = getelementptr inbounds float, float* %input, i32 %index32
120 %nexti = add nsw i32 %i, 1
121 br label %loop2
122loop2:
123 %f = load float, float* %ptr, align 4
124 %exitcond = icmp eq i32 %nexti, %numIterations
125 br i1 %exitcond, label %exit, label %loop
126exit:
127 ret void
128}
129
Sanjoy Dasa6155b62016-04-22 17:41:06 +0000130; Similar to test-add-not-header, but in this case the load
131; instruction may not be executed.
132define void @test-add-not-header3(float* %input, i32 %offset, i32 %numIterations,
133 i1* %cond_buf) {
134; CHECK-LABEL: @test-add-not-header3
135entry:
136 br label %loop
137loop:
138 %i = phi i32 [ %nexti, %loop2 ], [ 0, %entry ]
139
140; CHECK: %index32 =
141; CHECK: --> {%offset,+,1}<nw>
142 %index32 = add nsw i32 %i, %offset
143
144 %ptr = getelementptr inbounds float, float* %input, i32 %index32
145 %nexti = add nsw i32 %i, 1
146 %cond = load volatile i1, i1* %cond_buf
147 br i1 %cond, label %loop2, label %exit
148loop2:
149 %f = load float, float* %ptr, align 4
150 %exitcond = icmp eq i32 %nexti, %numIterations
151 br i1 %exitcond, label %exit, label %loop
152exit:
153 ret void
154}
155
156; Same thing as test-add-not-header2, except we have a few extra
157; blocks.
158define void @test-add-not-header4(float* %input, i32 %offset, i32 %numIterations) {
159; CHECK-LABEL: @test-add-not-header4
160entry:
161 br label %loop
162loop:
163 %i = phi i32 [ %nexti, %loop2 ], [ 0, %entry ]
164
165; CHECK: %index32 =
166; CHECK: --> {%offset,+,1}<nsw>
167 %index32 = add nsw i32 %i, %offset
168
169 %ptr = getelementptr inbounds float, float* %input, i32 %index32
170 %nexti = add nsw i32 %i, 1
171 br label %loop3
172loop3:
173 br label %loop4
174loop4:
175 br label %loop2
176loop2:
177 %f = load float, float* %ptr, align 4
178 %exitcond = icmp eq i32 %nexti, %numIterations
179 br i1 %exitcond, label %exit, label %loop
180exit:
181 ret void
182}
183
184; Demonstrate why we need a Visited set in llvm::isKnownNotFullPoison.
185define void @test-add-not-header5(float* %input, i32 %offset) {
186; CHECK-LABEL: @test-add-not-header5
187entry:
188 br label %loop
189loop:
190 %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
191
192; CHECK: %index32 =
193; CHECK: --> {%offset,+,1}<nw>
194 %index32 = add nsw i32 %i, %offset
195
196 %ptr = getelementptr inbounds float, float* %input, i32 %index32
197 %nexti = add nsw i32 %i, 1
198 br label %loop
199
200exit:
201 ret void
202}
203
Jingyue Wu42f1d672015-07-28 18:22:40 +0000204; The call instruction makes it not guaranteed that the add will be
205; executed, since it could run forever or throw an exception, so we
206; cannot assume that the UB is realized.
207define void @test-add-call(float* %input, i32 %offset, i32 %numIterations) {
208; CHECK-LABEL: @test-add-call
209entry:
210 br label %loop
211loop:
212 %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
213
214; CHECK: %index32 =
215; CHECK: --> {%offset,+,1}<nw>
216 call void @foo()
217 %index32 = add nsw i32 %i, %offset
218
219 %ptr = getelementptr inbounds float, float* %input, i32 %index32
220 %nexti = add nsw i32 %i, 1
221 %f = load float, float* %ptr, align 4
222 %exitcond = icmp eq i32 %nexti, %numIterations
223 br i1 %exitcond, label %exit, label %loop
224exit:
225 ret void
226}
227
228; Same issue as test-add-call, but this time the call is between the
229; producer of poison and the load that consumes it.
230define void @test-add-call2(float* %input, i32 %offset, i32 %numIterations) {
231; CHECK-LABEL: @test-add-call2
232entry:
233 br label %loop
234loop:
235 %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
236
237; CHECK: %index32 =
238; CHECK: --> {%offset,+,1}<nw>
239 %index32 = add nsw i32 %i, %offset
240
241 %ptr = getelementptr inbounds float, float* %input, i32 %index32
242 %nexti = add nsw i32 %i, 1
243 call void @foo()
244 %f = load float, float* %ptr, align 4
245 %exitcond = icmp eq i32 %nexti, %numIterations
246 br i1 %exitcond, label %exit, label %loop
247exit:
248 ret void
249}
250
251; Without inbounds, GEP does not propagate poison in the very
252; conservative approach used here.
253define void @test-add-no-inbounds(float* %input, i32 %offset, i32 %numIterations) {
254; CHECK-LABEL: @test-add-no-inbounds
255entry:
256 br label %loop
257loop:
258 %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
259
260; CHECK: %index32 =
261; CHECK: --> {%offset,+,1}<nw>
262 %index32 = add nsw i32 %i, %offset
263
264 %ptr = getelementptr float, float* %input, i32 %index32
265 %nexti = add nsw i32 %i, 1
266 %f = load float, float* %ptr, align 4
267 %exitcond = icmp eq i32 %nexti, %numIterations
268 br i1 %exitcond, label %exit, label %loop
269exit:
270 ret void
271}
272
273; Multiplication by a non-zero constant propagates poison if there is
274; a nuw or nsw flag on the multiplication.
275define void @test-add-mul-propagates(float* %input, i32 %offset, i32 %numIterations) {
276; CHECK-LABEL: @test-add-mul-propagates
277entry:
278 br label %loop
279loop:
280 %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
281
282; CHECK: %index32 =
283; CHECK: --> {%offset,+,1}<nsw>
284 %index32 = add nsw i32 %i, %offset
285
286 %indexmul = mul nuw i32 %index32, 2
287 %ptr = getelementptr inbounds float, float* %input, i32 %indexmul
288 %nexti = add nsw i32 %i, 1
289 %f = load float, float* %ptr, align 4
290 %exitcond = icmp eq i32 %nexti, %numIterations
291 br i1 %exitcond, label %exit, label %loop
292exit:
293 ret void
294}
295
296; Multiplication by a non-constant should not propagate poison in the
297; very conservative approach used here.
298define void @test-add-mul-no-propagation(float* %input, i32 %offset, i32 %numIterations) {
299; CHECK-LABEL: @test-add-mul-no-propagation
300entry:
301 br label %loop
302loop:
303 %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
304
305; CHECK: %index32 =
306; CHECK: --> {%offset,+,1}<nw>
307 %index32 = add nsw i32 %i, %offset
308
309 %indexmul = mul nsw i32 %index32, %offset
310 %ptr = getelementptr inbounds float, float* %input, i32 %indexmul
311 %nexti = add nsw i32 %i, 1
312 %f = load float, float* %ptr, align 4
313 %exitcond = icmp eq i32 %nexti, %numIterations
314 br i1 %exitcond, label %exit, label %loop
315exit:
316 ret void
317}
318
319; Multiplication by a non-zero constant does not propagate poison
320; without a no-wrap flag.
321define void @test-add-mul-no-propagation2(float* %input, i32 %offset, i32 %numIterations) {
322; CHECK-LABEL: @test-add-mul-no-propagation2
323entry:
324 br label %loop
325loop:
326 %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
327
328; CHECK: %index32 =
329; CHECK: --> {%offset,+,1}<nw>
330 %index32 = add nsw i32 %i, %offset
331
332 %indexmul = mul i32 %index32, 2
333 %ptr = getelementptr inbounds float, float* %input, i32 %indexmul
334 %nexti = add nsw i32 %i, 1
335 %f = load float, float* %ptr, align 4
336 %exitcond = icmp eq i32 %nexti, %numIterations
337 br i1 %exitcond, label %exit, label %loop
338exit:
339 ret void
340}
341
342; Division by poison triggers UB.
343define void @test-add-div(float* %input, i32 %offset, i32 %numIterations) {
344; CHECK-LABEL: @test-add-div
345entry:
346 br label %loop
347loop:
348 %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
349
350; CHECK: %j =
351; CHECK: --> {%offset,+,1}<nsw>
352 %j = add nsw i32 %i, %offset
353
354 %q = sdiv i32 %numIterations, %j
355 %nexti = add nsw i32 %i, 1
356 %exitcond = icmp eq i32 %nexti, %numIterations
357 br i1 %exitcond, label %exit, label %loop
358exit:
359 ret void
360}
361
362; Remainder of poison by non-poison divisor does not trigger UB.
363define void @test-add-div2(float* %input, i32 %offset, i32 %numIterations) {
364; CHECK-LABEL: @test-add-div2
365entry:
366 br label %loop
367loop:
368 %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
369
370; CHECK: %j =
371; CHECK: --> {%offset,+,1}<nw>
372 %j = add nsw i32 %i, %offset
373
374 %q = sdiv i32 %j, %numIterations
375 %nexti = add nsw i32 %i, 1
376 %exitcond = icmp eq i32 %nexti, %numIterations
377 br i1 %exitcond, label %exit, label %loop
378exit:
379 ret void
380}
381
382; Store to poison address triggers UB.
383define void @test-add-store(float* %input, i32 %offset, i32 %numIterations) {
384; CHECK-LABEL: @test-add-store
385entry:
386 br label %loop
387loop:
388 %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
389
390; CHECK: %index32 =
391; CHECK: --> {%offset,+,1}<nsw>
392 %index32 = add nsw i32 %i, %offset
393
394 %ptr = getelementptr inbounds float, float* %input, i32 %index32
395 %nexti = add nsw i32 %i, 1
396 store float 1.0, float* %ptr, align 4
397 %exitcond = icmp eq i32 %nexti, %numIterations
398 br i1 %exitcond, label %exit, label %loop
399exit:
400 ret void
401}
402
403; Three sequential adds where the middle add should have nsw. There is
404; a special case for sequential adds and this test covers that. We have to
405; put the final add first in the program since otherwise the special case
406; is not triggered, hence the strange basic block ordering.
407define void @test-add-twice(float* %input, i32 %offset, i32 %numIterations) {
408; CHECK-LABEL: @test-add-twice
409entry:
410 br label %loop
411loop2:
412; CHECK: %seq =
413; CHECK: --> {(2 + %offset),+,1}<nw>
414 %seq = add nsw nuw i32 %index32, 1
415 %exitcond = icmp eq i32 %nexti, %numIterations
416 br i1 %exitcond, label %exit, label %loop
417
418loop:
419 %i = phi i32 [ %nexti, %loop2 ], [ 0, %entry ]
420
421 %j = add nsw i32 %i, 1
422; CHECK: %index32 =
423; CHECK: --> {(1 + %offset),+,1}<nsw>
424 %index32 = add nsw i32 %j, %offset
425
426 %ptr = getelementptr inbounds float, float* %input, i32 %index32
427 %nexti = add nsw i32 %i, 1
428 store float 1.0, float* %ptr, align 4
429 br label %loop2
430exit:
431 ret void
432}
Bjarke Hammersholt Roune9791ed42015-08-14 22:45:26 +0000433
434; Example where a mul should get the nsw flag, so that a sext can be
435; distributed over the mul.
436define void @test-mul-nsw(float* %input, i32 %stride, i32 %numIterations) {
437; CHECK-LABEL: @test-mul-nsw
438entry:
439 br label %loop
440loop:
441 %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
442
443; CHECK: %index32 =
444; CHECK: --> {0,+,%stride}<nsw>
445 %index32 = mul nsw i32 %i, %stride
446
447; CHECK: %index64 =
448; CHECK: --> {0,+,(sext i32 %stride to i64)}<nsw>
449 %index64 = sext i32 %index32 to i64
450
451 %ptr = getelementptr inbounds float, float* %input, i64 %index64
452 %nexti = add nsw i32 %i, 1
453 %f = load float, float* %ptr, align 4
454 %exitcond = icmp eq i32 %nexti, %numIterations
455 br i1 %exitcond, label %exit, label %loop
456exit:
457 ret void
458}
459
460; Example where a mul should get the nuw flag.
461define void @test-mul-nuw(float* %input, i32 %stride, i32 %numIterations) {
462; CHECK-LABEL: @test-mul-nuw
463entry:
464 br label %loop
465loop:
466 %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
467
468; CHECK: %index32 =
469; CHECK: --> {0,+,%stride}<nuw>
470 %index32 = mul nuw i32 %i, %stride
471
472 %ptr = getelementptr inbounds float, float* %input, i32 %index32
473 %nexti = add nuw i32 %i, 1
474 %f = load float, float* %ptr, align 4
475 %exitcond = icmp eq i32 %nexti, %numIterations
476 br i1 %exitcond, label %exit, label %loop
477
478exit:
479 ret void
480}
481
482; Example where a shl should get the nsw flag, so that a sext can be
483; distributed over the shl.
484define void @test-shl-nsw(float* %input, i32 %start, i32 %numIterations) {
485; CHECK-LABEL: @test-shl-nsw
486entry:
487 br label %loop
488loop:
489 %i = phi i32 [ %nexti, %loop ], [ %start, %entry ]
490
491; CHECK: %index32 =
492; CHECK: --> {(256 * %start),+,256}<nsw>
493 %index32 = shl nsw i32 %i, 8
494
495; CHECK: %index64 =
496; CHECK: --> {(sext i32 (256 * %start) to i64),+,256}<nsw>
497 %index64 = sext i32 %index32 to i64
498
499 %ptr = getelementptr inbounds float, float* %input, i64 %index64
500 %nexti = add nsw i32 %i, 1
501 %f = load float, float* %ptr, align 4
502 %exitcond = icmp eq i32 %nexti, %numIterations
503 br i1 %exitcond, label %exit, label %loop
504exit:
505 ret void
506}
507
508; Example where a shl should get the nuw flag.
509define void @test-shl-nuw(float* %input, i32 %numIterations) {
510; CHECK-LABEL: @test-shl-nuw
511entry:
512 br label %loop
513loop:
514 %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
515
516; CHECK: %index32 =
517; CHECK: --> {0,+,512}<nuw>
518 %index32 = shl nuw i32 %i, 9
519
520 %ptr = getelementptr inbounds float, float* %input, i32 %index32
521 %nexti = add nuw i32 %i, 1
522 %f = load float, float* %ptr, align 4
523 %exitcond = icmp eq i32 %nexti, %numIterations
524 br i1 %exitcond, label %exit, label %loop
525
526exit:
527 ret void
528}
529
530; Example where a sub should *not* get the nsw flag, because of how
531; scalar evolution represents A - B as A + (-B) and -B can wrap even
532; in cases where A - B does not.
533define void @test-sub-no-nsw(float* %input, i32 %start, i32 %sub, i32 %numIterations) {
534; CHECK-LABEL: @test-sub-no-nsw
535entry:
536 br label %loop
537loop:
538 %i = phi i32 [ %nexti, %loop ], [ %start, %entry ]
539
540; CHECK: %index32 =
541; CHECK: --> {((-1 * %sub) + %start),+,1}<nw>
542 %index32 = sub nsw i32 %i, %sub
543 %index64 = sext i32 %index32 to i64
544
545 %ptr = getelementptr inbounds float, float* %input, i64 %index64
546 %nexti = add nsw i32 %i, 1
547 %f = load float, float* %ptr, align 4
548 %exitcond = icmp eq i32 %nexti, %numIterations
549 br i1 %exitcond, label %exit, label %loop
550exit:
551 ret void
552}
553
554; Example where a sub should get the nsw flag as the RHS cannot be the
555; minimal signed value.
556define void @test-sub-nsw(float* %input, i32 %start, i32 %sub, i32 %numIterations) {
557; CHECK-LABEL: @test-sub-nsw
558entry:
559 %halfsub = ashr i32 %sub, 1
560 br label %loop
561loop:
562 %i = phi i32 [ %nexti, %loop ], [ %start, %entry ]
563
564; CHECK: %index32 =
565; CHECK: --> {((-1 * %halfsub)<nsw> + %start),+,1}<nsw>
566 %index32 = sub nsw i32 %i, %halfsub
567 %index64 = sext i32 %index32 to i64
568
569 %ptr = getelementptr inbounds float, float* %input, i64 %index64
570 %nexti = add nsw i32 %i, 1
571 %f = load float, float* %ptr, align 4
572 %exitcond = icmp eq i32 %nexti, %numIterations
573 br i1 %exitcond, label %exit, label %loop
574exit:
575 ret void
576}
577
578; Example where a sub should get the nsw flag, since the LHS is non-negative,
579; which implies that the RHS cannot be the minimal signed value.
580define void @test-sub-nsw-lhs-non-negative(float* %input, i32 %sub, i32 %numIterations) {
581; CHECK-LABEL: @test-sub-nsw-lhs-non-negative
582entry:
583 br label %loop
584loop:
585 %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
586
587; CHECK: %index32 =
588; CHECK: --> {(-1 * %sub),+,1}<nsw>
589 %index32 = sub nsw i32 %i, %sub
590
591; CHECK: %index64 =
592; CHECK: --> {(sext i32 (-1 * %sub) to i64),+,1}<nsw>
593 %index64 = sext i32 %index32 to i64
594
595 %ptr = getelementptr inbounds float, float* %input, i64 %index64
596 %nexti = add nsw i32 %i, 1
597 %f = load float, float* %ptr, align 4
598 %exitcond = icmp eq i32 %nexti, %numIterations
599 br i1 %exitcond, label %exit, label %loop
600exit:
601 ret void
602}
603
604; Two adds with a sub in the middle and the sub should have nsw. There is
605; a special case for sequential adds/subs and this test covers that. We have to
606; put the final add first in the program since otherwise the special case
607; is not triggered, hence the strange basic block ordering.
608define void @test-sub-with-add(float* %input, i32 %offset, i32 %numIterations) {
609; CHECK-LABEL: @test-sub-with-add
610entry:
611 br label %loop
612loop2:
613; CHECK: %seq =
614; CHECK: --> {(2 + (-1 * %offset)),+,1}<nw>
615 %seq = add nsw nuw i32 %index32, 1
616 %exitcond = icmp eq i32 %nexti, %numIterations
617 br i1 %exitcond, label %exit, label %loop
618
619loop:
620 %i = phi i32 [ %nexti, %loop2 ], [ 0, %entry ]
621
622 %j = add nsw i32 %i, 1
623; CHECK: %index32 =
624; CHECK: --> {(1 + (-1 * %offset)),+,1}<nsw>
625 %index32 = sub nsw i32 %j, %offset
626
627 %ptr = getelementptr inbounds float, float* %input, i32 %index32
628 %nexti = add nsw i32 %i, 1
629 store float 1.0, float* %ptr, align 4
630 br label %loop2
631exit:
632 ret void
633}
634
635
636; Subtraction of two recurrences. The addition in the SCEV that this
637; maps to is NSW, but the negation of the RHS does not since that
638; recurrence could be the most negative representable value.
639define void @subrecurrences(i32 %outer_l, i32 %inner_l, i32 %val) {
640; CHECK-LABEL: @subrecurrences
641 entry:
642 br label %outer
643
644outer:
645 %o_idx = phi i32 [ 0, %entry ], [ %o_idx.inc, %outer.be ]
646 %o_idx.inc = add nsw i32 %o_idx, 1
647 %cond = icmp eq i32 %o_idx, %val
648 br i1 %cond, label %inner, label %outer.be
649
650inner:
651 %i_idx = phi i32 [ 0, %outer ], [ %i_idx.inc, %inner ]
652 %i_idx.inc = add nsw i32 %i_idx, 1
653; CHECK: %v =
654; CHECK-NEXT: --> {{[{][{]}}-1,+,-1}<nw><%outer>,+,1}<nsw><%inner>
655 %v = sub nsw i32 %i_idx, %o_idx.inc
656 %forub = udiv i32 1, %v
657 %cond2 = icmp eq i32 %i_idx, %inner_l
658 br i1 %cond2, label %outer.be, label %inner
659
660outer.be:
661 %cond3 = icmp eq i32 %o_idx, %outer_l
662 br i1 %cond3, label %exit, label %outer
663
664exit:
665 ret void
666}