xref: /llvm-project/llvm/test/Transforms/CorrelatedValuePropagation/min-max.ll (revision cc839275164a7768451531af868fa70eb9e71cbd)
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.umin(i8, i8)
6declare i8 @llvm.umax(i8, i8)
7declare i8 @llvm.smin(i8, i8)
8declare i8 @llvm.smax(i8, i8)
9
10; If we don't know anything about the arguments, we can't do anything.
11
12define i8 @test0(i8 %x, i8 %y) {
13; CHECK-LABEL: @test0(
14; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
15; CHECK-NEXT:    ret i8 [[R]]
16;
17  %r = call i8 @llvm.umin(i8 %x, i8 %y)
18  ret i8 %r
19}
20define i8 @test1(i8 %x, i8 %y) {
21; CHECK-LABEL: @test1(
22; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
23; CHECK-NEXT:    ret i8 [[R]]
24;
25  %r = call i8 @llvm.umax(i8 %x, i8 %y)
26  ret i8 %r
27}
28define i8 @test2(i8 %x, i8 %y) {
29; CHECK-LABEL: @test2(
30; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
31; CHECK-NEXT:    ret i8 [[R]]
32;
33  %r = call i8 @llvm.smin(i8 %x, i8 %y)
34  ret i8 %r
35}
36define i8 @test3(i8 %x, i8 %y) {
37; CHECK-LABEL: @test3(
38; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
39; CHECK-NEXT:    ret i8 [[R]]
40;
41  %r = call i8 @llvm.smax(i8 %x, i8 %y)
42  ret i8 %r
43}
44
45; However, if we do know the ranges of arguments, we sometimes can tell that either one is always picked.
46
47define i8 @test4(i8 %x) {
48; CHECK-LABEL: @test4(
49; CHECK-NEXT:    [[LIM:%.*]] = icmp ule i8 [[X:%.*]], 43
50; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
51; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 42)
52; CHECK-NEXT:    ret i8 [[R]]
53;
54  %lim = icmp ule i8 %x, 43
55  call void @llvm.assume(i1 %lim)
56  %r = call i8 @llvm.umin(i8 %x, i8 42)
57  ret i8 %r
58}
59define i8 @test5(i8 %x) {
60; CHECK-LABEL: @test5(
61; CHECK-NEXT:    [[LIM:%.*]] = icmp ule i8 [[X:%.*]], 42
62; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
63; CHECK-NEXT:    ret i8 [[X]]
64;
65  %lim = icmp ule i8 %x, 42
66  call void @llvm.assume(i1 %lim)
67  %r = call i8 @llvm.umin(i8 %x, i8 42)
68  ret i8 %r
69}
70define i8 @test6(i8 %x) {
71; CHECK-LABEL: @test6(
72; CHECK-NEXT:    [[LIM:%.*]] = icmp uge i8 [[X:%.*]], 42
73; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
74; CHECK-NEXT:    ret i8 42
75;
76  %lim = icmp uge i8 %x, 42
77  call void @llvm.assume(i1 %lim)
78  %r = call i8 @llvm.umin(i8 %x, i8 42)
79  ret i8 %r
80}
81define i8 @test7(i8 %x) {
82; CHECK-LABEL: @test7(
83; CHECK-NEXT:    [[LIM:%.*]] = icmp uge i8 [[X:%.*]], 41
84; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
85; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 42)
86; CHECK-NEXT:    ret i8 [[R]]
87;
88  %lim = icmp uge i8 %x, 41
89  call void @llvm.assume(i1 %lim)
90  %r = call i8 @llvm.umin(i8 %x, i8 42)
91  ret i8 %r
92}
93
94define i8 @test8(i8 %x) {
95; CHECK-LABEL: @test8(
96; CHECK-NEXT:    [[LIM:%.*]] = icmp uge i8 [[X:%.*]], 41
97; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
98; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 42)
99; CHECK-NEXT:    ret i8 [[R]]
100;
101  %lim = icmp uge i8 %x, 41
102  call void @llvm.assume(i1 %lim)
103  %r = call i8 @llvm.umax(i8 %x, i8 42)
104  ret i8 %r
105}
106define i8 @test9(i8 %x) {
107; CHECK-LABEL: @test9(
108; CHECK-NEXT:    [[LIM:%.*]] = icmp uge i8 [[X:%.*]], 42
109; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
110; CHECK-NEXT:    ret i8 [[X]]
111;
112  %lim = icmp uge i8 %x, 42
113  call void @llvm.assume(i1 %lim)
114  %r = call i8 @llvm.umax(i8 %x, i8 42)
115  ret i8 %r
116}
117define i8 @test10(i8 %x) {
118; CHECK-LABEL: @test10(
119; CHECK-NEXT:    [[LIM:%.*]] = icmp ule i8 [[X:%.*]], 42
120; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
121; CHECK-NEXT:    ret i8 42
122;
123  %lim = icmp ule i8 %x, 42
124  call void @llvm.assume(i1 %lim)
125  %r = call i8 @llvm.umax(i8 %x, i8 42)
126  ret i8 %r
127}
128define i8 @test11(i8 %x) {
129; CHECK-LABEL: @test11(
130; CHECK-NEXT:    [[LIM:%.*]] = icmp ule i8 [[X:%.*]], 43
131; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
132; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 42)
133; CHECK-NEXT:    ret i8 [[R]]
134;
135  %lim = icmp ule i8 %x, 43
136  call void @llvm.assume(i1 %lim)
137  %r = call i8 @llvm.umax(i8 %x, i8 42)
138  ret i8 %r
139}
140
141define i8 @test12(i8 %x) {
142; CHECK-LABEL: @test12(
143; CHECK-NEXT:    [[LIM:%.*]] = icmp sle i8 [[X:%.*]], 43
144; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
145; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[X]], i8 42)
146; CHECK-NEXT:    ret i8 [[R]]
147;
148  %lim = icmp sle i8 %x, 43
149  call void @llvm.assume(i1 %lim)
150  %r = call i8 @llvm.smin(i8 %x, i8 42)
151  ret i8 %r
152}
153define i8 @test13(i8 %x) {
154; CHECK-LABEL: @test13(
155; CHECK-NEXT:    [[LIM:%.*]] = icmp sle i8 [[X:%.*]], 42
156; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
157; CHECK-NEXT:    ret i8 [[X]]
158;
159  %lim = icmp sle i8 %x, 42
160  call void @llvm.assume(i1 %lim)
161  %r = call i8 @llvm.smin(i8 %x, i8 42)
162  ret i8 %r
163}
164define i8 @test14(i8 %x) {
165; CHECK-LABEL: @test14(
166; CHECK-NEXT:    [[LIM:%.*]] = icmp sge i8 [[X:%.*]], 42
167; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
168; CHECK-NEXT:    ret i8 42
169;
170  %lim = icmp sge i8 %x, 42
171  call void @llvm.assume(i1 %lim)
172  %r = call i8 @llvm.smin(i8 %x, i8 42)
173  ret i8 %r
174}
175define i8 @test15(i8 %x) {
176; CHECK-LABEL: @test15(
177; CHECK-NEXT:    [[LIM:%.*]] = icmp sge i8 [[X:%.*]], 41
178; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
179; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 42)
180; CHECK-NEXT:    ret i8 [[TMP1]]
181;
182  %lim = icmp sge i8 %x, 41
183  call void @llvm.assume(i1 %lim)
184  %r = call i8 @llvm.smin(i8 %x, i8 42)
185  ret i8 %r
186}
187
188define i8 @test16(i8 %x) {
189; CHECK-LABEL: @test16(
190; CHECK-NEXT:    [[LIM:%.*]] = icmp sge i8 [[X:%.*]], 41
191; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
192; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 42)
193; CHECK-NEXT:    ret i8 [[TMP1]]
194;
195  %lim = icmp sge i8 %x, 41
196  call void @llvm.assume(i1 %lim)
197  %r = call i8 @llvm.smax(i8 %x, i8 42)
198  ret i8 %r
199}
200define i8 @test17(i8 %x) {
201; CHECK-LABEL: @test17(
202; CHECK-NEXT:    [[LIM:%.*]] = icmp sge i8 [[X:%.*]], 42
203; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
204; CHECK-NEXT:    ret i8 [[X]]
205;
206  %lim = icmp sge i8 %x, 42
207  call void @llvm.assume(i1 %lim)
208  %r = call i8 @llvm.smax(i8 %x, i8 42)
209  ret i8 %r
210}
211define i8 @test18(i8 %x) {
212; CHECK-LABEL: @test18(
213; CHECK-NEXT:    [[LIM:%.*]] = icmp sle i8 [[X:%.*]], 42
214; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
215; CHECK-NEXT:    ret i8 42
216;
217  %lim = icmp sle i8 %x, 42
218  call void @llvm.assume(i1 %lim)
219  %r = call i8 @llvm.smax(i8 %x, i8 42)
220  ret i8 %r
221}
222define i8 @test19(i8 %x) {
223; CHECK-LABEL: @test19(
224; CHECK-NEXT:    [[LIM:%.*]] = icmp sle i8 [[X:%.*]], 43
225; CHECK-NEXT:    call void @llvm.assume(i1 [[LIM]])
226; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[X]], i8 42)
227; CHECK-NEXT:    ret i8 [[R]]
228;
229  %lim = icmp sle i8 %x, 43
230  call void @llvm.assume(i1 %lim)
231  %r = call i8 @llvm.smax(i8 %x, i8 42)
232  ret i8 %r
233}
234
235declare void @body(i32)
236
237define void @test_bidirectional() {
238; CHECK-LABEL: @test_bidirectional(
239; CHECK-NEXT:  entry:
240; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
241; CHECK:       for.body:
242; CHECK-NEXT:    [[INDVAR:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
243; CHECK-NEXT:    call void @body(i32 65535)
244; CHECK-NEXT:    [[INC]] = add nsw i32 [[INDVAR]], 1
245; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[INDVAR]], 65535
246; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[EXIT:%.*]]
247; CHECK:       exit:
248; CHECK-NEXT:    ret void
249;
250entry:
251  br label %for.body
252
253for.body:
254  %indvar = phi i32 [ 0, %entry ], [ %inc, %for.body ]
255  %smax = call i32 @llvm.smax.i32(i32 %indvar, i32 65535)
256  call void @body(i32 %smax)
257  %inc = add nsw i32 %indvar, 1
258  %cmp = icmp slt i32 %indvar, 65535
259  br i1 %cmp, label %for.body, label %exit
260
261exit:
262  ret void
263}
264
265define i64 @test_at_use(i1 %cond, i64 %x) {
266; CHECK-LABEL: @test_at_use(
267; CHECK-NEXT:  entry:
268; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[IF_END:%.*]]
269; CHECK:       bb1:
270; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[X:%.*]], 0
271; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END]]
272; CHECK:       if.then:
273; CHECK-NEXT:    ret i64 0
274; CHECK:       if.end:
275; CHECK-NEXT:    [[PHI:%.*]] = phi i64 [ [[X]], [[BB1]] ], [ 0, [[ENTRY:%.*]] ]
276; CHECK-NEXT:    ret i64 [[PHI]]
277;
278entry:
279  br i1 %cond, label %bb1, label %if.end
280
281bb1:
282  %val = call i64 @llvm.smax.i64(i64 %x, i64 -1)
283  %cmp = icmp slt i64 %x, 0
284  br i1 %cmp, label %if.then, label %if.end
285
286if.then:
287  ret i64 0
288
289if.end:
290  %phi = phi i64 [%val, %bb1], [0, %entry]
291  ret i64 %phi
292}
293
294define i8 @test_smax_to_umax_nneg(i8 %a, i8 %b) {
295; CHECK-LABEL: @test_smax_to_umax_nneg(
296; CHECK-NEXT:    [[NNEG_A:%.*]] = and i8 [[A:%.*]], 127
297; CHECK-NEXT:    [[NNEG_B:%.*]] = and i8 [[B:%.*]], 127
298; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[NNEG_A]], i8 [[NNEG_B]])
299; CHECK-NEXT:    ret i8 [[TMP1]]
300;
301  %nneg_a = and i8 %a, 127
302  %nneg_b = and i8 %b, 127
303  %ret = call i8 @llvm.smax.i8(i8 %nneg_a, i8 %nneg_b)
304  ret i8 %ret
305}
306
307define i8 @test_smax_to_umax_neg(i8 %a, i8 %b) {
308; CHECK-LABEL: @test_smax_to_umax_neg(
309; CHECK-NEXT:    [[NEG_A:%.*]] = or i8 [[A:%.*]], -128
310; CHECK-NEXT:    [[NEG_B:%.*]] = or i8 [[B:%.*]], -128
311; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[NEG_A]], i8 [[NEG_B]])
312; CHECK-NEXT:    ret i8 [[TMP1]]
313;
314  %neg_a = or i8 %a, 128
315  %neg_b = or i8 %b, 128
316  %ret = call i8 @llvm.smax.i8(i8 %neg_a, i8 %neg_b)
317  ret i8 %ret
318}
319
320define i8 @test_smin_to_umin_nneg(i8 %a, i8 %b) {
321; CHECK-LABEL: @test_smin_to_umin_nneg(
322; CHECK-NEXT:    [[NNEG_A:%.*]] = and i8 [[A:%.*]], 127
323; CHECK-NEXT:    [[NNEG_B:%.*]] = and i8 [[B:%.*]], 127
324; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[NNEG_A]], i8 [[NNEG_B]])
325; CHECK-NEXT:    ret i8 [[TMP1]]
326;
327  %nneg_a = and i8 %a, 127
328  %nneg_b = and i8 %b, 127
329  %ret = call i8 @llvm.smin.i8(i8 %nneg_a, i8 %nneg_b)
330  ret i8 %ret
331}
332
333define i8 @test_smin_to_umin_neg(i8 %a, i8 %b) {
334; CHECK-LABEL: @test_smin_to_umin_neg(
335; CHECK-NEXT:    [[NEG_A:%.*]] = or i8 [[A:%.*]], -128
336; CHECK-NEXT:    [[NEG_B:%.*]] = or i8 [[B:%.*]], -128
337; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[NEG_A]], i8 [[NEG_B]])
338; CHECK-NEXT:    ret i8 [[TMP1]]
339;
340  %neg_a = or i8 %a, 128
341  %neg_b = or i8 %b, 128
342  %ret = call i8 @llvm.smin.i8(i8 %neg_a, i8 %neg_b)
343  ret i8 %ret
344}
345
346define i8 @test_umax_nneg(i8 %a, i8 %b) {
347; CHECK-LABEL: @test_umax_nneg(
348; CHECK-NEXT:    [[NNEG_A:%.*]] = and i8 [[A:%.*]], 127
349; CHECK-NEXT:    [[NNEG_B:%.*]] = and i8 [[B:%.*]], 127
350; CHECK-NEXT:    [[RET:%.*]] = call i8 @llvm.umax.i8(i8 [[NNEG_A]], i8 [[NNEG_B]])
351; CHECK-NEXT:    ret i8 [[RET]]
352;
353  %nneg_a = and i8 %a, 127
354  %nneg_b = and i8 %b, 127
355  %ret = call i8 @llvm.umax.i8(i8 %nneg_a, i8 %nneg_b)
356  ret i8 %ret
357}
358