xref: /llvm-project/llvm/test/Transforms/InstCombine/binop-select.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4declare void @use(i32)
5declare void @use_f32(float)
6declare void @use_v2f16(<2 x half>)
7declare void @use_v2i8(<2 x i8>)
8declare i32 @llvm.sadd.sat.i32(i32, i32)
9declare <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8>, <2 x i8>)
10
11define i32 @test1(i1 %c, i32 %x, i32 %y) {
12; CHECK-LABEL: @test1(
13; CHECK-NEXT:    [[SUB:%.*]] = sub i32 0, [[X:%.*]]
14; CHECK-NEXT:    [[COND:%.*]] = select i1 [[C:%.*]], i32 [[SUB]], i32 [[Y:%.*]]
15; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[COND]], [[X]]
16; CHECK-NEXT:    ret i32 [[ADD]]
17;
18  %sub = sub i32 0, %x
19  %cond = select i1 %c, i32 %sub, i32 %y
20  %add = add i32 %cond, %x
21  ret i32 %add
22}
23
24define i32 @test2(i1 %c, i32 %x, i32 %y) {
25; CHECK-LABEL: @test2(
26; CHECK-NEXT:    [[SUB:%.*]] = sub i32 0, [[X:%.*]]
27; CHECK-NEXT:    [[COND:%.*]] = select i1 [[C:%.*]], i32 [[SUB]], i32 [[X]]
28; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[COND]], [[X]]
29; CHECK-NEXT:    ret i32 [[ADD]]
30;
31  %sub = sub i32 0, %x
32  %cond = select i1 %c, i32 %sub, i32 %x
33  %add = add i32 %cond, %x
34  ret i32 %add
35}
36
37define i32 @test3(i1 %c, i32 %x, i32 %y) {
38; CHECK-LABEL: @test3(
39; CHECK-NEXT:    [[SUB:%.*]] = sub i32 0, [[X:%.*]]
40; CHECK-NEXT:    [[COND:%.*]] = select i1 [[C:%.*]], i32 [[SUB]], i32 1
41; CHECK-NEXT:    [[MUL:%.*]] = mul i32 [[COND]], [[X]]
42; CHECK-NEXT:    ret i32 [[MUL]]
43;
44  %sub = sub i32 0, %x
45  %cond = select i1 %c, i32 %sub, i32 1
46  %mul = mul i32 %cond, %x
47  ret i32 %mul
48}
49
50define i32 @test4(i1 %c, i32 %x, i32 %y) {
51; CHECK-LABEL: @test4(
52; CHECK-NEXT:    [[SUB:%.*]] = sub i32 0, [[X:%.*]]
53; CHECK-NEXT:    [[COND:%.*]] = select i1 [[C:%.*]], i32 [[SUB]], i32 1
54; CHECK-NEXT:    [[MUL:%.*]] = mul i32 [[COND]], [[X]]
55; CHECK-NEXT:    ret i32 [[MUL]]
56;
57  %sub = sub i32 0, %x
58  %cond = select i1 %c, i32 %sub, i32 1
59  %mul = mul i32 %cond, %x
60  ret i32 %mul
61}
62
63define i32 @test5(i1 %c, i32 %x, i32 %y) {
64; CHECK-LABEL: @test5(
65; CHECK-NEXT:    [[COND:%.*]] = select i1 [[C:%.*]], i32 [[X:%.*]], i32 0
66; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[COND]], [[X]]
67; CHECK-NEXT:    ret i32 [[ADD]]
68;
69  %cond = select i1 %c, i32 %x, i32 0
70  %add = add i32 %cond, %x
71  ret i32 %add
72}
73
74define i32 @test_sub_deduce_true(i32 %x, i32 %y) {
75; CHECK-LABEL: @test_sub_deduce_true(
76; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[X:%.*]], 9
77; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[X]], i32 [[Y:%.*]])
78; CHECK-NEXT:    [[SUB:%.*]] = select i1 [[C]], i32 15, i32 [[TMP1]]
79; CHECK-NEXT:    ret i32 [[SUB]]
80;
81  %c = icmp eq i32 %x, 9
82  %cond = select i1 %c, i32 6, i32 %y
83  %sub = call i32 @llvm.sadd.sat.i32(i32 %x, i32 %cond)
84  ret i32 %sub
85}
86
87define i32 @test_sub_deduce_true_no_const_fold(i32 %x, i32 %y) {
88; CHECK-LABEL: @test_sub_deduce_true_no_const_fold(
89; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[X:%.*]], 9
90; CHECK-NEXT:    [[COND:%.*]] = select i1 [[C]], i32 [[Y:%.*]], i32 6
91; CHECK-NEXT:    [[SUB:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[X]], i32 [[COND]])
92; CHECK-NEXT:    ret i32 [[SUB]]
93;
94  %c = icmp eq i32 %x, 9
95  %cond = select i1 %c, i32 %y, i32 6
96  %sub = call i32 @llvm.sadd.sat.i32(i32 %x, i32 %cond)
97  ret i32 %sub
98}
99
100define i32 @test_sub_deduce_false(i32 %x, i32 %y) {
101; CHECK-LABEL: @test_sub_deduce_false(
102; CHECK-NEXT:    [[C_NOT:%.*]] = icmp eq i32 [[X:%.*]], 9
103; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[X]], i32 [[Y:%.*]])
104; CHECK-NEXT:    [[SUB:%.*]] = select i1 [[C_NOT]], i32 16, i32 [[TMP1]]
105; CHECK-NEXT:    ret i32 [[SUB]]
106;
107  %c = icmp ne i32 %x, 9
108  %cond = select i1 %c, i32 %y, i32 7
109  %sub = call i32 @llvm.sadd.sat.i32(i32 %x, i32 %cond)
110  ret i32 %sub
111}
112
113define <2 x i8> @test_sub_dont_deduce_with_undef_cond_vec(<2 x i8> %x, <2 x i8> %y) {
114; CHECK-LABEL: @test_sub_dont_deduce_with_undef_cond_vec(
115; CHECK-NEXT:    [[C_NOT:%.*]] = icmp eq <2 x i8> [[X:%.*]], <i8 9, i8 undef>
116; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[C_NOT]], <2 x i8> splat (i8 7), <2 x i8> [[Y:%.*]]
117; CHECK-NEXT:    [[SUB:%.*]] = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> [[X]], <2 x i8> [[COND]])
118; CHECK-NEXT:    ret <2 x i8> [[SUB]]
119;
120  %c = icmp ne <2 x i8> %x, <i8 9, i8 undef>
121  %cond = select <2 x i1> %c, <2 x i8> %y, <2 x i8> <i8 7, i8 7>
122  %sub = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> %x, <2 x i8> %cond)
123  ret <2 x i8> %sub
124}
125
126define <2 x i8> @test_sub_dont_deduce_with_poison_cond_vec(<2 x i8> %x, <2 x i8> %y) {
127; CHECK-LABEL: @test_sub_dont_deduce_with_poison_cond_vec(
128; CHECK-NEXT:    [[C_NOT:%.*]] = icmp eq <2 x i8> [[X:%.*]], <i8 poison, i8 9>
129; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[C_NOT]], <2 x i8> splat (i8 7), <2 x i8> [[Y:%.*]]
130; CHECK-NEXT:    [[SUB:%.*]] = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> [[X]], <2 x i8> [[COND]])
131; CHECK-NEXT:    ret <2 x i8> [[SUB]]
132;
133  %c = icmp ne <2 x i8> %x, <i8 poison, i8 9>
134  %cond = select <2 x i1> %c, <2 x i8> %y, <2 x i8> <i8 7, i8 7>
135  %sub = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> %x, <2 x i8> %cond)
136  ret <2 x i8> %sub
137}
138
139
140define <2 x i8> @test_sub_deduce_with_undef_val_vec(<2 x i8> %x, <2 x i8> %y) {
141; CHECK-LABEL: @test_sub_deduce_with_undef_val_vec(
142; CHECK-NEXT:    [[C_NOT:%.*]] = icmp eq <2 x i8> [[X:%.*]], <i8 1, i8 2>
143; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> [[X]], <2 x i8> [[Y:%.*]])
144; CHECK-NEXT:    [[SUB:%.*]] = select <2 x i1> [[C_NOT]], <2 x i8> <i8 4, i8 -1>, <2 x i8> [[TMP1]]
145; CHECK-NEXT:    ret <2 x i8> [[SUB]]
146;
147  %c = icmp ne <2 x i8> %x, <i8 1, i8 2>
148  %cond = select <2 x i1> %c, <2 x i8> %y, <2 x i8> <i8 3, i8 undef>
149  %sub = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> %x, <2 x i8> %cond)
150  ret <2 x i8> %sub
151}
152
153
154define i32 @test6(i1 %c, i32 %x, i32 %y) {
155; CHECK-LABEL: @test6(
156; CHECK-NEXT:    [[COND:%.*]] = select i1 [[C:%.*]], i32 7, i32 [[X:%.*]]
157; CHECK-NEXT:    [[AND:%.*]] = and i32 [[COND]], [[X]]
158; CHECK-NEXT:    ret i32 [[AND]]
159;
160  %cond = select i1 %c, i32 7, i32 %x
161  %and = and i32 %cond, %x
162  ret i32 %and
163}
164
165define i32 @test7(i1 %c, i32 %x) {
166; CHECK-LABEL: @test7(
167; CHECK-NEXT:    [[SUB:%.*]] = sub i32 0, [[X:%.*]]
168; CHECK-NEXT:    [[COND:%.*]] = select i1 [[C:%.*]], i32 [[X]], i32 [[SUB]]
169; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 [[X]], [[COND]]
170; CHECK-NEXT:    ret i32 [[DIV]]
171;
172  %sub = sub i32 0, %x
173  %cond = select i1 %c, i32 %x, i32 %sub
174  %div = sdiv i32 %x, %cond
175  ret i32 %div
176}
177
178
179define i32 @test8(i1 %c, i32 %x, i32 %y) {
180; CHECK-LABEL: @test8(
181; CHECK-NEXT:    [[COND:%.*]] = select i1 [[C:%.*]], i32 7, i32 [[Y:%.*]]
182; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 42, [[COND]]
183; CHECK-NEXT:    ret i32 [[DIV]]
184;
185  %cond = select i1 %c, i32 7, i32 %y
186  %div = sdiv i32 42, %cond
187  ret i32 %div
188}
189
190define i32 @test9(i1 %c, i32 %x, i32 %y) {
191; CHECK-LABEL: @test9(
192; CHECK-NEXT:    [[COND:%.*]] = select i1 [[C:%.*]], i32 1, i32 [[X:%.*]]
193; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 0, [[COND]]
194; CHECK-NEXT:    ret i32 [[SUB]]
195;
196  %cond = select i1 %c, i32 1, i32 %x
197  %sub = sub nsw i32 0, %cond
198  ret i32 %sub
199}
200
201define i32 @test10(i1 %c, i32 %x, i32 %y) {
202; CHECK-LABEL: @test10(
203; CHECK-NEXT:    [[COND:%.*]] = select i1 [[C:%.*]], i32 7, i32 [[Y:%.*]]
204; CHECK-NEXT:    [[DIV:%.*]] = udiv i32 42, [[COND]]
205; CHECK-NEXT:    ret i32 [[DIV]]
206;
207  %cond = select i1 %c, i32 7, i32 %y
208  %div = udiv i32 42, %cond
209  ret i32 %div
210}
211
212define i32 @test11(i1 %c, i32 %x, i32 %y) {
213; CHECK-LABEL: @test11(
214; CHECK-NEXT:    [[COND:%.*]] = select i1 [[C:%.*]], i32 7, i32 [[Y:%.*]]
215; CHECK-NEXT:    [[DIV:%.*]] = srem i32 42, [[COND]]
216; CHECK-NEXT:    ret i32 [[DIV]]
217;
218  %cond = select i1 %c, i32 7, i32 %y
219  %div = srem i32 42, %cond
220  ret i32 %div
221}
222
223define i32 @test12(i1 %c, i32 %x, i32 %y) {
224; CHECK-LABEL: @test12(
225; CHECK-NEXT:    [[COND:%.*]] = select i1 [[C:%.*]], i32 7, i32 [[Y:%.*]]
226; CHECK-NEXT:    [[DIV:%.*]] = urem i32 42, [[COND]]
227; CHECK-NEXT:    ret i32 [[DIV]]
228;
229  %cond = select i1 %c, i32 7, i32 %y
230  %div = urem i32 42, %cond
231  ret i32 %div
232}
233
234define i32 @extra_use(i1 %c, i32 %x, i32 %y) {
235; CHECK-LABEL: @extra_use(
236; CHECK-NEXT:    [[COND:%.*]] = select i1 [[C:%.*]], i32 1, i32 [[X:%.*]]
237; CHECK-NEXT:    tail call void @use(i32 [[COND]])
238; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 0, [[COND]]
239; CHECK-NEXT:    ret i32 [[SUB]]
240;
241  %cond = select i1 %c, i32 1, i32 %x
242  tail call void @use(i32 %cond)
243  %sub = sub nsw i32 0, %cond
244  ret i32 %sub
245}
246
247
248define i32 @extra_use2(i1 %c, i32 %x) {
249; CHECK-LABEL: @extra_use2(
250; CHECK-NEXT:    [[SUB:%.*]] = sub i32 0, [[X:%.*]]
251; CHECK-NEXT:    [[COND:%.*]] = select i1 [[C:%.*]], i32 [[X]], i32 [[SUB]]
252; CHECK-NEXT:    tail call void @use(i32 [[COND]])
253; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 [[COND]], [[X]]
254; CHECK-NEXT:    ret i32 [[DIV]]
255;
256  %sub = sub i32 0, %x
257  %cond = select i1 %c, i32 %x, i32 %sub
258  tail call void @use(i32 %cond)
259  %div = sdiv i32 %cond, %x
260  ret i32 %div
261}
262
263define i32 @and_sel_op0(i1 %b) {
264; CHECK-LABEL: @and_sel_op0(
265; CHECK-NEXT:    [[S:%.*]] = zext i1 [[B:%.*]] to i32
266; CHECK-NEXT:    ret i32 [[S]]
267;
268  %s = select i1 %b, i32 25, i32 0
269  %r = and i32 %s, 1
270  ret i32 %r
271}
272
273define i32 @and_sel_op0_use(i1 %b) {
274; CHECK-LABEL: @and_sel_op0_use(
275; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], i32 25, i32 0
276; CHECK-NEXT:    call void @use(i32 [[S]])
277; CHECK-NEXT:    [[R:%.*]] = and i32 [[S]], 1
278; CHECK-NEXT:    ret i32 [[R]]
279;
280  %s = select i1 %b, i32 25, i32 0
281  call void @use(i32 %s)
282  %r = and i32 %s, 1
283  ret i32 %r
284}
285
286define i32 @mul_sel_op0(i1 %b, i32 %x) {
287; CHECK-LABEL: @mul_sel_op0(
288; CHECK-NEXT:    [[R:%.*]] = select i1 [[B:%.*]], i32 0, i32 42
289; CHECK-NEXT:    ret i32 [[R]]
290;
291  %d = udiv exact i32 42, %x
292  %s = select i1 %b, i32 0, i32 %d
293  %r = mul i32 %s, %x
294  ret i32 %r
295}
296
297define i32 @mul_sel_op0_use(i1 %b, i32 %x) {
298; CHECK-LABEL: @mul_sel_op0_use(
299; CHECK-NEXT:    [[D:%.*]] = udiv exact i32 42, [[X:%.*]]
300; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], i32 0, i32 [[D]]
301; CHECK-NEXT:    call void @use(i32 [[S]])
302; CHECK-NEXT:    [[R:%.*]] = mul i32 [[S]], [[X]]
303; CHECK-NEXT:    ret i32 [[R]]
304;
305  %d = udiv exact i32 42, %x
306  %s = select i1 %b, i32 0, i32 %d
307  call void @use(i32 %s)
308  %r = mul i32 %s, %x
309  ret i32 %r
310}
311
312define i32 @sub_sel_op1(i1 %b) {
313; CHECK-LABEL: @sub_sel_op1(
314; CHECK-NEXT:    [[NOT_B:%.*]] = xor i1 [[B:%.*]], true
315; CHECK-NEXT:    [[R:%.*]] = zext i1 [[NOT_B]] to i32
316; CHECK-NEXT:    ret i32 [[R]]
317;
318  %s = select i1 %b, i32 42, i32 41
319  %r = sub nsw i32 42, %s
320  ret i32 %r
321}
322
323define i32 @sub_sel_op1_use(i1 %b) {
324; CHECK-LABEL: @sub_sel_op1_use(
325; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], i32 42, i32 41
326; CHECK-NEXT:    call void @use(i32 [[S]])
327; CHECK-NEXT:    [[R:%.*]] = sub nuw nsw i32 42, [[S]]
328; CHECK-NEXT:    ret i32 [[R]]
329;
330  %s = select i1 %b, i32 42, i32 41
331  call void @use(i32 %s)
332  %r = sub nuw nsw i32 42, %s
333  ret i32 %r
334}
335
336define float @fadd_sel_op0(i1 %b, float %x) {
337; CHECK-LABEL: @fadd_sel_op0(
338; CHECK-NEXT:    [[R:%.*]] = select nnan i1 [[B:%.*]], float 0xFFF0000000000000, float 0x7FF0000000000000
339; CHECK-NEXT:    ret float [[R]]
340;
341  %s = select i1 %b, float 0xFFF0000000000000, float 0x7FF0000000000000
342  %r = fadd nnan float %s, %x
343  ret float %r
344}
345
346define float @fadd_sel_op0_use(i1 %b, float %x) {
347; CHECK-LABEL: @fadd_sel_op0_use(
348; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], float 0xFFF0000000000000, float 0x7FF0000000000000
349; CHECK-NEXT:    call void @use_f32(float [[S]])
350; CHECK-NEXT:    [[R:%.*]] = fadd nnan float [[S]], [[X:%.*]]
351; CHECK-NEXT:    ret float [[R]]
352;
353  %s = select i1 %b, float 0xFFF0000000000000, float 0x7FF0000000000000
354  call void @use_f32(float %s)
355  %r = fadd nnan float %s, %x
356  ret float %r
357}
358
359define <2 x half> @fmul_sel_op1(i1 %b, <2 x half> %p) {
360; CHECK-LABEL: @fmul_sel_op1(
361; CHECK-NEXT:    ret <2 x half> zeroinitializer
362;
363  %x = fadd <2 x half> %p, <half 1.0, half 2.0> ; thwart complexity-based canonicalization
364  %s = select i1 %b, <2 x half> zeroinitializer, <2 x half> <half 0xHffff, half 0xHffff>
365  %r = fmul nnan nsz <2 x half> %x, %s
366  ret <2 x half> %r
367}
368
369define <2 x half> @fmul_sel_op1_use(i1 %b, <2 x half> %p) {
370; CHECK-LABEL: @fmul_sel_op1_use(
371; CHECK-NEXT:    [[X:%.*]] = fadd <2 x half> [[P:%.*]], <half 0xH3C00, half 0xH4000>
372; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], <2 x half> zeroinitializer, <2 x half> splat (half 0xHFFFF)
373; CHECK-NEXT:    call void @use_v2f16(<2 x half> [[S]])
374; CHECK-NEXT:    [[R:%.*]] = fmul nnan nsz <2 x half> [[X]], [[S]]
375; CHECK-NEXT:    ret <2 x half> [[R]]
376;
377  %x = fadd <2 x half> %p, <half 1.0, half 2.0> ; thwart complexity-based canonicalization
378  %s = select i1 %b, <2 x half> zeroinitializer, <2 x half> <half 0xHffff, half 0xHffff>
379  call void @use_v2f16(<2 x half> %s)
380  %r = fmul nnan nsz <2 x half> %x, %s
381  ret <2 x half> %r
382}
383
384define i32 @ashr_sel_op1(i1 %b) {
385; CHECK-LABEL: @ashr_sel_op1(
386; CHECK-NEXT:    [[R:%.*]] = select i1 [[B:%.*]], i32 -1, i32 -2
387; CHECK-NEXT:    ret i32 [[R]]
388;
389  %s = select i1 %b, i32 2, i32 0
390  %r = ashr i32 -2, %s
391  ret i32 %r
392}
393
394define i32 @ashr_sel_op1_use(i1 %b) {
395; CHECK-LABEL: @ashr_sel_op1_use(
396; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], i32 2, i32 0
397; CHECK-NEXT:    call void @use(i32 [[S]])
398; CHECK-NEXT:    [[R:%.*]] = ashr i32 -2, [[S]]
399; CHECK-NEXT:    ret i32 [[R]]
400;
401  %s = select i1 %b, i32 2, i32 0
402  call void @use(i32 %s)
403  %r = ashr i32 -2, %s
404  ret i32 %r
405}
406