[AArch64][NFC] NFC for const vector as Instruction operand (#116790)
[llvm-project.git] / llvm / test / Transforms / InstCombine / commutative-operation-over-selects.ll
bloba992733ebfe074fa221098fb008aa4945ee5dbd6
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
4 declare float @llvm.maxnum.f32(float %a, float %b)
5 declare float @llvm.minnum.f32(float %a, float %b)
6 declare float @llvm.maximum.f32(float %a, float %b)
7 declare float @llvm.minimum.f32(float %a, float %b)
8 declare i32 @llvm.smax.i32(i32 %a, i32 %b)
9 declare i32 @llvm.smin.i32(i32 %a, i32 %b)
10 declare i32 @llvm.umax.i32(i32 %a, i32 %b)
11 declare i32 @llvm.umin.i32(i32 %a, i32 %b)
12 declare i16 @llvm.sadd.sat.i16(i16 %a, i16 %b)
13 declare i16 @llvm.uadd.sat.i16(i16 %a, i16 %b)
14 declare {i16, i1} @llvm.sadd.with.overflow.i16(i16 %a, i16 %b)
15 declare {i16, i1} @llvm.uadd.with.overflow.i16(i16 %a, i16 %b)
16 declare {i16, i1} @llvm.smul.with.overflow.i16(i16 %a, i16 %b)
17 declare {i16, i1} @llvm.umul.with.overflow.i16(i16 %a, i16 %b)
18 declare i16 @llvm.smul.fix.i16(i16 %a, i16 %b, i32 %scale)
19 declare i16 @llvm.umul.fix.i16(i16 %a, i16 %b, i32 %scale)
20 declare i16 @llvm.smul.fix.sat.i16(i16 %a, i16 %b, i32 %scale)
21 declare i16 @llvm.umul.fix.sat.i16(i16 %a, i16 %b, i32 %scale)
22 declare float @llvm.fma.f32(float %a, float %b, float %c)
23 declare float @llvm.fmuladd.f32(float %a, float %b, float %c)
25 define 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]]
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
37 define 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]]
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
49 define <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]]
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
61 define 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]]
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
73 define <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]]
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
85 define 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]]
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
97 define <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]]
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
109 define 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]]
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
121 define <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]]
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
133 define 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]]
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
145 define <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]]
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
157 define 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]]
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
169 define 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]]
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
181 define <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]]
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
193 define 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]]
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
205 define <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]]
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
219 define 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]]
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
231 define 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]]
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
243 define 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]]
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
255 define 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]]
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
267 define 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]]
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
279 define 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]]
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
291 define 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]]
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
303 define 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]]
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
315 define 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]]
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
327 define 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]]
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
339 define 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]]
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
356 overflow:
357   ret i16 0
358 normal:
359   %sum = extractvalue {i16, i1} %res, 0
360   ret i16 %sum
363 define 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]]
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
380 overflow:
381   ret i16 0
382 normal:
383   %sum = extractvalue {i16, i1} %res, 0
384   ret i16 %sum
387 define 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]]
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
404 overflow:
405   ret i16 0
406 normal:
407   %mul = extractvalue {i16, i1} %res, 0
408   ret i16 %mul
411 define 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]]
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
428 overflow:
429   ret i16 0
430 normal:
431   %mul = extractvalue {i16, i1} %res, 0
432   ret i16 %mul
435 define 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]]
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
447 define 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]]
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
459 define 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]]
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
471 define 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]]
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
483 define 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]]
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
495 define 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]]
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
507 ;negative tests:
509 define 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]]
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
523 define 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]]
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
537 define 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]]
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
551 define 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]]
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