1; RUN: opt < %s -correlated-propagation -S | FileCheck %s
2
3; CHECK-LABEL: @test0(
4define void @test0(i32 %a) {
5entry:
6  %cmp = icmp slt i32 %a, 100
7  br i1 %cmp, label %bb, label %exit
8
9bb:
10; CHECK: %add = add nsw i32 %a, 1
11  %add = add i32 %a, 1
12  br label %exit
13
14exit:
15  ret void
16}
17
18; CHECK-LABEL: @test1(
19define void @test1(i32 %a) {
20entry:
21  %cmp = icmp ult i32 %a, 100
22  br i1 %cmp, label %bb, label %exit
23
24bb:
25; CHECK: %add = add nuw nsw i32 %a, 1
26  %add = add i32 %a, 1
27  br label %exit
28
29exit:
30  ret void
31}
32
33; CHECK-LABEL: @test2(
34define void @test2(i32 %a) {
35entry:
36  %cmp = icmp ult i32 %a, -1
37  br i1 %cmp, label %bb, label %exit
38
39bb:
40; CHECK: %add = add nuw i32 %a, 1
41  %add = add i32 %a, 1
42  br label %exit
43
44exit:
45  ret void
46}
47
48; CHECK-LABEL: @test3(
49define void @test3(i32 %a) {
50entry:
51  %cmp = icmp ule i32 %a, -1
52  br i1 %cmp, label %bb, label %exit
53
54bb:
55; CHECK: %add = add i32 %a, 1
56  %add = add i32 %a, 1
57  br label %exit
58
59exit:
60  ret void
61}
62
63; CHECK-LABEL: @test4(
64define void @test4(i32 %a) {
65entry:
66  %cmp = icmp slt i32 %a, 2147483647
67  br i1 %cmp, label %bb, label %exit
68
69bb:
70; CHECK: %add = add nsw i32 %a, 1
71  %add = add i32 %a, 1
72  br label %exit
73
74exit:
75  ret void
76}
77
78; CHECK-LABEL: @test5(
79define void @test5(i32 %a) {
80entry:
81  %cmp = icmp sle i32 %a, 2147483647
82  br i1 %cmp, label %bb, label %exit
83
84bb:
85; CHECK: %add = add i32 %a, 1
86  %add = add i32 %a, 1
87  br label %exit
88
89exit:
90  ret void
91}
92
93; Check for a corner case where an integer value is represented with a constant
94; LVILatticeValue instead of constantrange. Check that we don't fail with an
95; assertion in this case.
96@b = global i32 0, align 4
97define void @test6(i32 %a) {
98bb:
99  %add = add i32 %a, ptrtoint (i32* @b to i32)
100  ret void
101}
102
103; Check that we can gather information for conditions is the form of
104;   and ( i s< 100, Unknown )
105; CHECK-LABEL: @test7(
106define void @test7(i32 %a, i1 %flag) {
107entry:
108  %cmp.1 = icmp slt i32 %a, 100
109  %cmp = and i1 %cmp.1, %flag
110  br i1 %cmp, label %bb, label %exit
111
112bb:
113; CHECK: %add = add nsw i32 %a, 1
114  %add = add i32 %a, 1
115  br label %exit
116
117exit:
118  ret void
119}
120
121; Check that we can gather information for conditions is the form of
122;   and ( i s< 100, i s> 0 )
123; CHECK-LABEL: @test8(
124define void @test8(i32 %a) {
125entry:
126  %cmp.1 = icmp slt i32 %a, 100
127  %cmp.2 = icmp sgt i32 %a, 0
128  %cmp = and i1 %cmp.1, %cmp.2
129  br i1 %cmp, label %bb, label %exit
130
131bb:
132; CHECK: %add = add nuw nsw i32 %a, 1
133  %add = add i32 %a, 1
134  br label %exit
135
136exit:
137  ret void
138}
139
140; Check that for conditions is the form of cond1 && cond2 we don't mistakenly
141; assume that !cond1 && !cond2 holds down to false path.
142; CHECK-LABEL: @test8_neg(
143define void @test8_neg(i32 %a) {
144entry:
145  %cmp.1 = icmp sge i32 %a, 100
146  %cmp.2 = icmp sle i32 %a, 0
147  %cmp = and i1 %cmp.1, %cmp.2
148  br i1 %cmp, label %exit, label %bb
149
150bb:
151; CHECK: %add = add i32 %a, 1
152  %add = add i32 %a, 1
153  br label %exit
154
155exit:
156  ret void
157}
158
159; Check that we can gather information for conditions is the form of
160;   and ( i s< 100, and (i s> 0, Unknown )
161; CHECK-LABEL: @test9(
162define void @test9(i32 %a, i1 %flag) {
163entry:
164  %cmp.1 = icmp slt i32 %a, 100
165  %cmp.2 = icmp sgt i32 %a, 0
166  %cmp.3 = and i1 %cmp.2, %flag
167  %cmp = and i1 %cmp.1, %cmp.3
168  br i1 %cmp, label %bb, label %exit
169
170bb:
171; CHECK: %add = add nuw nsw i32 %a, 1
172  %add = add i32 %a, 1
173  br label %exit
174
175exit:
176  ret void
177}
178
179; Check that we can gather information for conditions is the form of
180;   and ( i s< Unknown, ... )
181; CHECK-LABEL: @test10(
182define void @test10(i32 %a, i32 %b, i1 %flag) {
183entry:
184  %cmp.1 = icmp slt i32 %a, %b
185  %cmp = and i1 %cmp.1, %flag
186  br i1 %cmp, label %bb, label %exit
187
188bb:
189; CHECK: %add = add nsw i32 %a, 1
190  %add = add i32 %a, 1
191  br label %exit
192
193exit:
194  ret void
195}
196
197@limit = external global i32
198; CHECK-LABEL: @test11(
199define i32 @test11(i32* %p, i32 %i) {
200  %limit = load i32, i32* %p, !range !{i32 0, i32 2147483647}
201  %within.1 = icmp ugt i32 %limit, %i
202  %i.plus.7 = add i32 %i, 7
203  %within.2 = icmp ugt i32 %limit, %i.plus.7
204  %within = and i1 %within.1, %within.2
205  br i1 %within, label %then, label %else
206
207then:
208; CHECK: %i.plus.6 = add nuw nsw i32 %i, 6
209  %i.plus.6 = add i32 %i, 6
210  ret i32 %i.plus.6
211
212else:
213  ret i32 0
214}
215
216; Check that we can gather information for conditions is the form of
217;   or ( i s>= 100, Unknown )
218; CHECK-LABEL: @test12(
219define void @test12(i32 %a, i1 %flag) {
220entry:
221  %cmp.1 = icmp sge i32 %a, 100
222  %cmp = or i1 %cmp.1, %flag
223  br i1 %cmp, label %exit, label %bb
224
225bb:
226; CHECK: %add = add nsw i32 %a, 1
227  %add = add i32 %a, 1
228  br label %exit
229
230exit:
231  ret void
232}
233
234; Check that we can gather information for conditions is the form of
235;   or ( i s>= 100, i s<= 0 )
236; CHECK-LABEL: @test13(
237define void @test13(i32 %a) {
238entry:
239  %cmp.1 = icmp sge i32 %a, 100
240  %cmp.2 = icmp sle i32 %a, 0
241  %cmp = or i1 %cmp.1, %cmp.2
242  br i1 %cmp, label %exit, label %bb
243
244bb:
245; CHECK: %add = add nuw nsw i32 %a, 1
246  %add = add i32 %a, 1
247  br label %exit
248
249exit:
250  ret void
251}
252
253; Check that for conditions is the form of cond1 || cond2 we don't mistakenly
254; assume that cond1 || cond2 holds down to true path.
255; CHECK-LABEL: @test13_neg(
256define void @test13_neg(i32 %a) {
257entry:
258  %cmp.1 = icmp slt i32 %a, 100
259  %cmp.2 = icmp sgt i32 %a, 0
260  %cmp = or i1 %cmp.1, %cmp.2
261  br i1 %cmp, label %bb, label %exit
262
263bb:
264; CHECK: %add = add i32 %a, 1
265  %add = add i32 %a, 1
266  br label %exit
267
268exit:
269  ret void
270}
271
272; Check that we can gather information for conditions is the form of
273;   or ( i s>=100, or (i s<= 0, Unknown )
274; CHECK-LABEL: @test14(
275define void @test14(i32 %a, i1 %flag) {
276entry:
277  %cmp.1 = icmp sge i32 %a, 100
278  %cmp.2 = icmp sle i32 %a, 0
279  %cmp.3 = or i1 %cmp.2, %flag
280  %cmp = or i1 %cmp.1, %cmp.3
281  br i1 %cmp, label %exit, label %bb
282
283bb:
284; CHECK: %add = add nuw nsw i32 %a, 1
285  %add = add i32 %a, 1
286  br label %exit
287
288exit:
289  ret void
290}
291
292; Check that we can gather information for conditions is the form of
293;   or ( i s>= Unknown, ... )
294; CHECK-LABEL: @test15(
295define void @test15(i32 %a, i32 %b, i1 %flag) {
296entry:
297  %cmp.1 = icmp sge i32 %a, %b
298  %cmp = or i1 %cmp.1, %flag
299  br i1 %cmp, label %exit, label %bb
300
301bb:
302; CHECK: %add = add nsw i32 %a, 1
303  %add = add i32 %a, 1
304  br label %exit
305
306exit:
307  ret void
308}
309
310; single basic block loop
311; because the loop exit condition is SLT, we can supplement the iv add
312; (iv.next def) with an nsw.
313; CHECK-LABEL: @test16(
314define i32 @test16(i32* %n, i32* %a) {
315preheader:
316  br label %loop
317
318loop:
319; CHECK: %iv.next = add nsw i32 %iv, 1
320  %iv = phi i32 [ 0, %preheader ], [ %iv.next, %loop ]
321  %acc = phi i32 [ 0, %preheader ], [ %acc.curr, %loop ]
322  %x = load atomic i32, i32* %a unordered, align 8
323  fence acquire
324  %acc.curr = add i32 %acc, %x
325  %iv.next = add i32 %iv, 1
326  %nval = load atomic i32, i32* %n unordered, align 8
327  %cmp = icmp slt i32 %iv.next, %nval
328  br i1 %cmp, label %loop, label %exit
329
330exit:
331  ret i32 %acc.curr
332}
333