[rtsan] Add fork/execve interceptors (#117198)
[llvm-project.git] / llvm / test / Transforms / CorrelatedValuePropagation / min-max.ll
blobc9ee233b5a4612756c28b09a1a95f7a6b17a0531
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s
4 declare void @llvm.assume(i1)
5 declare i8 @llvm.umin(i8, i8)
6 declare i8 @llvm.umax(i8, i8)
7 declare i8 @llvm.smin(i8, i8)
8 declare i8 @llvm.smax(i8, i8)
10 ; If we don't know anything about the arguments, we can't do anything.
12 define 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]]
17   %r = call i8 @llvm.umin(i8 %x, i8 %y)
18   ret i8 %r
20 define 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]]
25   %r = call i8 @llvm.umax(i8 %x, i8 %y)
26   ret i8 %r
28 define 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]]
33   %r = call i8 @llvm.smin(i8 %x, i8 %y)
34   ret i8 %r
36 define 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]]
41   %r = call i8 @llvm.smax(i8 %x, i8 %y)
42   ret i8 %r
45 ; However, if we do know the ranges of arguments, we sometimes can tell that either one is always picked.
47 define 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]]
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
59 define 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]]
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
70 define 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
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
81 define 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]]
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
94 define 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]]
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
106 define 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]]
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
117 define 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
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
128 define 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]]
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
141 define 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]]
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
153 define 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]]
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
164 define 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
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
175 define 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]]
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
188 define 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]]
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
200 define 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]]
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
211 define 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
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
222 define 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]]
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
235 declare void @body(i32)
237 define 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
250 entry:
251   br label %for.body
253 for.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
261 exit:
262   ret void
265 define 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]]
278 entry:
279   br i1 %cond, label %bb1, label %if.end
281 bb1:
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
286 if.then:
287   ret i64 0
289 if.end:
290   %phi = phi i64 [%val, %bb1], [0, %entry]
291   ret i64 %phi
294 define 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]]
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
307 define 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]]
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
320 define 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]]
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
333 define 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]]
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
346 define 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]]
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