xref: /llvm-project/llvm/test/Transforms/InstCombine/commutative-operation-over-selects.ll (revision 88cc35b27e6c7966ab2463fa06d3dd970e88df64)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2; RUN: opt -passes=instcombine -S < %s | FileCheck %s
3
4declare float @llvm.maxnum.f32(float %a, float %b)
5declare float @llvm.minnum.f32(float %a, float %b)
6declare float @llvm.maximum.f32(float %a, float %b)
7declare float @llvm.minimum.f32(float %a, float %b)
8declare i32 @llvm.smax.i32(i32 %a, i32 %b)
9declare i32 @llvm.smin.i32(i32 %a, i32 %b)
10declare i32 @llvm.umax.i32(i32 %a, i32 %b)
11declare i32 @llvm.umin.i32(i32 %a, i32 %b)
12declare i16 @llvm.sadd.sat.i16(i16 %a, i16 %b)
13declare i16 @llvm.uadd.sat.i16(i16 %a, i16 %b)
14declare {i16, i1} @llvm.sadd.with.overflow.i16(i16 %a, i16 %b)
15declare {i16, i1} @llvm.uadd.with.overflow.i16(i16 %a, i16 %b)
16declare {i16, i1} @llvm.smul.with.overflow.i16(i16 %a, i16 %b)
17declare {i16, i1} @llvm.umul.with.overflow.i16(i16 %a, i16 %b)
18declare i16 @llvm.smul.fix.i16(i16 %a, i16 %b, i32 %scale)
19declare i16 @llvm.umul.fix.i16(i16 %a, i16 %b, i32 %scale)
20declare i16 @llvm.smul.fix.sat.i16(i16 %a, i16 %b, i32 %scale)
21declare i16 @llvm.umul.fix.sat.i16(i16 %a, i16 %b, i32 %scale)
22declare float @llvm.fma.f32(float %a, float %b, float %c)
23declare float @llvm.fmuladd.f32(float %a, float %b, float %c)
24
25define i8 @fold_select_mul(i1 %c, i8 %a, i8 %b) {
26; CHECK-LABEL: define i8 @fold_select_mul(
27; CHECK-SAME: i1 [[C:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]) {
28; CHECK-NEXT:    [[RET:%.*]] = mul i8 [[B]], [[A]]
29; CHECK-NEXT:    ret i8 [[RET]]
30;
31  %s0 = select i1 %c, i8 %a, i8 %b
32  %s1 = select i1 %c, i8 %b, i8 %a
33  %ret = mul i8 %s1, %s0
34  ret i8 %ret
35}
36
37define i8 @fold_select_mul_nsw_nuw_preserve(i1 %c, i8 %a, i8 %b) {
38; CHECK-LABEL: define i8 @fold_select_mul_nsw_nuw_preserve(
39; CHECK-SAME: i1 [[C:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]) {
40; CHECK-NEXT:    [[RET:%.*]] = mul nuw nsw i8 [[B]], [[A]]
41; CHECK-NEXT:    ret i8 [[RET]]
42;
43  %s0 = select i1 %c, i8 %a, i8 %b
44  %s1 = select i1 %c, i8 %b, i8 %a
45  %ret = mul nsw nuw i8 %s1, %s0
46  ret i8 %ret
47}
48
49define <2 x i4> @fold_select_mul_vec2(i1 %c, <2 x i4> %a, <2 x i4> %b) {
50; CHECK-LABEL: define <2 x i4> @fold_select_mul_vec2(
51; CHECK-SAME: i1 [[C:%.*]], <2 x i4> [[A:%.*]], <2 x i4> [[B:%.*]]) {
52; CHECK-NEXT:    [[RET:%.*]] = mul <2 x i4> [[B]], [[A]]
53; CHECK-NEXT:    ret <2 x i4> [[RET]]
54;
55  %s0 = select i1 %c, <2 x i4> %a, <2 x i4> %b
56  %s1 = select i1 %c, <2 x i4> %b, <2 x i4> %a
57  %ret = mul <2 x i4> %s1, %s0
58  ret <2 x i4> %ret
59}
60
61define i8 @fold_select_add(i1 %c, i8 %a, i8 %b) {
62; CHECK-LABEL: define i8 @fold_select_add(
63; CHECK-SAME: i1 [[C:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]) {
64; CHECK-NEXT:    [[RET:%.*]] = add i8 [[B]], [[A]]
65; CHECK-NEXT:    ret i8 [[RET]]
66;
67  %s0 = select i1 %c, i8 %a, i8 %b
68  %s1 = select i1 %c, i8 %b, i8 %a
69  %ret = add i8 %s1, %s0
70  ret i8 %ret
71}
72
73define <2 x i4> @fold_select_add_vec2(i1 %c, <2 x i4> %a, <2 x i4> %b) {
74; CHECK-LABEL: define <2 x i4> @fold_select_add_vec2(
75; CHECK-SAME: i1 [[C:%.*]], <2 x i4> [[A:%.*]], <2 x i4> [[B:%.*]]) {
76; CHECK-NEXT:    [[RET:%.*]] = add <2 x i4> [[B]], [[A]]
77; CHECK-NEXT:    ret <2 x i4> [[RET]]
78;
79  %s0 = select i1 %c, <2 x i4> %a, <2 x i4> %b
80  %s1 = select i1 %c, <2 x i4> %b, <2 x i4> %a
81  %ret = add <2 x i4> %s1, %s0
82  ret <2 x i4> %ret
83}
84
85define i8 @fold_select_and(i1 %c, i8 %a, i8 %b) {
86; CHECK-LABEL: define i8 @fold_select_and(
87; CHECK-SAME: i1 [[C:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]) {
88; CHECK-NEXT:    [[RET:%.*]] = and i8 [[B]], [[A]]
89; CHECK-NEXT:    ret i8 [[RET]]
90;
91  %s0 = select i1 %c, i8 %a, i8 %b
92  %s1 = select i1 %c, i8 %b, i8 %a
93  %ret = and i8 %s1, %s0
94  ret i8 %ret
95}
96
97define <2 x i4> @fold_select_and_vec2(i1 %c, <2 x i4> %a, <2 x i4> %b) {
98; CHECK-LABEL: define <2 x i4> @fold_select_and_vec2(
99; CHECK-SAME: i1 [[C:%.*]], <2 x i4> [[A:%.*]], <2 x i4> [[B:%.*]]) {
100; CHECK-NEXT:    [[RET:%.*]] = and <2 x i4> [[B]], [[A]]
101; CHECK-NEXT:    ret <2 x i4> [[RET]]
102;
103  %s0 = select i1 %c, <2 x i4> %a, <2 x i4> %b
104  %s1 = select i1 %c, <2 x i4> %b, <2 x i4> %a
105  %ret = and <2 x i4> %s1, %s0
106  ret <2 x i4> %ret
107}
108
109define i8 @fold_select_or(i1 %c, i8 %a, i8 %b) {
110; CHECK-LABEL: define i8 @fold_select_or(
111; CHECK-SAME: i1 [[C:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]) {
112; CHECK-NEXT:    [[RET:%.*]] = or i8 [[B]], [[A]]
113; CHECK-NEXT:    ret i8 [[RET]]
114;
115  %s0 = select i1 %c, i8 %a, i8 %b
116  %s1 = select i1 %c, i8 %b, i8 %a
117  %ret = or i8 %s1, %s0
118  ret i8 %ret
119}
120
121define <2 x i4> @fold_select_or_vec2(i1 %c, <2 x i4> %a, <2 x i4> %b) {
122; CHECK-LABEL: define <2 x i4> @fold_select_or_vec2(
123; CHECK-SAME: i1 [[C:%.*]], <2 x i4> [[A:%.*]], <2 x i4> [[B:%.*]]) {
124; CHECK-NEXT:    [[RET:%.*]] = or <2 x i4> [[B]], [[A]]
125; CHECK-NEXT:    ret <2 x i4> [[RET]]
126;
127  %s0 = select i1 %c, <2 x i4> %a, <2 x i4> %b
128  %s1 = select i1 %c, <2 x i4> %b, <2 x i4> %a
129  %ret = or <2 x i4> %s1, %s0
130  ret <2 x i4> %ret
131}
132
133define i8 @fold_select_xor(i1 %c, i8 %a, i8 %b) {
134; CHECK-LABEL: define i8 @fold_select_xor(
135; CHECK-SAME: i1 [[C:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]) {
136; CHECK-NEXT:    [[RET:%.*]] = xor i8 [[B]], [[A]]
137; CHECK-NEXT:    ret i8 [[RET]]
138;
139  %s0 = select i1 %c, i8 %a, i8 %b
140  %s1 = select i1 %c, i8 %b, i8 %a
141  %ret = xor i8 %s1, %s0
142  ret i8 %ret
143}
144
145define <2 x i4> @fold_select_xor_vec2(i1 %c, <2 x i4> %a, <2 x i4> %b) {
146; CHECK-LABEL: define <2 x i4> @fold_select_xor_vec2(
147; CHECK-SAME: i1 [[C:%.*]], <2 x i4> [[A:%.*]], <2 x i4> [[B:%.*]]) {
148; CHECK-NEXT:    [[RET:%.*]] = xor <2 x i4> [[B]], [[A]]
149; CHECK-NEXT:    ret <2 x i4> [[RET]]
150;
151  %s0 = select i1 %c, <2 x i4> %a, <2 x i4> %b
152  %s1 = select i1 %c, <2 x i4> %b, <2 x i4> %a
153  %ret = xor <2 x i4> %s1, %s0
154  ret <2 x i4> %ret
155}
156
157define float @fold_select_fadd(i1 %c, float %a, float %b) {
158; CHECK-LABEL: define float @fold_select_fadd(
159; CHECK-SAME: i1 [[C:%.*]], float [[A:%.*]], float [[B:%.*]]) {
160; CHECK-NEXT:    [[RET:%.*]] = fadd float [[B]], [[A]]
161; CHECK-NEXT:    ret float [[RET]]
162;
163  %s0 = select i1 %c, float %a, float %b
164  %s1 = select i1 %c, float %b, float %a
165  %ret = fadd float %s1, %s0
166  ret float %ret
167}
168
169define float @fold_select_fadd_nnan(i1 %c, float %a, float %b) {
170; CHECK-LABEL: define float @fold_select_fadd_nnan(
171; CHECK-SAME: i1 [[C:%.*]], float [[A:%.*]], float [[B:%.*]]) {
172; CHECK-NEXT:    [[RET:%.*]] = fadd nnan float [[B]], [[A]]
173; CHECK-NEXT:    ret float [[RET]]
174;
175  %s0 = select i1 %c, float %a, float %b
176  %s1 = select i1 %c, float %b, float %a
177  %ret = fadd nnan float %s1, %s0
178  ret float %ret
179}
180
181define <2 x float> @fold_select_fadd_vec2(i1 %c, <2 x float> %a, <2 x float> %b) {
182; CHECK-LABEL: define <2 x float> @fold_select_fadd_vec2(
183; CHECK-SAME: i1 [[C:%.*]], <2 x float> [[A:%.*]], <2 x float> [[B:%.*]]) {
184; CHECK-NEXT:    [[RET:%.*]] = fadd <2 x float> [[B]], [[A]]
185; CHECK-NEXT:    ret <2 x float> [[RET]]
186;
187  %s0 = select i1 %c, <2 x float> %a, <2 x float> %b
188  %s1 = select i1 %c, <2 x float> %b, <2 x float> %a
189  %ret = fadd <2 x float> %s1, %s0
190  ret <2 x float> %ret
191}
192
193define float @fold_select_fmul(i1 %c, float %a, float %b) {
194; CHECK-LABEL: define float @fold_select_fmul(
195; CHECK-SAME: i1 [[C:%.*]], float [[A:%.*]], float [[B:%.*]]) {
196; CHECK-NEXT:    [[RET:%.*]] = fmul float [[B]], [[A]]
197; CHECK-NEXT:    ret float [[RET]]
198;
199  %s0 = select i1 %c, float %a, float %b
200  %s1 = select i1 %c, float %b, float %a
201  %ret = fmul float %s1, %s0
202  ret float %ret
203}
204
205define <2 x float> @fold_select_fmul_vec2(i1 %c, <2 x float> %a, <2 x float> %b) {
206; CHECK-LABEL: define <2 x float> @fold_select_fmul_vec2(
207; CHECK-SAME: i1 [[C:%.*]], <2 x float> [[A:%.*]], <2 x float> [[B:%.*]]) {
208; CHECK-NEXT:    [[RET:%.*]] = fmul <2 x float> [[B]], [[A]]
209; CHECK-NEXT:    ret <2 x float> [[RET]]
210;
211  %s0 = select i1 %c, <2 x float> %a, <2 x float> %b
212  %s1 = select i1 %c, <2 x float> %b, <2 x float> %a
213  %ret = fmul <2 x float> %s1, %s0
214  ret <2 x float> %ret
215}
216
217;
218
219define float @fold_select_maxnum(i1 %c, float %a, float %b) {
220; CHECK-LABEL: define float @fold_select_maxnum(
221; CHECK-SAME: i1 [[C:%.*]], float [[A:%.*]], float [[B:%.*]]) {
222; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.maxnum.f32(float [[B]], float [[A]])
223; CHECK-NEXT:    ret float [[RET]]
224;
225  %s0 = select i1 %c, float %a, float %b
226  %s1 = select i1 %c, float %b, float %a
227  %ret = call float @llvm.maxnum.f32(float %s1, float %s0)
228  ret float %ret
229}
230
231define float @fold_select_minnum(i1 %c, float %a, float %b) {
232; CHECK-LABEL: define float @fold_select_minnum(
233; CHECK-SAME: i1 [[C:%.*]], float [[A:%.*]], float [[B:%.*]]) {
234; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.minnum.f32(float [[B]], float [[A]])
235; CHECK-NEXT:    ret float [[RET]]
236;
237  %s0 = select i1 %c, float %a, float %b
238  %s1 = select i1 %c, float %b, float %a
239  %ret = call float @llvm.minnum.f32(float %s1, float %s0)
240  ret float %ret
241}
242
243define float @fold_select_maximum(i1 %c, float %a, float %b) {
244; CHECK-LABEL: define float @fold_select_maximum(
245; CHECK-SAME: i1 [[C:%.*]], float [[A:%.*]], float [[B:%.*]]) {
246; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.maximum.f32(float [[B]], float [[A]])
247; CHECK-NEXT:    ret float [[RET]]
248;
249  %s0 = select i1 %c, float %a, float %b
250  %s1 = select i1 %c, float %b, float %a
251  %ret = call float @llvm.maximum.f32(float %s1, float %s0)
252  ret float %ret
253}
254
255define float @fold_select_minimum(i1 %c, float %a, float %b) {
256; CHECK-LABEL: define float @fold_select_minimum(
257; CHECK-SAME: i1 [[C:%.*]], float [[A:%.*]], float [[B:%.*]]) {
258; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.minimum.f32(float [[B]], float [[A]])
259; CHECK-NEXT:    ret float [[RET]]
260;
261  %s0 = select i1 %c, float %a, float %b
262  %s1 = select i1 %c, float %b, float %a
263  %ret = call float @llvm.minimum.f32(float %s1, float %s0)
264  ret float %ret
265}
266
267define i32 @fold_select_smax(i1 %c, i32 %a, i32 %b) {
268; CHECK-LABEL: define i32 @fold_select_smax(
269; CHECK-SAME: i1 [[C:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) {
270; CHECK-NEXT:    [[RET:%.*]] = call i32 @llvm.smax.i32(i32 [[B]], i32 [[A]])
271; CHECK-NEXT:    ret i32 [[RET]]
272;
273  %s0 = select i1 %c, i32 %a, i32 %b
274  %s1 = select i1 %c, i32 %b, i32 %a
275  %ret = call i32 @llvm.smax.i32(i32 %s1, i32 %s0)
276  ret i32 %ret
277}
278
279define i32 @fold_select_smin(i1 %c, i32 %a, i32 %b) {
280; CHECK-LABEL: define i32 @fold_select_smin(
281; CHECK-SAME: i1 [[C:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) {
282; CHECK-NEXT:    [[RET:%.*]] = call i32 @llvm.smin.i32(i32 [[B]], i32 [[A]])
283; CHECK-NEXT:    ret i32 [[RET]]
284;
285  %s0 = select i1 %c, i32 %a, i32 %b
286  %s1 = select i1 %c, i32 %b, i32 %a
287  %ret = call i32 @llvm.smin.i32(i32 %s1, i32 %s0)
288  ret i32 %ret
289}
290
291define i32 @fold_select_umax(i1 %c, i32 %a, i32 %b) {
292; CHECK-LABEL: define i32 @fold_select_umax(
293; CHECK-SAME: i1 [[C:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) {
294; CHECK-NEXT:    [[RET:%.*]] = call i32 @llvm.umax.i32(i32 [[B]], i32 [[A]])
295; CHECK-NEXT:    ret i32 [[RET]]
296;
297  %s0 = select i1 %c, i32 %a, i32 %b
298  %s1 = select i1 %c, i32 %b, i32 %a
299  %ret = call i32 @llvm.umax.i32(i32 %s1, i32 %s0)
300  ret i32 %ret
301}
302
303define i32 @fold_select_umin(i1 %c, i32 %a, i32 %b) {
304; CHECK-LABEL: define i32 @fold_select_umin(
305; CHECK-SAME: i1 [[C:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) {
306; CHECK-NEXT:    [[RET:%.*]] = call i32 @llvm.umin.i32(i32 [[B]], i32 [[A]])
307; CHECK-NEXT:    ret i32 [[RET]]
308;
309  %s0 = select i1 %c, i32 %a, i32 %b
310  %s1 = select i1 %c, i32 %b, i32 %a
311  %ret = call i32 @llvm.umin.i32(i32 %s1, i32 %s0)
312  ret i32 %ret
313}
314
315define i16 @fold_select_sadd_sat(i1 %c, i16 %a, i16 %b) {
316; CHECK-LABEL: define i16 @fold_select_sadd_sat(
317; CHECK-SAME: i1 [[C:%.*]], i16 [[A:%.*]], i16 [[B:%.*]]) {
318; CHECK-NEXT:    [[RET:%.*]] = call i16 @llvm.sadd.sat.i16(i16 [[B]], i16 [[A]])
319; CHECK-NEXT:    ret i16 [[RET]]
320;
321  %s0 = select i1 %c, i16 %a, i16 %b
322  %s1 = select i1 %c, i16 %b, i16 %a
323  %ret = call i16 @llvm.sadd.sat.i16(i16 %s1, i16 %s0)
324  ret i16 %ret
325}
326
327define i16 @fold_select_uadd_sat(i1 %c, i16 %a, i16 %b) {
328; CHECK-LABEL: define i16 @fold_select_uadd_sat(
329; CHECK-SAME: i1 [[C:%.*]], i16 [[A:%.*]], i16 [[B:%.*]]) {
330; CHECK-NEXT:    [[RET:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[B]], i16 [[A]])
331; CHECK-NEXT:    ret i16 [[RET]]
332;
333  %s0 = select i1 %c, i16 %a, i16 %b
334  %s1 = select i1 %c, i16 %b, i16 %a
335  %ret = call i16 @llvm.uadd.sat.i16(i16 %s1, i16 %s0)
336  ret i16 %ret
337}
338
339define i16 @fold_select_sadd_with_overflow(i1 %c, i16 %a, i16 %b) {
340; CHECK-LABEL: define i16 @fold_select_sadd_with_overflow(
341; CHECK-SAME: i1 [[C:%.*]], i16 [[A:%.*]], i16 [[B:%.*]]) {
342; CHECK-NEXT:    [[RES:%.*]] = call { i16, i1 } @llvm.sadd.with.overflow.i16(i16 [[B]], i16 [[A]])
343; CHECK-NEXT:    [[OBIT:%.*]] = extractvalue { i16, i1 } [[RES]], 1
344; CHECK-NEXT:    br i1 [[OBIT]], label [[OVERFLOW:%.*]], label [[NORMAL:%.*]]
345; CHECK:       overflow:
346; CHECK-NEXT:    ret i16 0
347; CHECK:       normal:
348; CHECK-NEXT:    [[SUM:%.*]] = extractvalue { i16, i1 } [[RES]], 0
349; CHECK-NEXT:    ret i16 [[SUM]]
350;
351  %s0 = select i1 %c, i16 %a, i16 %b
352  %s1 = select i1 %c, i16 %b, i16 %a
353  %res = call {i16, i1} @llvm.sadd.with.overflow.i16(i16 %s1, i16 %s0)
354  %obit = extractvalue {i16, i1} %res, 1
355  br i1 %obit, label %overflow, label %normal
356overflow:
357  ret i16 0
358normal:
359  %sum = extractvalue {i16, i1} %res, 0
360  ret i16 %sum
361}
362
363define i16 @fold_select_uadd_with_overflow(i1 %c, i16 %a, i16 %b) {
364; CHECK-LABEL: define i16 @fold_select_uadd_with_overflow(
365; CHECK-SAME: i1 [[C:%.*]], i16 [[A:%.*]], i16 [[B:%.*]]) {
366; CHECK-NEXT:    [[RES:%.*]] = call { i16, i1 } @llvm.uadd.with.overflow.i16(i16 [[B]], i16 [[A]])
367; CHECK-NEXT:    [[OBIT:%.*]] = extractvalue { i16, i1 } [[RES]], 1
368; CHECK-NEXT:    br i1 [[OBIT]], label [[OVERFLOW:%.*]], label [[NORMAL:%.*]]
369; CHECK:       overflow:
370; CHECK-NEXT:    ret i16 0
371; CHECK:       normal:
372; CHECK-NEXT:    [[SUM:%.*]] = extractvalue { i16, i1 } [[RES]], 0
373; CHECK-NEXT:    ret i16 [[SUM]]
374;
375  %s0 = select i1 %c, i16 %a, i16 %b
376  %s1 = select i1 %c, i16 %b, i16 %a
377  %res = call {i16, i1} @llvm.uadd.with.overflow.i16(i16 %s1, i16 %s0)
378  %obit = extractvalue {i16, i1} %res, 1
379  br i1 %obit, label %overflow, label %normal
380overflow:
381  ret i16 0
382normal:
383  %sum = extractvalue {i16, i1} %res, 0
384  ret i16 %sum
385}
386
387define i16 @fold_select_smul_with_overflow(i1 %c, i16 %a, i16 %b) {
388; CHECK-LABEL: define i16 @fold_select_smul_with_overflow(
389; CHECK-SAME: i1 [[C:%.*]], i16 [[A:%.*]], i16 [[B:%.*]]) {
390; CHECK-NEXT:    [[RES:%.*]] = call { i16, i1 } @llvm.smul.with.overflow.i16(i16 [[B]], i16 [[A]])
391; CHECK-NEXT:    [[OBIT:%.*]] = extractvalue { i16, i1 } [[RES]], 1
392; CHECK-NEXT:    br i1 [[OBIT]], label [[OVERFLOW:%.*]], label [[NORMAL:%.*]]
393; CHECK:       overflow:
394; CHECK-NEXT:    ret i16 0
395; CHECK:       normal:
396; CHECK-NEXT:    [[MUL:%.*]] = extractvalue { i16, i1 } [[RES]], 0
397; CHECK-NEXT:    ret i16 [[MUL]]
398;
399  %s0 = select i1 %c, i16 %a, i16 %b
400  %s1 = select i1 %c, i16 %b, i16 %a
401  %res = call {i16, i1} @llvm.smul.with.overflow.i16(i16 %s1, i16 %s0)
402  %obit = extractvalue {i16, i1} %res, 1
403  br i1 %obit, label %overflow, label %normal
404overflow:
405  ret i16 0
406normal:
407  %mul = extractvalue {i16, i1} %res, 0
408  ret i16 %mul
409}
410
411define i16 @fold_select_umul_with_overflow(i1 %c, i16 %a, i16 %b) {
412; CHECK-LABEL: define i16 @fold_select_umul_with_overflow(
413; CHECK-SAME: i1 [[C:%.*]], i16 [[A:%.*]], i16 [[B:%.*]]) {
414; CHECK-NEXT:    [[RES:%.*]] = call { i16, i1 } @llvm.umul.with.overflow.i16(i16 [[B]], i16 [[A]])
415; CHECK-NEXT:    [[OBIT:%.*]] = extractvalue { i16, i1 } [[RES]], 1
416; CHECK-NEXT:    br i1 [[OBIT]], label [[OVERFLOW:%.*]], label [[NORMAL:%.*]]
417; CHECK:       overflow:
418; CHECK-NEXT:    ret i16 0
419; CHECK:       normal:
420; CHECK-NEXT:    [[MUL:%.*]] = extractvalue { i16, i1 } [[RES]], 0
421; CHECK-NEXT:    ret i16 [[MUL]]
422;
423  %s0 = select i1 %c, i16 %a, i16 %b
424  %s1 = select i1 %c, i16 %b, i16 %a
425  %res = call {i16, i1} @llvm.umul.with.overflow.i16(i16 %s1, i16 %s0)
426  %obit = extractvalue {i16, i1} %res, 1
427  br i1 %obit, label %overflow, label %normal
428overflow:
429  ret i16 0
430normal:
431  %mul = extractvalue {i16, i1} %res, 0
432  ret i16 %mul
433}
434
435define i16 @fold_select_smul_fix(i1 %c, i16 %a, i16 %b, i32 %y) {
436; CHECK-LABEL: define i16 @fold_select_smul_fix(
437; CHECK-SAME: i1 [[C:%.*]], i16 [[A:%.*]], i16 [[B:%.*]], i32 [[Y:%.*]]) {
438; CHECK-NEXT:    [[RET:%.*]] = call i16 @llvm.smul.fix.i16(i16 [[B]], i16 [[A]], i32 1)
439; CHECK-NEXT:    ret i16 [[RET]]
440;
441  %s0 = select i1 %c, i16 %a, i16 %b
442  %s1 = select i1 %c, i16 %b, i16 %a
443  %ret = call i16 @llvm.smul.fix.i16(i16 %s1, i16 %s0, i32 1)
444  ret i16 %ret
445}
446
447define i16 @fold_select_umul_fix(i1 %c, i16 %a, i16 %b, i32 %y) {
448; CHECK-LABEL: define i16 @fold_select_umul_fix(
449; CHECK-SAME: i1 [[C:%.*]], i16 [[A:%.*]], i16 [[B:%.*]], i32 [[Y:%.*]]) {
450; CHECK-NEXT:    [[RET:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[B]], i16 [[A]], i32 1)
451; CHECK-NEXT:    ret i16 [[RET]]
452;
453  %s0 = select i1 %c, i16 %a, i16 %b
454  %s1 = select i1 %c, i16 %b, i16 %a
455  %ret = call i16 @llvm.umul.fix.i16(i16 %s1, i16 %s0, i32 1)
456  ret i16 %ret
457}
458
459define i16 @fold_select_smul_fix_sat(i1 %c, i16 %a, i16 %b, i32 %y) {
460; CHECK-LABEL: define i16 @fold_select_smul_fix_sat(
461; CHECK-SAME: i1 [[C:%.*]], i16 [[A:%.*]], i16 [[B:%.*]], i32 [[Y:%.*]]) {
462; CHECK-NEXT:    [[RET:%.*]] = call i16 @llvm.smul.fix.sat.i16(i16 [[B]], i16 [[A]], i32 1)
463; CHECK-NEXT:    ret i16 [[RET]]
464;
465  %s0 = select i1 %c, i16 %a, i16 %b
466  %s1 = select i1 %c, i16 %b, i16 %a
467  %ret = call i16 @llvm.smul.fix.sat.i16(i16 %s1, i16 %s0, i32 1)
468  ret i16 %ret
469}
470
471define i16 @fold_select_umul_fix_sat(i1 %c, i16 %a, i16 %b, i32 %y) {
472; CHECK-LABEL: define i16 @fold_select_umul_fix_sat(
473; CHECK-SAME: i1 [[C:%.*]], i16 [[A:%.*]], i16 [[B:%.*]], i32 [[Y:%.*]]) {
474; CHECK-NEXT:    [[RET:%.*]] = call i16 @llvm.umul.fix.sat.i16(i16 [[B]], i16 [[A]], i32 1)
475; CHECK-NEXT:    ret i16 [[RET]]
476;
477  %s0 = select i1 %c, i16 %a, i16 %b
478  %s1 = select i1 %c, i16 %b, i16 %a
479  %ret = call i16 @llvm.umul.fix.sat.i16(i16 %s1, i16 %s0, i32 1)
480  ret i16 %ret
481}
482
483define float @fold_select_fma(i1 %c, float %a, float %b, float %y) {
484; CHECK-LABEL: define float @fold_select_fma(
485; CHECK-SAME: i1 [[C:%.*]], float [[A:%.*]], float [[B:%.*]], float [[Y:%.*]]) {
486; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.fma.f32(float [[B]], float [[A]], float [[Y]])
487; CHECK-NEXT:    ret float [[RET]]
488;
489  %s0 = select i1 %c, float %a, float %b
490  %s1 = select i1 %c, float %b, float %a
491  %ret = call float @llvm.fma.f32(float %s1, float %s0, float %y)
492  ret float %ret
493}
494
495define float @fold_select_fmuladd(i1 %c, float %a, float %b, float %y) {
496; CHECK-LABEL: define float @fold_select_fmuladd(
497; CHECK-SAME: i1 [[C:%.*]], float [[A:%.*]], float [[B:%.*]], float [[Y:%.*]]) {
498; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.fmuladd.f32(float [[B]], float [[A]], float [[Y]])
499; CHECK-NEXT:    ret float [[RET]]
500;
501  %s0 = select i1 %c, float %a, float %b
502  %s1 = select i1 %c, float %b, float %a
503  %ret = call float @llvm.fmuladd.f32(float %s1, float %s0, float %y)
504  ret float %ret
505}
506
507;negative tests:
508
509define i8 @fold_select_unmatch_mul_neg(i1 %c, i1 %c1, i8 %a, i8 %b) {
510; CHECK-LABEL: define i8 @fold_select_unmatch_mul_neg(
511; CHECK-SAME: i1 [[C:%.*]], i1 [[C1:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]) {
512; CHECK-NEXT:    [[S0:%.*]] = select i1 [[C]], i8 [[A]], i8 [[B]]
513; CHECK-NEXT:    [[S1:%.*]] = select i1 [[C1]], i8 [[B]], i8 [[A]]
514; CHECK-NEXT:    [[RET:%.*]] = mul i8 [[S1]], [[S0]]
515; CHECK-NEXT:    ret i8 [[RET]]
516;
517  %s0 = select i1 %c, i8 %a, i8 %b
518  %s1 = select i1 %c1, i8 %b, i8 %a
519  %ret = mul i8 %s1, %s0
520  ret i8 %ret
521}
522
523define i8 @fold_select_sub_neg(i1 %c, i8 %a, i8 %b) {
524; CHECK-LABEL: define i8 @fold_select_sub_neg(
525; CHECK-SAME: i1 [[C:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]) {
526; CHECK-NEXT:    [[S0:%.*]] = select i1 [[C]], i8 [[A]], i8 [[B]]
527; CHECK-NEXT:    [[S1:%.*]] = select i1 [[C]], i8 [[B]], i8 [[A]]
528; CHECK-NEXT:    [[RET:%.*]] = sub i8 [[S1]], [[S0]]
529; CHECK-NEXT:    ret i8 [[RET]]
530;
531  %s0 = select i1 %c, i8 %a, i8 %b
532  %s1 = select i1 %c, i8 %b, i8 %a
533  %ret = sub i8 %s1, %s0
534  ret i8 %ret
535}
536
537define float @fold_select_fma_neg(i1 %c, i1 %c1, float %a, float %b, float %y) {
538; CHECK-LABEL: define float @fold_select_fma_neg(
539; CHECK-SAME: i1 [[C:%.*]], i1 [[C1:%.*]], float [[A:%.*]], float [[B:%.*]], float [[Y:%.*]]) {
540; CHECK-NEXT:    [[S0:%.*]] = select i1 [[C]], float [[A]], float [[B]]
541; CHECK-NEXT:    [[S1:%.*]] = select i1 [[C1]], float [[B]], float [[A]]
542; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.fma.f32(float [[S1]], float [[S0]], float [[Y]])
543; CHECK-NEXT:    ret float [[RET]]
544;
545  %s0 = select i1 %c, float %a, float %b
546  %s1 = select i1 %c1, float %b, float %a
547  %ret = call float @llvm.fma.f32(float %s1, float %s0, float %y)
548  ret float %ret
549}
550
551define float @fold_select_fma_match_neg(i1 %c, float %a, float %b, float %y) {
552; CHECK-LABEL: define float @fold_select_fma_match_neg(
553; CHECK-SAME: i1 [[C:%.*]], float [[A:%.*]], float [[B:%.*]], float [[Y:%.*]]) {
554; CHECK-NEXT:    [[S0:%.*]] = select i1 [[C]], float [[A]], float [[B]]
555; CHECK-NEXT:    [[S1:%.*]] = select i1 [[C]], float [[B]], float [[A]]
556; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.fma.f32(float [[Y]], float [[S0]], float [[S1]])
557; CHECK-NEXT:    ret float [[RET]]
558;
559  %s0 = select i1 %c, float %a, float %b
560  %s1 = select i1 %c, float %b, float %a
561  %ret = call float @llvm.fma.f32(float %y, float %s0, float %s1)
562  ret float %ret
563}
564