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