1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s
3
4declare void @llvm.assume(i1)
5declare i8 @llvm.abs(i8, i1)
6
7; If we don't know anything about the argument, we can't do anything.
8
9define i8 @test0(i8 %x) {
10; CHECK-LABEL: @test0(
11; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false)
12; CHECK-NEXT:    ret i8 [[R]]
13;
14  %r = call i8 @llvm.abs(i8 %x, i1 0)
15  ret i8 %r
16}
17define i8 @test1(i8 %x) {
18; CHECK-LABEL: @test1(
19; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 true)
20; CHECK-NEXT:    ret i8 [[R]]
21;
22  %r = call i8 @llvm.abs(i8 %x, i1 1)
23  ret i8 %r
24}
25
26; But if we know that the argument is always positive, we can bypass @llvm.abs.
27
28define i8 @test2(i8 %x) {
29; CHECK-LABEL: @test2(
30; CHECK-NEXT:    [[LIM:%.*]] = icmp sge i8 [[X:%.*]], -1
31; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
32; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true)
33; CHECK-NEXT:    ret i8 [[R]]
34;
35
36  %lim = icmp sge i8 %x, -1
37  call void @llvm.assume(i1 %lim)
38  %r = call i8 @llvm.abs(i8 %x, i1 0)
39  ret i8 %r
40}
41define i8 @test3(i8 %x) {
42; CHECK-LABEL: @test3(
43; CHECK-NEXT:    [[LIM:%.*]] = icmp sge i8 [[X:%.*]], -1
44; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
45; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true)
46; CHECK-NEXT:    ret i8 [[R]]
47;
48
49  %lim = icmp sge i8 %x, -1
50  call void @llvm.assume(i1 %lim)
51  %r = call i8 @llvm.abs(i8 %x, i1 1)
52  ret i8 %r
53}
54
55define i8 @test4(i8 %x) {
56; CHECK-LABEL: @test4(
57; CHECK-NEXT:    [[LIM:%.*]] = icmp sge i8 [[X:%.*]], 0
58; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
59; CHECK-NEXT:    ret i8 [[X]]
60;
61
62  %lim = icmp sge i8 %x, 0
63  call void @llvm.assume(i1 %lim)
64  %r = call i8 @llvm.abs(i8 %x, i1 0)
65  ret i8 %r
66}
67define i8 @test5(i8 %x) {
68; CHECK-LABEL: @test5(
69; CHECK-NEXT:    [[LIM:%.*]] = icmp sge i8 [[X:%.*]], 0
70; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
71; CHECK-NEXT:    ret i8 [[X]]
72;
73
74  %lim = icmp sge i8 %x, 0
75  call void @llvm.assume(i1 %lim)
76  %r = call i8 @llvm.abs(i8 %x, i1 1)
77  ret i8 %r
78}
79
80define i8 @test6(i8 %x) {
81; CHECK-LABEL: @test6(
82; CHECK-NEXT:    [[LIM:%.*]] = icmp sge i8 [[X:%.*]], 1
83; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
84; CHECK-NEXT:    ret i8 [[X]]
85;
86
87  %lim = icmp sge i8 %x, 1
88  call void @llvm.assume(i1 %lim)
89  %r = call i8 @llvm.abs(i8 %x, i1 0)
90  ret i8 %r
91}
92define i8 @test7(i8 %x) {
93; CHECK-LABEL: @test7(
94; CHECK-NEXT:    [[LIM:%.*]] = icmp sge i8 [[X:%.*]], 1
95; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
96; CHECK-NEXT:    ret i8 [[X]]
97;
98
99  %lim = icmp sge i8 %x, 1
100  call void @llvm.assume(i1 %lim)
101  %r = call i8 @llvm.abs(i8 %x, i1 1)
102  ret i8 %r
103}
104
105; Likewise, INT_MIN is fine for otherwise-positive value.
106
107define i8 @test8(i8 %x) {
108; CHECK-LABEL: @test8(
109; CHECK-NEXT:    [[LIM:%.*]] = icmp ule i8 [[X:%.*]], 127
110; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
111; CHECK-NEXT:    ret i8 [[X]]
112;
113
114  %lim = icmp ule i8 %x, 127
115  call void @llvm.assume(i1 %lim)
116  %r = call i8 @llvm.abs(i8 %x, i1 0)
117  ret i8 %r
118}
119define i8 @test9(i8 %x) {
120; CHECK-LABEL: @test9(
121; CHECK-NEXT:    [[LIM:%.*]] = icmp ule i8 [[X:%.*]], 127
122; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
123; CHECK-NEXT:    ret i8 [[X]]
124;
125
126  %lim = icmp ule i8 %x, 127
127  call void @llvm.assume(i1 %lim)
128  %r = call i8 @llvm.abs(i8 %x, i1 1)
129  ret i8 %r
130}
131
132define i8 @test10(i8 %x) {
133; CHECK-LABEL: @test10(
134; CHECK-NEXT:    [[LIM:%.*]] = icmp ule i8 [[X:%.*]], -128
135; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
136; CHECK-NEXT:    ret i8 [[X]]
137;
138
139  %lim = icmp ule i8 %x, 128
140  call void @llvm.assume(i1 %lim)
141  %r = call i8 @llvm.abs(i8 %x, i1 0)
142  ret i8 %r
143}
144define i8 @test11(i8 %x) {
145; CHECK-LABEL: @test11(
146; CHECK-NEXT:    [[LIM:%.*]] = icmp ule i8 [[X:%.*]], -128
147; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
148; CHECK-NEXT:    ret i8 [[X]]
149;
150
151  %lim = icmp ule i8 %x, 128
152  call void @llvm.assume(i1 %lim)
153  %r = call i8 @llvm.abs(i8 %x, i1 1)
154  ret i8 %r
155}
156
157define i8 @test12(i8 %x) {
158; CHECK-LABEL: @test12(
159; CHECK-NEXT:    [[LIM:%.*]] = icmp ule i8 [[X:%.*]], -127
160; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
161; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 false)
162; CHECK-NEXT:    ret i8 [[R]]
163;
164
165  %lim = icmp ule i8 %x, 129
166  call void @llvm.assume(i1 %lim)
167  %r = call i8 @llvm.abs(i8 %x, i1 0)
168  ret i8 %r
169}
170define i8 @test13(i8 %x) {
171; CHECK-LABEL: @test13(
172; CHECK-NEXT:    [[LIM:%.*]] = icmp ule i8 [[X:%.*]], -127
173; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
174; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true)
175; CHECK-NEXT:    ret i8 [[R]]
176;
177
178  %lim = icmp ule i8 %x, 129
179  call void @llvm.assume(i1 %lim)
180  %r = call i8 @llvm.abs(i8 %x, i1 1)
181  ret i8 %r
182}
183
184; Likewise, if we know that argument is always negative,
185; we can expand @llvm.abs into a direct negation.
186; For negative arguments, we must be careful to include 0 though.
187
188define i8 @test14(i8 %x) {
189; CHECK-LABEL: @test14(
190; CHECK-NEXT:    [[LIM:%.*]] = icmp sle i8 [[X:%.*]], -1
191; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
192; CHECK-NEXT:    [[R1:%.*]] = sub i8 0, [[X]]
193; CHECK-NEXT:    ret i8 [[R1]]
194;
195
196  %lim = icmp sle i8 %x, -1
197  call void @llvm.assume(i1 %lim)
198  %r = call i8 @llvm.abs(i8 %x, i1 0)
199  ret i8 %r
200}
201define i8 @test15(i8 %x) {
202; CHECK-LABEL: @test15(
203; CHECK-NEXT:    [[LIM:%.*]] = icmp sle i8 [[X:%.*]], -1
204; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
205; CHECK-NEXT:    [[R1:%.*]] = sub nsw i8 0, [[X]]
206; CHECK-NEXT:    ret i8 [[R1]]
207;
208
209  %lim = icmp sle i8 %x, -1
210  call void @llvm.assume(i1 %lim)
211  %r = call i8 @llvm.abs(i8 %x, i1 1)
212  ret i8 %r
213}
214
215define i8 @test16(i8 %x) {
216; CHECK-LABEL: @test16(
217; CHECK-NEXT:    [[LIM:%.*]] = icmp sle i8 [[X:%.*]], 0
218; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
219; CHECK-NEXT:    [[R1:%.*]] = sub i8 0, [[X]]
220; CHECK-NEXT:    ret i8 [[R1]]
221;
222
223  %lim = icmp sle i8 %x, 0
224  call void @llvm.assume(i1 %lim)
225  %r = call i8 @llvm.abs(i8 %x, i1 0)
226  ret i8 %r
227}
228define i8 @test17(i8 %x) {
229; CHECK-LABEL: @test17(
230; CHECK-NEXT:    [[LIM:%.*]] = icmp sle i8 [[X:%.*]], 0
231; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
232; CHECK-NEXT:    [[R1:%.*]] = sub nsw i8 0, [[X]]
233; CHECK-NEXT:    ret i8 [[R1]]
234;
235
236  %lim = icmp sle i8 %x, 0
237  call void @llvm.assume(i1 %lim)
238  %r = call i8 @llvm.abs(i8 %x, i1 1)
239  ret i8 %r
240}
241
242define i8 @test18(i8 %x) {
243; CHECK-LABEL: @test18(
244; CHECK-NEXT:    [[LIM:%.*]] = icmp sle i8 [[X:%.*]], 1
245; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
246; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 false)
247; CHECK-NEXT:    ret i8 [[R]]
248;
249
250  %lim = icmp sle i8 %x, 1
251  call void @llvm.assume(i1 %lim)
252  %r = call i8 @llvm.abs(i8 %x, i1 0)
253  ret i8 %r
254}
255define i8 @test19(i8 %x) {
256; CHECK-LABEL: @test19(
257; CHECK-NEXT:    [[LIM:%.*]] = icmp sle i8 [[X:%.*]], 1
258; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
259; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true)
260; CHECK-NEXT:    ret i8 [[R]]
261;
262
263  %lim = icmp sle i8 %x, 1
264  call void @llvm.assume(i1 %lim)
265  %r = call i8 @llvm.abs(i8 %x, i1 1)
266  ret i8 %r
267}
268
269; And again, INT_MIN is also fine for otherwise-negative range.
270
271define i8 @test20(i8 %x) {
272; CHECK-LABEL: @test20(
273; CHECK-NEXT:    [[LIM:%.*]] = icmp uge i8 [[X:%.*]], 127
274; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
275; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 false)
276; CHECK-NEXT:    ret i8 [[R]]
277;
278
279  %lim = icmp uge i8 %x, 127
280  call void @llvm.assume(i1 %lim)
281  %r = call i8 @llvm.abs(i8 %x, i1 0)
282  ret i8 %r
283}
284define i8 @test21(i8 %x) {
285; CHECK-LABEL: @test21(
286; CHECK-NEXT:    [[LIM:%.*]] = icmp uge i8 [[X:%.*]], 127
287; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
288; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true)
289; CHECK-NEXT:    ret i8 [[R]]
290;
291
292  %lim = icmp uge i8 %x, 127
293  call void @llvm.assume(i1 %lim)
294  %r = call i8 @llvm.abs(i8 %x, i1 1)
295  ret i8 %r
296}
297
298define i8 @test22(i8 %x) {
299; CHECK-LABEL: @test22(
300; CHECK-NEXT:    [[LIM:%.*]] = icmp uge i8 [[X:%.*]], -128
301; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
302; CHECK-NEXT:    [[R1:%.*]] = sub i8 0, [[X]]
303; CHECK-NEXT:    ret i8 [[R1]]
304;
305
306  %lim = icmp uge i8 %x, 128
307  call void @llvm.assume(i1 %lim)
308  %r = call i8 @llvm.abs(i8 %x, i1 0)
309  ret i8 %r
310}
311define i8 @test23(i8 %x) {
312; CHECK-LABEL: @test23(
313; CHECK-NEXT:    [[LIM:%.*]] = icmp uge i8 [[X:%.*]], -128
314; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
315; CHECK-NEXT:    [[R1:%.*]] = sub nsw i8 0, [[X]]
316; CHECK-NEXT:    ret i8 [[R1]]
317;
318
319  %lim = icmp uge i8 %x, 128
320  call void @llvm.assume(i1 %lim)
321  %r = call i8 @llvm.abs(i8 %x, i1 1)
322  ret i8 %r
323}
324
325define i8 @test24(i8 %x) {
326; CHECK-LABEL: @test24(
327; CHECK-NEXT:    [[LIM:%.*]] = icmp uge i8 [[X:%.*]], -127
328; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
329; CHECK-NEXT:    [[R1:%.*]] = sub nsw i8 0, [[X]]
330; CHECK-NEXT:    ret i8 [[R1]]
331;
332
333  %lim = icmp uge i8 %x, 129
334  call void @llvm.assume(i1 %lim)
335  %r = call i8 @llvm.abs(i8 %x, i1 0)
336  ret i8 %r
337}
338define i8 @test25(i8 %x) {
339; CHECK-LABEL: @test25(
340; CHECK-NEXT:    [[LIM:%.*]] = icmp uge i8 [[X:%.*]], -127
341; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
342; CHECK-NEXT:    [[R1:%.*]] = sub nsw i8 0, [[X]]
343; CHECK-NEXT:    ret i8 [[R1]]
344;
345
346  %lim = icmp uge i8 %x, 129
347  call void @llvm.assume(i1 %lim)
348  %r = call i8 @llvm.abs(i8 %x, i1 1)
349  ret i8 %r
350}
351
352; If all else fails, we can sometimes at least inferr NSW.
353
354define i8 @test26(i8 %x) {
355; CHECK-LABEL: @test26(
356; CHECK-NEXT:    [[LIM:%.*]] = icmp ne i8 [[X:%.*]], -128
357; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
358; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true)
359; CHECK-NEXT:    ret i8 [[R]]
360;
361  %lim = icmp ne i8 %x, 128
362  call void @llvm.assume(i1 %lim)
363  %r = call i8 @llvm.abs(i8 %x, i1 0)
364  ret i8 %r
365}
366define i8 @test27(i8 %x) {
367; CHECK-LABEL: @test27(
368; CHECK-NEXT:    [[LIM:%.*]] = icmp ne i8 [[X:%.*]], -128
369; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
370; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true)
371; CHECK-NEXT:    ret i8 [[R]]
372;
373  %lim = icmp ne i8 %x, 128
374  call void @llvm.assume(i1 %lim)
375  %r = call i8 @llvm.abs(i8 %x, i1 1)
376  ret i8 %r
377}
378