xref: /llvm-project/llvm/test/Transforms/InstCombine/fma.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 float @llvm.fma.f32(float, float, float)
5declare <2 x float> @llvm.fma.v2f32(<2 x float>, <2 x float>, <2 x float>)
6declare <3 x float> @llvm.fma.v3f32(<3 x float>, <3 x float>, <3 x float>)
7declare <8 x half> @llvm.fma.v8f16(<8 x half>, <8 x half>, <8 x half>)
8declare <2 x double> @llvm.fma.v2f64(<2 x double>, <2 x double>, <2 x double>)
9
10declare float @llvm.fmuladd.f32(float, float, float)
11declare <2 x double> @llvm.fmuladd.v2f64(<2 x double>, <2 x double>, <2 x double>)
12declare float @llvm.fabs.f32(float)
13declare <2 x double> @llvm.sqrt.v2f64(<2 x double>)
14declare void @use_vec(<2 x float>)
15declare void @use_vec3(<3 x float>)
16
17@external = external global i32
18
19define float @fma_fneg_x_fneg_y(float %x, float %y, float %z) {
20; CHECK-LABEL: @fma_fneg_x_fneg_y(
21; CHECK-NEXT:    [[FMA:%.*]] = call float @llvm.fma.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]])
22; CHECK-NEXT:    ret float [[FMA]]
23;
24  %x.fneg = fsub float -0.0, %x
25  %y.fneg = fsub float -0.0, %y
26  %fma = call float @llvm.fma.f32(float %x.fneg, float %y.fneg, float %z)
27  ret float %fma
28}
29
30define float @fma_unary_fneg_x_unary_fneg_y(float %x, float %y, float %z) {
31; CHECK-LABEL: @fma_unary_fneg_x_unary_fneg_y(
32; CHECK-NEXT:    [[FMA:%.*]] = call float @llvm.fma.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]])
33; CHECK-NEXT:    ret float [[FMA]]
34;
35  %x.fneg = fneg float %x
36  %y.fneg = fneg float %y
37  %fma = call float @llvm.fma.f32(float %x.fneg, float %y.fneg, float %z)
38  ret float %fma
39}
40
41define <2 x float> @fma_fneg_x_fneg_y_vec(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
42; CHECK-LABEL: @fma_fneg_x_fneg_y_vec(
43; CHECK-NEXT:    [[FMA:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]], <2 x float> [[Z:%.*]])
44; CHECK-NEXT:    ret <2 x float> [[FMA]]
45;
46  %xn = fsub <2 x float> <float -0.0, float -0.0>, %x
47  %yn = fsub <2 x float> <float -0.0, float -0.0>, %y
48  %fma = call <2 x float> @llvm.fma.v2f32(<2 x float> %xn, <2 x float> %yn, <2 x float> %z)
49  ret <2 x float> %fma
50}
51
52define <2 x float> @fma_unary_fneg_x_unary_fneg_y_vec(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
53; CHECK-LABEL: @fma_unary_fneg_x_unary_fneg_y_vec(
54; CHECK-NEXT:    [[FMA:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]], <2 x float> [[Z:%.*]])
55; CHECK-NEXT:    ret <2 x float> [[FMA]]
56;
57  %xn = fneg <2 x float> %x
58  %yn = fneg <2 x float> %y
59  %fma = call <2 x float> @llvm.fma.v2f32(<2 x float> %xn, <2 x float> %yn, <2 x float> %z)
60  ret <2 x float> %fma
61}
62
63define <2 x float> @fma_fneg_x_fneg_y_vec_poison(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
64; CHECK-LABEL: @fma_fneg_x_fneg_y_vec_poison(
65; CHECK-NEXT:    [[FMA:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]], <2 x float> [[Z:%.*]])
66; CHECK-NEXT:    ret <2 x float> [[FMA]]
67;
68  %xn = fsub <2 x float> <float -0.0, float poison>, %x
69  %yn = fsub <2 x float> <float poison, float -0.0>, %y
70  %fma = call <2 x float> @llvm.fma.v2f32(<2 x float> %xn, <2 x float> %yn, <2 x float> %z)
71  ret <2 x float> %fma
72}
73
74define float @fma_fneg_x_fneg_y_fast(float %x, float %y, float %z) {
75; CHECK-LABEL: @fma_fneg_x_fneg_y_fast(
76; CHECK-NEXT:    [[FMA:%.*]] = call fast float @llvm.fma.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]])
77; CHECK-NEXT:    ret float [[FMA]]
78;
79  %x.fneg = fsub float -0.0, %x
80  %y.fneg = fsub float -0.0, %y
81  %fma = call fast float @llvm.fma.f32(float %x.fneg, float %y.fneg, float %z)
82  ret float %fma
83}
84
85define float @fma_unary_fneg_x_unary_fneg_y_fast(float %x, float %y, float %z) {
86; CHECK-LABEL: @fma_unary_fneg_x_unary_fneg_y_fast(
87; CHECK-NEXT:    [[FMA:%.*]] = call fast float @llvm.fma.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]])
88; CHECK-NEXT:    ret float [[FMA]]
89;
90  %x.fneg = fneg float %x
91  %y.fneg = fneg float %y
92  %fma = call fast float @llvm.fma.f32(float %x.fneg, float %y.fneg, float %z)
93  ret float %fma
94}
95
96define float @fma_fneg_const_fneg_y(float %y, float %z) {
97; CHECK-LABEL: @fma_fneg_const_fneg_y(
98; CHECK-NEXT:    [[FMA:%.*]] = call float @llvm.fma.f32(float [[Y:%.*]], float bitcast (i32 ptrtoint (ptr @external to i32) to float), float [[Z:%.*]])
99; CHECK-NEXT:    ret float [[FMA]]
100;
101  %y.fneg = fsub float -0.0, %y
102  %fsub = fsub float -0.0, bitcast (i32 ptrtoint (ptr @external to i32) to float)
103  %fma = call float @llvm.fma.f32(float %fsub, float %y.fneg, float %z)
104  ret float %fma
105}
106
107define float @fma_unary_fneg_const_unary_fneg_y(float %y, float %z) {
108; CHECK-LABEL: @fma_unary_fneg_const_unary_fneg_y(
109; CHECK-NEXT:    [[FMA:%.*]] = call float @llvm.fma.f32(float [[Y:%.*]], float bitcast (i32 ptrtoint (ptr @external to i32) to float), float [[Z:%.*]])
110; CHECK-NEXT:    ret float [[FMA]]
111;
112  %y.fneg = fneg float %y
113  %external.fneg = fneg float bitcast (i32 ptrtoint (ptr @external to i32) to float)
114  %fma = call float @llvm.fma.f32(float %external.fneg, float %y.fneg, float %z)
115  ret float %fma
116}
117
118define float @fma_fneg_x_fneg_const(float %x, float %z) {
119; CHECK-LABEL: @fma_fneg_x_fneg_const(
120; CHECK-NEXT:    [[FMA:%.*]] = call float @llvm.fma.f32(float [[X:%.*]], float bitcast (i32 ptrtoint (ptr @external to i32) to float), float [[Z:%.*]])
121; CHECK-NEXT:    ret float [[FMA]]
122;
123  %x.fneg = fsub float -0.0, %x
124  %fsub = fsub float -0.0, bitcast (i32 ptrtoint (ptr @external to i32) to float)
125  %fma = call float @llvm.fma.f32(float %x.fneg, float %fsub, float %z)
126  ret float %fma
127}
128
129define float @fma_unary_fneg_x_unary_fneg_const(float %x, float %z) {
130; CHECK-LABEL: @fma_unary_fneg_x_unary_fneg_const(
131; CHECK-NEXT:    [[FMA:%.*]] = call float @llvm.fma.f32(float [[X:%.*]], float bitcast (i32 ptrtoint (ptr @external to i32) to float), float [[Z:%.*]])
132; CHECK-NEXT:    ret float [[FMA]]
133;
134  %x.fneg = fneg float %x
135  %external.fneg = fneg float bitcast (i32 ptrtoint (ptr @external to i32) to float)
136  %fma = call float @llvm.fma.f32(float %x.fneg, float %external.fneg, float %z)
137  ret float %fma
138}
139
140define float @fma_fabs_x_fabs_y(float %x, float %y, float %z) {
141; CHECK-LABEL: @fma_fabs_x_fabs_y(
142; CHECK-NEXT:    [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
143; CHECK-NEXT:    [[Y_FABS:%.*]] = call float @llvm.fabs.f32(float [[Y:%.*]])
144; CHECK-NEXT:    [[FMA:%.*]] = call float @llvm.fma.f32(float [[X_FABS]], float [[Y_FABS]], float [[Z:%.*]])
145; CHECK-NEXT:    ret float [[FMA]]
146;
147  %x.fabs = call float @llvm.fabs.f32(float %x)
148  %y.fabs = call float @llvm.fabs.f32(float %y)
149  %fma = call float @llvm.fma.f32(float %x.fabs, float %y.fabs, float %z)
150  ret float %fma
151}
152
153define float @fma_fabs_x_fabs_x(float %x, float %z) {
154; CHECK-LABEL: @fma_fabs_x_fabs_x(
155; CHECK-NEXT:    [[FMA:%.*]] = call float @llvm.fma.f32(float [[X:%.*]], float [[X]], float [[Z:%.*]])
156; CHECK-NEXT:    ret float [[FMA]]
157;
158  %x.fabs = call float @llvm.fabs.f32(float %x)
159  %fma = call float @llvm.fma.f32(float %x.fabs, float %x.fabs, float %z)
160  ret float %fma
161}
162
163define float @fma_fabs_x_fabs_x_fast(float %x, float %z) {
164; CHECK-LABEL: @fma_fabs_x_fabs_x_fast(
165; CHECK-NEXT:    [[FMA:%.*]] = call fast float @llvm.fma.f32(float [[X:%.*]], float [[X]], float [[Z:%.*]])
166; CHECK-NEXT:    ret float [[FMA]]
167;
168  %x.fabs = call float @llvm.fabs.f32(float %x)
169  %fma = call fast float @llvm.fma.f32(float %x.fabs, float %x.fabs, float %z)
170  ret float %fma
171}
172
173define float @fmuladd_fneg_x_fneg_y(float %x, float %y, float %z) {
174; CHECK-LABEL: @fmuladd_fneg_x_fneg_y(
175; CHECK-NEXT:    [[FMULADD:%.*]] = call float @llvm.fmuladd.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]])
176; CHECK-NEXT:    ret float [[FMULADD]]
177;
178  %x.fneg = fsub float -0.0, %x
179  %y.fneg = fsub float -0.0, %y
180  %fmuladd = call float @llvm.fmuladd.f32(float %x.fneg, float %y.fneg, float %z)
181  ret float %fmuladd
182}
183
184define float @fmuladd_unary_fneg_x_unary_fneg_y(float %x, float %y, float %z) {
185; CHECK-LABEL: @fmuladd_unary_fneg_x_unary_fneg_y(
186; CHECK-NEXT:    [[FMULADD:%.*]] = call float @llvm.fmuladd.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]])
187; CHECK-NEXT:    ret float [[FMULADD]]
188;
189  %x.fneg = fneg float %x
190  %y.fneg = fneg float %y
191  %fmuladd = call float @llvm.fmuladd.f32(float %x.fneg, float %y.fneg, float %z)
192  ret float %fmuladd
193}
194
195define float @fmuladd_fneg_x_fneg_y_fast(float %x, float %y, float %z) {
196; CHECK-LABEL: @fmuladd_fneg_x_fneg_y_fast(
197; CHECK-NEXT:    [[FMULADD:%.*]] = call fast float @llvm.fmuladd.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]])
198; CHECK-NEXT:    ret float [[FMULADD]]
199;
200  %x.fneg = fsub float -0.0, %x
201  %y.fneg = fsub float -0.0, %y
202  %fmuladd = call fast float @llvm.fmuladd.f32(float %x.fneg, float %y.fneg, float %z)
203  ret float %fmuladd
204}
205
206define float @fmuladd_unfold(float %x, float %y, float %z) {
207; CHECK-LABEL: @fmuladd_unfold(
208; CHECK-NEXT:    [[FMULADD:%.*]] = call reassoc contract float @llvm.fmuladd.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]])
209; CHECK-NEXT:    ret float [[FMULADD]]
210;
211  %fmuladd = call reassoc contract float @llvm.fmuladd.f32(float %x, float %y, float %z)
212  ret float %fmuladd
213}
214
215define <8 x half> @fmuladd_unfold_vec(<8 x half> %x, <8 x half> %y, <8 x half> %z) {
216; CHECK-LABEL: @fmuladd_unfold_vec(
217; CHECK-NEXT:    [[FMULADD:%.*]] = call reassoc contract <8 x half> @llvm.fmuladd.v8f16(<8 x half> [[X:%.*]], <8 x half> [[Y:%.*]], <8 x half> [[Z:%.*]])
218; CHECK-NEXT:    ret <8 x half> [[FMULADD]]
219;
220  %fmuladd = call reassoc contract <8 x half> @llvm.fmuladd.v8f16(<8 x half> %x, <8 x half> %y, <8 x half> %z)
221  ret <8 x half> %fmuladd
222}
223
224define float @fmuladd_unary_fneg_x_unary_fneg_y_fast(float %x, float %y, float %z) {
225; CHECK-LABEL: @fmuladd_unary_fneg_x_unary_fneg_y_fast(
226; CHECK-NEXT:    [[FMULADD:%.*]] = call fast float @llvm.fmuladd.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]])
227; CHECK-NEXT:    ret float [[FMULADD]]
228;
229  %x.fneg = fneg float %x
230  %y.fneg = fneg float %y
231  %fmuladd = call fast float @llvm.fmuladd.f32(float %x.fneg, float %y.fneg, float %z)
232  ret float %fmuladd
233}
234
235define float @fmuladd_fneg_const_fneg_y(float %y, float %z) {
236; CHECK-LABEL: @fmuladd_fneg_const_fneg_y(
237; CHECK-NEXT:    [[FMULADD:%.*]] = call float @llvm.fmuladd.f32(float [[Y:%.*]], float bitcast (i32 ptrtoint (ptr @external to i32) to float), float [[Z:%.*]])
238; CHECK-NEXT:    ret float [[FMULADD]]
239;
240  %y.fneg = fsub float -0.0, %y
241  %fsub = fsub float -0.0, bitcast (i32 ptrtoint (ptr @external to i32) to float)
242  %fmuladd = call float @llvm.fmuladd.f32(float %fsub, float %y.fneg, float %z)
243  ret float %fmuladd
244}
245
246define float @fmuladd_unary_fneg_const_unary_fneg_y(float %y, float %z) {
247; CHECK-LABEL: @fmuladd_unary_fneg_const_unary_fneg_y(
248; CHECK-NEXT:    [[FMULADD:%.*]] = call float @llvm.fmuladd.f32(float [[Y:%.*]], float bitcast (i32 ptrtoint (ptr @external to i32) to float), float [[Z:%.*]])
249; CHECK-NEXT:    ret float [[FMULADD]]
250;
251  %y.fneg = fneg float %y
252  %external.fneg = fneg float bitcast (i32 ptrtoint (ptr @external to i32) to float)
253  %fmuladd = call float @llvm.fmuladd.f32(float %external.fneg, float %y.fneg, float %z)
254  ret float %fmuladd
255}
256
257define float @fmuladd_fneg_x_fneg_const(float %x, float %z) {
258; CHECK-LABEL: @fmuladd_fneg_x_fneg_const(
259; CHECK-NEXT:    [[FMULADD:%.*]] = call float @llvm.fmuladd.f32(float [[X:%.*]], float bitcast (i32 ptrtoint (ptr @external to i32) to float), float [[Z:%.*]])
260; CHECK-NEXT:    ret float [[FMULADD]]
261;
262  %x.fneg = fsub float -0.0, %x
263  %fsub = fsub float -0.0, bitcast (i32 ptrtoint (ptr @external to i32) to float)
264  %fmuladd = call float @llvm.fmuladd.f32(float %x.fneg, float %fsub, float %z)
265  ret float %fmuladd
266}
267
268define float @fmuladd_unary_fneg_x_unary_fneg_const(float %x, float %z) {
269; CHECK-LABEL: @fmuladd_unary_fneg_x_unary_fneg_const(
270; CHECK-NEXT:    [[FMULADD:%.*]] = call float @llvm.fmuladd.f32(float [[X:%.*]], float bitcast (i32 ptrtoint (ptr @external to i32) to float), float [[Z:%.*]])
271; CHECK-NEXT:    ret float [[FMULADD]]
272;
273  %x.fneg = fneg float %x
274  %external.fneg = fneg float bitcast (i32 ptrtoint (ptr @external to i32) to float)
275  %fmuladd = call float @llvm.fmuladd.f32(float %x.fneg, float %external.fneg, float %z)
276  ret float %fmuladd
277}
278
279define float @fmuladd_fabs_x_fabs_y(float %x, float %y, float %z) {
280; CHECK-LABEL: @fmuladd_fabs_x_fabs_y(
281; CHECK-NEXT:    [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
282; CHECK-NEXT:    [[Y_FABS:%.*]] = call float @llvm.fabs.f32(float [[Y:%.*]])
283; CHECK-NEXT:    [[FMULADD:%.*]] = call float @llvm.fmuladd.f32(float [[X_FABS]], float [[Y_FABS]], float [[Z:%.*]])
284; CHECK-NEXT:    ret float [[FMULADD]]
285;
286  %x.fabs = call float @llvm.fabs.f32(float %x)
287  %y.fabs = call float @llvm.fabs.f32(float %y)
288  %fmuladd = call float @llvm.fmuladd.f32(float %x.fabs, float %y.fabs, float %z)
289  ret float %fmuladd
290}
291
292define float @fmuladd_fabs_x_fabs_x(float %x, float %z) {
293; CHECK-LABEL: @fmuladd_fabs_x_fabs_x(
294; CHECK-NEXT:    [[FMULADD:%.*]] = call float @llvm.fmuladd.f32(float [[X:%.*]], float [[X]], float [[Z:%.*]])
295; CHECK-NEXT:    ret float [[FMULADD]]
296;
297  %x.fabs = call float @llvm.fabs.f32(float %x)
298  %fmuladd = call float @llvm.fmuladd.f32(float %x.fabs, float %x.fabs, float %z)
299  ret float %fmuladd
300}
301
302define float @fmuladd_fabs_x_fabs_x_fast(float %x, float %z) {
303; CHECK-LABEL: @fmuladd_fabs_x_fabs_x_fast(
304; CHECK-NEXT:    [[FMULADD:%.*]] = call fast float @llvm.fmuladd.f32(float [[X:%.*]], float [[X]], float [[Z:%.*]])
305; CHECK-NEXT:    ret float [[FMULADD]]
306;
307  %x.fabs = call float @llvm.fabs.f32(float %x)
308  %fmuladd = call fast float @llvm.fmuladd.f32(float %x.fabs, float %x.fabs, float %z)
309  ret float %fmuladd
310}
311
312define float @fma_k_y_z(float %y, float %z) {
313; CHECK-LABEL: @fma_k_y_z(
314; CHECK-NEXT:    [[FMA:%.*]] = call float @llvm.fma.f32(float [[Y:%.*]], float 4.000000e+00, float [[Z:%.*]])
315; CHECK-NEXT:    ret float [[FMA]]
316;
317  %fma = call float @llvm.fma.f32(float 4.0, float %y, float %z)
318  ret float %fma
319}
320
321define float @fma_k_y_z_fast(float %y, float %z) {
322; CHECK-LABEL: @fma_k_y_z_fast(
323; CHECK-NEXT:    [[FMA:%.*]] = call fast float @llvm.fma.f32(float [[Y:%.*]], float 4.000000e+00, float [[Z:%.*]])
324; CHECK-NEXT:    ret float [[FMA]]
325;
326  %fma = call fast float @llvm.fma.f32(float 4.0, float %y, float %z)
327  ret float %fma
328}
329
330; Treat fmuladd like an fma intrinsic
331define float @fmuladd_k_y_z_fast(float %y, float %z) {
332; CHECK-LABEL: @fmuladd_k_y_z_fast(
333; CHECK-NEXT:    [[FMULADD:%.*]] = call fast float @llvm.fmuladd.f32(float [[Y:%.*]], float 4.000000e+00, float [[Z:%.*]])
334; CHECK-NEXT:    ret float [[FMULADD]]
335;
336  %fmuladd = call fast float @llvm.fmuladd.f32(float 4.0, float %y, float %z)
337  ret float %fmuladd
338}
339
340define float @fma_1_y_z(float %y, float %z) {
341; CHECK-LABEL: @fma_1_y_z(
342; CHECK-NEXT:    [[FMA:%.*]] = fadd float [[Y:%.*]], [[Z:%.*]]
343; CHECK-NEXT:    ret float [[FMA]]
344;
345  %fma = call float @llvm.fma.f32(float 1.0, float %y, float %z)
346  ret float %fma
347}
348
349define float @fma_x_1_z(float %x, float %z) {
350; CHECK-LABEL: @fma_x_1_z(
351; CHECK-NEXT:    [[FMA:%.*]] = fadd float [[X:%.*]], [[Z:%.*]]
352; CHECK-NEXT:    ret float [[FMA]]
353;
354  %fma = call float @llvm.fma.f32(float %x, float 1.0, float %z)
355  ret float %fma
356}
357
358define <2 x float> @fma_x_1_z_v2f32(<2 x float> %x, <2 x float> %z) {
359; CHECK-LABEL: @fma_x_1_z_v2f32(
360; CHECK-NEXT:    [[FMA:%.*]] = fadd <2 x float> [[X:%.*]], [[Z:%.*]]
361; CHECK-NEXT:    ret <2 x float> [[FMA]]
362;
363  %fma = call <2 x float> @llvm.fma.v2f32(<2 x float> %x, <2 x float> <float 1.0, float 1.0>, <2 x float> %z)
364  ret <2 x float> %fma
365}
366
367define <2 x float> @fma_x_1_2_z_v2f32(<2 x float> %x, <2 x float> %z) {
368; CHECK-LABEL: @fma_x_1_2_z_v2f32(
369; CHECK-NEXT:    [[FMA:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[X:%.*]], <2 x float> <float 1.000000e+00, float 2.000000e+00>, <2 x float> [[Z:%.*]])
370; CHECK-NEXT:    ret <2 x float> [[FMA]]
371;
372  %fma = call <2 x float> @llvm.fma.v2f32(<2 x float> %x, <2 x float> <float 1.0, float 2.0>, <2 x float> %z)
373  ret <2 x float> %fma
374}
375
376define float @fma_x_1_z_fast(float %x, float %z) {
377; CHECK-LABEL: @fma_x_1_z_fast(
378; CHECK-NEXT:    [[FMA:%.*]] = fadd fast float [[X:%.*]], [[Z:%.*]]
379; CHECK-NEXT:    ret float [[FMA]]
380;
381  %fma = call fast float @llvm.fma.f32(float %x, float 1.0, float %z)
382  ret float %fma
383}
384
385define float @fma_1_1_z(float %z) {
386; CHECK-LABEL: @fma_1_1_z(
387; CHECK-NEXT:    [[FMA:%.*]] = fadd float [[Z:%.*]], 1.000000e+00
388; CHECK-NEXT:    ret float [[FMA]]
389;
390  %fma = call float @llvm.fma.f32(float 1.0, float 1.0, float %z)
391  ret float %fma
392}
393
394define float @fma_x_y_0(float %x, float %y) {
395; CHECK-LABEL: @fma_x_y_0(
396; CHECK-NEXT:    [[FMA:%.*]] = call float @llvm.fma.f32(float [[X:%.*]], float [[Y:%.*]], float 0.000000e+00)
397; CHECK-NEXT:    ret float [[FMA]]
398;
399  %fma = call float @llvm.fma.f32(float %x, float %y, float 0.0)
400  ret float %fma
401}
402
403define float @fma_x_y_0_nsz(float %x, float %y) {
404; CHECK-LABEL: @fma_x_y_0_nsz(
405; CHECK-NEXT:    [[FMA:%.*]] = fmul nsz float [[X:%.*]], [[Y:%.*]]
406; CHECK-NEXT:    ret float [[FMA]]
407;
408  %fma = call nsz float @llvm.fma.f32(float %x, float %y, float 0.0)
409  ret float %fma
410}
411
412define <8 x half> @fma_x_y_0_v(<8 x half> %x, <8 x half> %y) {
413; CHECK-LABEL: @fma_x_y_0_v(
414; CHECK-NEXT:    [[FMA:%.*]] = call <8 x half> @llvm.fma.v8f16(<8 x half> [[X:%.*]], <8 x half> [[Y:%.*]], <8 x half> zeroinitializer)
415; CHECK-NEXT:    ret <8 x half> [[FMA]]
416;
417  %fma = call <8 x half> @llvm.fma.v8f16(<8 x half> %x, <8 x half> %y, <8 x half> zeroinitializer)
418  ret <8 x half> %fma
419}
420
421define <8 x half> @fma_x_y_0_nsz_v(<8 x half> %x, <8 x half> %y) {
422; CHECK-LABEL: @fma_x_y_0_nsz_v(
423; CHECK-NEXT:    [[FMA:%.*]] = fmul nsz <8 x half> [[X:%.*]], [[Y:%.*]]
424; CHECK-NEXT:    ret <8 x half> [[FMA]]
425;
426  %fma = call nsz <8 x half> @llvm.fma.v8f16(<8 x half> %x, <8 x half> %y, <8 x half> zeroinitializer)
427  ret <8 x half> %fma
428}
429
430define float @fmuladd_x_y_0(float %x, float %y) {
431; CHECK-LABEL: @fmuladd_x_y_0(
432; CHECK-NEXT:    [[FMA:%.*]] = call float @llvm.fmuladd.f32(float [[X:%.*]], float [[Y:%.*]], float 0.000000e+00)
433; CHECK-NEXT:    ret float [[FMA]]
434;
435  %fma = call float @llvm.fmuladd.f32(float %x, float %y, float 0.0)
436  ret float %fma
437}
438
439define float @fmuladd_x_y_0_nsz(float %x, float %y) {
440; CHECK-LABEL: @fmuladd_x_y_0_nsz(
441; CHECK-NEXT:    [[FMA:%.*]] = fmul nsz float [[X:%.*]], [[Y:%.*]]
442; CHECK-NEXT:    ret float [[FMA]]
443;
444  %fma = call nsz float @llvm.fmuladd.f32(float %x, float %y, float 0.0)
445  ret float %fma
446}
447
448define float @fma_x_y_m0(float %x, float %y) {
449; CHECK-LABEL: @fma_x_y_m0(
450; CHECK-NEXT:    [[FMA:%.*]] = fmul float [[X:%.*]], [[Y:%.*]]
451; CHECK-NEXT:    ret float [[FMA]]
452;
453  %fma = call float @llvm.fma.f32(float %x, float %y, float -0.0)
454  ret float %fma
455}
456
457define <8 x half> @fma_x_y_m0_v(<8 x half> %x, <8 x half> %y) {
458; CHECK-LABEL: @fma_x_y_m0_v(
459; CHECK-NEXT:    [[FMA:%.*]] = fmul <8 x half> [[X:%.*]], [[Y:%.*]]
460; CHECK-NEXT:    ret <8 x half> [[FMA]]
461;
462  %fma = call <8 x half> @llvm.fma.v8f16(<8 x half> %x, <8 x half> %y, <8 x half> <half -0.0, half -0.0, half -0.0, half -0.0, half -0.0, half -0.0, half -0.0, half -0.0>)
463  ret <8 x half> %fma
464}
465
466define float @fmuladd_x_y_m0(float %x, float %y) {
467; CHECK-LABEL: @fmuladd_x_y_m0(
468; CHECK-NEXT:    [[FMA:%.*]] = fmul float [[X:%.*]], [[Y:%.*]]
469; CHECK-NEXT:    ret float [[FMA]]
470;
471  %fma = call float @llvm.fmuladd.f32(float %x, float %y, float -0.0)
472  ret float %fma
473}
474
475define float @fmuladd_x_1_z_fast(float %x, float %z) {
476; CHECK-LABEL: @fmuladd_x_1_z_fast(
477; CHECK-NEXT:    [[FMULADD:%.*]] = fadd fast float [[X:%.*]], [[Z:%.*]]
478; CHECK-NEXT:    ret float [[FMULADD]]
479;
480  %fmuladd = call fast float @llvm.fmuladd.f32(float %x, float 1.0, float %z)
481  ret float %fmuladd
482}
483
484define <2 x double> @fmuladd_a_0_b(<2 x double> %a, <2 x double> %b) {
485; CHECK-LABEL: @fmuladd_a_0_b(
486; CHECK-NEXT:    ret <2 x double> [[B:%.*]]
487;
488  %res = call nnan nsz <2 x double> @llvm.fmuladd.v2f64(<2 x double> %a, <2 x double> zeroinitializer, <2 x double> %b)
489  ret <2 x double> %res
490}
491
492define <2 x double> @fmuladd_0_a_b(<2 x double> %a, <2 x double> %b) {
493; CHECK-LABEL: @fmuladd_0_a_b(
494; CHECK-NEXT:    ret <2 x double> [[B:%.*]]
495;
496  %res = call nnan nsz <2 x double> @llvm.fmuladd.v2f64(<2 x double> zeroinitializer, <2 x double> %a, <2 x double> %b)
497  ret <2 x double> %res
498}
499
500define <2 x double> @fmuladd_a_0_b_missing_flags(<2 x double> %a, <2 x double> %b) {
501; CHECK-LABEL: @fmuladd_a_0_b_missing_flags(
502; CHECK-NEXT:    [[RES:%.*]] = call nnan <2 x double> @llvm.fmuladd.v2f64(<2 x double> [[A:%.*]], <2 x double> zeroinitializer, <2 x double> [[B:%.*]])
503; CHECK-NEXT:    ret <2 x double> [[RES]]
504;
505  %res = call nnan <2 x double> @llvm.fmuladd.v2f64(<2 x double> %a, <2 x double> zeroinitializer, <2 x double> %b)
506  ret <2 x double> %res
507}
508
509define <2 x double> @fma_a_0_b(<2 x double> %a, <2 x double> %b) {
510; CHECK-LABEL: @fma_a_0_b(
511; CHECK-NEXT:    ret <2 x double> [[B:%.*]]
512;
513  %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> %a, <2 x double> zeroinitializer, <2 x double> %b)
514  ret <2 x double> %res
515}
516
517define <2 x double> @fma_0_a_b(<2 x double> %a, <2 x double> %b) {
518; CHECK-LABEL: @fma_0_a_b(
519; CHECK-NEXT:    ret <2 x double> [[B:%.*]]
520;
521  %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> zeroinitializer, <2 x double> %a, <2 x double> %b)
522  ret <2 x double> %res
523}
524
525define <2 x double> @fma_0_a_b_missing_flags(<2 x double> %a, <2 x double> %b) {
526; CHECK-LABEL: @fma_0_a_b_missing_flags(
527; CHECK-NEXT:    [[RES:%.*]] = call nsz <2 x double> @llvm.fma.v2f64(<2 x double> [[A:%.*]], <2 x double> zeroinitializer, <2 x double> [[B:%.*]])
528; CHECK-NEXT:    ret <2 x double> [[RES]]
529;
530  %res = call nsz <2 x double> @llvm.fma.v2f64(<2 x double> zeroinitializer, <2 x double> %a, <2 x double> %b)
531  ret <2 x double> %res
532}
533
534define <2 x double> @fma_sqrt(<2 x double> %a, <2 x double> %b) {
535; CHECK-LABEL: @fma_sqrt(
536; CHECK-NEXT:    [[RES:%.*]] = fadd fast <2 x double> [[A:%.*]], [[B:%.*]]
537; CHECK-NEXT:    ret <2 x double> [[RES]]
538;
539  %sqrt = call fast <2 x double> @llvm.sqrt.v2f64(<2 x double> %a)
540  %res = call fast <2 x double> @llvm.fma.v2f64(<2 x double> %sqrt, <2 x double> %sqrt, <2 x double> %b)
541  ret <2 x double> %res
542}
543
544; We do not fold constant multiplies in FMAs, as they could require rounding, unless either constant is 0.0 or 1.0.
545define <2 x double> @fma_const_fmul(<2 x double> %b) {
546; CHECK-LABEL: @fma_const_fmul(
547; CHECK-NEXT:    [[RES:%.*]] = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> <double 0x4131233302898702, double 0x40C387800000D6C0>, <2 x double> <double 1.291820e-08, double 9.123000e-06>, <2 x double> [[B:%.*]])
548; CHECK-NEXT:    ret <2 x double> [[RES]]
549;
550  %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> <double 1123123.0099110012314, double 9999.0000001>, <2 x double> <double 0.0000000129182, double 0.000009123>, <2 x double> %b)
551  ret <2 x double> %res
552}
553
554define <2 x double> @fma_const_fmul_zero(<2 x double> %b) {
555; CHECK-LABEL: @fma_const_fmul_zero(
556; CHECK-NEXT:    ret <2 x double> [[B:%.*]]
557;
558  %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> <double 0.0, double 0.0>, <2 x double> <double 1123123.0099110012314, double 9999.0000001>, <2 x double> %b)
559  ret <2 x double> %res
560}
561
562define <2 x double> @fma_const_fmul_zero2(<2 x double> %b) {
563; CHECK-LABEL: @fma_const_fmul_zero2(
564; CHECK-NEXT:    ret <2 x double> [[B:%.*]]
565;
566  %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> <double 1123123.0099110012314, double 9999.0000001>, <2 x double> <double 0.0, double 0.0>, <2 x double> %b)
567  ret <2 x double> %res
568}
569
570define <2 x double> @fma_const_fmul_one(<2 x double> %b) {
571; CHECK-LABEL: @fma_const_fmul_one(
572; CHECK-NEXT:    [[RES:%.*]] = fadd nnan nsz <2 x double> [[B:%.*]], <double 0x4131233302898702, double 0x40C387800000D6C0>
573; CHECK-NEXT:    ret <2 x double> [[RES]]
574;
575  %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> <double 1.0, double 1.0>, <2 x double> <double 1123123.0099110012314, double 9999.0000001>, <2 x double> %b)
576  ret <2 x double> %res
577}
578
579define <2 x double> @fma_const_fmul_one2(<2 x double> %b) {
580; CHECK-LABEL: @fma_const_fmul_one2(
581; CHECK-NEXT:    [[RES:%.*]] = fadd nnan nsz <2 x double> [[B:%.*]], <double 0x4131233302898702, double 0x40C387800000D6C0>
582; CHECK-NEXT:    ret <2 x double> [[RES]]
583;
584  %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> <double 1123123.0099110012314, double 9999.0000001>, <2 x double> <double 1.0, double 1.0>, <2 x double> %b)
585  ret <2 x double> %res
586}
587
588define <2 x double> @fma_nan_and_const_0(<2 x double> %b) {
589; CHECK-LABEL: @fma_nan_and_const_0(
590; CHECK-NEXT:    ret <2 x double> splat (double 0x7FF8000000000000)
591;
592  %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>, <2 x double> <double 0.0000000129182, double 0.000009123>, <2 x double> %b)
593  ret <2 x double> %res
594}
595
596define <2 x double> @fma_nan_and_const_1(<2 x double> %b) {
597; CHECK-LABEL: @fma_nan_and_const_1(
598; CHECK-NEXT:    ret <2 x double> splat (double 0x7FF8000000000000)
599;
600  %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> <double 0.0000000129182, double 0.000009123>, <2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>, <2 x double> %b)
601  ret <2 x double> %res
602}
603
604define <2 x double> @fma_nan_and_const_2(<2 x double> %b) {
605; CHECK-LABEL: @fma_nan_and_const_2(
606; CHECK-NEXT:    ret <2 x double> splat (double 0x7FF8000000000000)
607;
608  %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> <double 0.0000000129182, double 0.000009123>, <2 x double> %b, <2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>)
609  ret <2 x double> %res
610}
611
612define <2 x double> @fma_undef_0(<2 x double> %b, <2 x double> %c) {
613; CHECK-LABEL: @fma_undef_0(
614; CHECK-NEXT:    ret <2 x double> splat (double 0x7FF8000000000000)
615;
616  %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> <double undef, double undef>, <2 x double> %b, <2 x double> %c)
617  ret <2 x double> %res
618}
619
620define <2 x double> @fma_undef_1(<2 x double> %b, <2 x double> %c) {
621; CHECK-LABEL: @fma_undef_1(
622; CHECK-NEXT:    ret <2 x double> splat (double 0x7FF8000000000000)
623;
624  %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> %b, <2 x double> <double undef, double undef>, <2 x double> %c)
625  ret <2 x double> %res
626}
627
628define <2 x double> @fma_undef_2(<2 x double> %b, <2 x double> %c) {
629; CHECK-LABEL: @fma_undef_2(
630; CHECK-NEXT:    ret <2 x double> splat (double 0x7FF8000000000000)
631;
632  %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> %b, <2 x double> %c, <2 x double> <double undef, double undef>)
633  ret <2 x double> %res
634}
635
636define <2 x double> @fma_partial_undef_0(<2 x double> %b, <2 x double> %c) {
637; CHECK-LABEL: @fma_partial_undef_0(
638; CHECK-NEXT:    [[RES:%.*]] = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> [[B:%.*]], <2 x double> <double undef, double 0x4068E00A137F38C5>, <2 x double> [[C:%.*]])
639; CHECK-NEXT:    ret <2 x double> [[RES]]
640;
641  %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> <double undef, double 199.00123>, <2 x double> %b, <2 x double> %c)
642  ret <2 x double> %res
643}
644
645define <2 x double> @fma_partial_undef_1(<2 x double> %b, <2 x double> %c) {
646; CHECK-LABEL: @fma_partial_undef_1(
647; CHECK-NEXT:    [[RES:%.*]] = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> [[B:%.*]], <2 x double> <double 0x4068E00A137F38C5, double undef>, <2 x double> [[C:%.*]])
648; CHECK-NEXT:    ret <2 x double> [[RES]]
649;
650  %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> %b, <2 x double> <double 199.00123, double undef>, <2 x double> %c)
651  ret <2 x double> %res
652}
653
654define <2 x double> @fma_partial_undef_2(<2 x double> %b, <2 x double> %c) {
655; CHECK-LABEL: @fma_partial_undef_2(
656; CHECK-NEXT:    [[RES:%.*]] = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> [[B:%.*]], <2 x double> [[C:%.*]], <2 x double> <double 0x4068E00A137F38C5, double undef>)
657; CHECK-NEXT:    ret <2 x double> [[RES]]
658;
659  %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> %b, <2 x double> %c, <2 x double> <double 199.00123, double undef>)
660  ret <2 x double> %res
661}
662
663
664define <2 x double> @fma_nan_0(<2 x double> %b, <2 x double> %c) {
665; CHECK-LABEL: @fma_nan_0(
666; CHECK-NEXT:    ret <2 x double> splat (double 0x7FF8000000000000)
667;
668  %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>, <2 x double> %b, <2 x double> %c)
669  ret <2 x double> %res
670}
671define <2 x double> @fma_nan_1(<2 x double> %b, <2 x double> %c) {
672; CHECK-LABEL: @fma_nan_1(
673; CHECK-NEXT:    ret <2 x double> splat (double 0x7FF8000000000000)
674;
675  %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> %b, <2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>, <2 x double> %c)
676  ret <2 x double> %res
677}
678
679define <2 x double> @fma_nan_2(<2 x double> %b, <2 x double> %c) {
680; CHECK-LABEL: @fma_nan_2(
681; CHECK-NEXT:    ret <2 x double> splat (double 0x7FF8000000000000)
682;
683  %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> %b, <2 x double> %c, <2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>)
684  ret <2 x double> %res
685}
686
687define <2 x double> @fmuladd_const_fmul(<2 x double> %b) {
688; CHECK-LABEL: @fmuladd_const_fmul(
689; CHECK-NEXT:    [[RES:%.*]] = fadd nnan nsz <2 x double> [[B:%.*]], <double 0x3F8DB6C076AD949B, double 0x3FB75A405B6E6D69>
690; CHECK-NEXT:    ret <2 x double> [[RES]]
691;
692  %res = call nnan nsz <2 x double> @llvm.fmuladd.v2f64(<2 x double> <double 1123123.0099110012314, double 9999.0000001>, <2 x double> <double 0.0000000129182, double 0.000009123>, <2 x double> %b)
693  ret <2 x double> %res
694}
695
696define <2 x double> @fmuladd_nan_and_const_0(<2 x double> %b) {
697; CHECK-LABEL: @fmuladd_nan_and_const_0(
698; CHECK-NEXT:    ret <2 x double> splat (double 0x7FF8000000000000)
699;
700  %res = call nnan nsz <2 x double> @llvm.fmuladd.v2f64(<2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>, <2 x double> <double 0.0000000129182, double 0.000009123>, <2 x double> %b)
701  ret <2 x double> %res
702}
703
704define <2 x double> @fmuladd_nan_and_const_1(<2 x double> %b) {
705; CHECK-LABEL: @fmuladd_nan_and_const_1(
706; CHECK-NEXT:    ret <2 x double> splat (double 0x7FF8000000000000)
707;
708  %res = call nnan nsz <2 x double> @llvm.fmuladd.v2f64(<2 x double> <double 0.0000000129182, double 0.000009123>, <2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>, <2 x double> %b)
709  ret <2 x double> %res
710}
711
712define <2 x double> @fmuladd_nan_and_const_2(<2 x double> %b) {
713; CHECK-LABEL: @fmuladd_nan_and_const_2(
714; CHECK-NEXT:    ret <2 x double> splat (double 0x7FF8000000000000)
715;
716  %res = call nnan nsz <2 x double> @llvm.fmuladd.v2f64(<2 x double> <double 0.0000000129182, double 0.000009123>, <2 x double> %b, <2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>)
717  ret <2 x double> %res
718}
719
720define <2 x double> @fmuladd_nan_0(<2 x double> %b, <2 x double> %c) {
721; CHECK-LABEL: @fmuladd_nan_0(
722; CHECK-NEXT:    ret <2 x double> splat (double 0x7FF8000000000000)
723;
724  %res = call nnan nsz <2 x double> @llvm.fmuladd.v2f64(<2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>, <2 x double> %b, <2 x double> %c)
725  ret <2 x double> %res
726}
727
728define <2 x double> @fmuladd_nan_1(<2 x double> %b, <2 x double> %c) {
729; CHECK-LABEL: @fmuladd_nan_1(
730; CHECK-NEXT:    ret <2 x double> splat (double 0x7FF8000000000000)
731;
732  %res = call nnan nsz <2 x double> @llvm.fmuladd.v2f64(<2 x double> %b, <2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>, <2 x double> %c)
733  ret <2 x double> %res
734}
735
736define <2 x double> @fmuladd_undef_0(<2 x double> %b, <2 x double> %c) {
737; CHECK-LABEL: @fmuladd_undef_0(
738; CHECK-NEXT:    ret <2 x double> splat (double 0x7FF8000000000000)
739;
740  %res = call nnan nsz <2 x double> @llvm.fmuladd.v2f64(<2 x double> <double undef, double undef>, <2 x double> %b, <2 x double> %c)
741  ret <2 x double> %res
742}
743
744define <2 x double> @fmuladd_undef_1(<2 x double> %b, <2 x double> %c) {
745; CHECK-LABEL: @fmuladd_undef_1(
746; CHECK-NEXT:    ret <2 x double> splat (double 0x7FF8000000000000)
747;
748  %res = call nnan nsz <2 x double> @llvm.fmuladd.v2f64(<2 x double> %b, <2 x double> <double undef, double undef>, <2 x double> %c)
749  ret <2 x double> %res
750}
751
752define <2 x double> @fmuladd_undef_2(<2 x double> %b, <2 x double> %c) {
753; CHECK-LABEL: @fmuladd_undef_2(
754; CHECK-NEXT:    ret <2 x double> splat (double 0x7FF8000000000000)
755;
756  %res = call nnan nsz <2 x double> @llvm.fmuladd.v2f64(<2 x double> %b, <2 x double> %c, <2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>)
757  ret <2 x double> %res
758}
759
760define <2 x float> @fma_unary_shuffle_ops(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
761; CHECK-LABEL: @fma_unary_shuffle_ops(
762; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]], <2 x float> [[Z:%.*]])
763; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> <i32 1, i32 0>
764; CHECK-NEXT:    ret <2 x float> [[R]]
765;
766  %a = shufflevector <2 x float> %x, <2 x float> poison, <2 x i32> <i32 1, i32 0>
767  %b = shufflevector <2 x float> %y, <2 x float> poison, <2 x i32> <i32 1, i32 0>
768  %c = shufflevector <2 x float> %z, <2 x float> poison, <2 x i32> <i32 1, i32 0>
769  %r = call <2 x float> @llvm.fma.v2f32(<2 x float> %a, <2 x float> %b, <2 x float> %c)
770  ret <2 x float> %r
771}
772
773define <3 x float> @fma_unary_shuffle_ops_widening(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
774; CHECK-LABEL: @fma_unary_shuffle_ops_widening(
775; CHECK-NEXT:    [[A:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> poison, <3 x i32> <i32 1, i32 0, i32 1>
776; CHECK-NEXT:    call void @use_vec3(<3 x float> [[A]])
777; CHECK-NEXT:    [[TMP1:%.*]] = call fast <2 x float> @llvm.fma.v2f32(<2 x float> [[X]], <2 x float> [[Y:%.*]], <2 x float> [[Z:%.*]])
778; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <3 x i32> <i32 1, i32 0, i32 1>
779; CHECK-NEXT:    ret <3 x float> [[R]]
780;
781  %a = shufflevector <2 x float> %x, <2 x float> poison, <3 x i32> <i32 1, i32 0, i32 1>
782  call void @use_vec3(<3 x float> %a)
783  %b = shufflevector <2 x float> %y, <2 x float> poison, <3 x i32> <i32 1, i32 0, i32 1>
784  %c = shufflevector <2 x float> %z, <2 x float> poison, <3 x i32> <i32 1, i32 0, i32 1>
785  %r = call fast <3 x float> @llvm.fma.v3f32(<3 x float> %a, <3 x float> %b, <3 x float> %c)
786  ret <3 x float> %r
787}
788
789define <2 x float> @fma_unary_shuffle_ops_narrowing(<3 x float> %x, <3 x float> %y, <3 x float> %z) {
790; CHECK-LABEL: @fma_unary_shuffle_ops_narrowing(
791; CHECK-NEXT:    [[B:%.*]] = shufflevector <3 x float> [[Y:%.*]], <3 x float> poison, <2 x i32> <i32 1, i32 0>
792; CHECK-NEXT:    call void @use_vec(<2 x float> [[B]])
793; CHECK-NEXT:    [[TMP1:%.*]] = call nnan nsz <3 x float> @llvm.fma.v3f32(<3 x float> [[X:%.*]], <3 x float> [[Y]], <3 x float> [[Z:%.*]])
794; CHECK-NEXT:    [[R:%.*]] = shufflevector <3 x float> [[TMP1]], <3 x float> poison, <2 x i32> <i32 1, i32 0>
795; CHECK-NEXT:    ret <2 x float> [[R]]
796;
797  %a = shufflevector <3 x float> %x, <3 x float> poison, <2 x i32> <i32 1, i32 0>
798  %b = shufflevector <3 x float> %y, <3 x float> poison, <2 x i32> <i32 1, i32 0>
799  call void @use_vec(<2 x float> %b)
800  %c = shufflevector <3 x float> %z, <3 x float> poison, <2 x i32> <i32 1, i32 0>
801  %r = call nnan nsz <2 x float> @llvm.fma.v2f32(<2 x float> %a, <2 x float> %b, <2 x float> %c)
802  ret <2 x float> %r
803}
804
805; negative test - must have 3 shuffles
806
807define <2 x float> @fma_unary_shuffle_ops_unshuffled(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
808; CHECK-LABEL: @fma_unary_shuffle_ops_unshuffled(
809; CHECK-NEXT:    [[A:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 0>
810; CHECK-NEXT:    [[B:%.*]] = shufflevector <2 x float> [[Y:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 0>
811; CHECK-NEXT:    [[R:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[A]], <2 x float> [[B]], <2 x float> [[Z:%.*]])
812; CHECK-NEXT:    ret <2 x float> [[R]]
813;
814  %a = shufflevector <2 x float> %x, <2 x float> poison, <2 x i32> <i32 1, i32 0>
815  %b = shufflevector <2 x float> %y, <2 x float> poison, <2 x i32> <i32 1, i32 0>
816  %r = call <2 x float> @llvm.fma.v2f32(<2 x float> %a, <2 x float> %b, <2 x float> %z)
817  ret <2 x float> %r
818}
819
820; negative test - must have identical masks
821
822define <2 x float> @fma_unary_shuffle_ops_wrong_mask(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
823; CHECK-LABEL: @fma_unary_shuffle_ops_wrong_mask(
824; CHECK-NEXT:    [[A:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 0>
825; CHECK-NEXT:    [[B:%.*]] = shufflevector <2 x float> [[Y:%.*]], <2 x float> poison, <2 x i32> zeroinitializer
826; CHECK-NEXT:    [[C:%.*]] = shufflevector <2 x float> [[Z:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 0>
827; CHECK-NEXT:    [[R:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[A]], <2 x float> [[B]], <2 x float> [[C]])
828; CHECK-NEXT:    ret <2 x float> [[R]]
829;
830  %a = shufflevector <2 x float> %x, <2 x float> poison, <2 x i32> <i32 1, i32 0>
831  %b = shufflevector <2 x float> %y, <2 x float> poison, <2 x i32> <i32 0, i32 0>
832  %c = shufflevector <2 x float> %z, <2 x float> poison, <2 x i32> <i32 1, i32 0>
833  %r = call <2 x float> @llvm.fma.v2f32(<2 x float> %a, <2 x float> %b, <2 x float> %c)
834  ret <2 x float> %r
835}
836
837; negative test - too many uses
838
839define <2 x float> @fma_unary_shuffle_ops_uses(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
840; CHECK-LABEL: @fma_unary_shuffle_ops_uses(
841; CHECK-NEXT:    [[A:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 0>
842; CHECK-NEXT:    call void @use_vec(<2 x float> [[A]])
843; CHECK-NEXT:    [[B:%.*]] = shufflevector <2 x float> [[Y:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 0>
844; CHECK-NEXT:    call void @use_vec(<2 x float> [[B]])
845; CHECK-NEXT:    [[C:%.*]] = shufflevector <2 x float> [[Z:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 0>
846; CHECK-NEXT:    call void @use_vec(<2 x float> [[C]])
847; CHECK-NEXT:    [[R:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[A]], <2 x float> [[B]], <2 x float> [[C]])
848; CHECK-NEXT:    ret <2 x float> [[R]]
849;
850  %a = shufflevector <2 x float> %x, <2 x float> poison, <2 x i32> <i32 1, i32 0>
851  call void @use_vec(<2 x float> %a)
852  %b = shufflevector <2 x float> %y, <2 x float> poison, <2 x i32> <i32 1, i32 0>
853  call void @use_vec(<2 x float> %b)
854  %c = shufflevector <2 x float> %z, <2 x float> poison, <2 x i32> <i32 1, i32 0>
855  call void @use_vec(<2 x float> %c)
856  %r = call <2 x float> @llvm.fma.v2f32(<2 x float> %a, <2 x float> %b, <2 x float> %c)
857  ret <2 x float> %r
858}
859
860define half @fma_negone(half %x, half %y) {
861; CHECK-LABEL: @fma_negone(
862; CHECK-NEXT:    [[SUB:%.*]] = fsub half [[Y:%.*]], [[X:%.*]]
863; CHECK-NEXT:    ret half [[SUB]]
864;
865  %sub = call half @llvm.fma.f16(half %x, half -1.0, half %y)
866  ret half %sub
867}
868
869define half @fmuladd_negone(half %x, half %y) {
870; CHECK-LABEL: @fmuladd_negone(
871; CHECK-NEXT:    [[SUB:%.*]] = fsub half [[Y:%.*]], [[X:%.*]]
872; CHECK-NEXT:    ret half [[SUB]]
873;
874  %sub = call half @llvm.fmuladd.f16(half %x, half -1.0, half %y)
875  ret half %sub
876}
877
878define half @fma_negone_fmf(half %x, half %y) {
879; CHECK-LABEL: @fma_negone_fmf(
880; CHECK-NEXT:    [[SUB:%.*]] = fsub nnan ninf nsz half [[Y:%.*]], [[X:%.*]]
881; CHECK-NEXT:    ret half [[SUB]]
882;
883  %sub = call nnan ninf nsz half @llvm.fma.f16(half %x, half -1.0, half %y)
884  ret half %sub
885}
886
887define half @fmuladd_negone_fmf(half %x, half %y) {
888; CHECK-LABEL: @fmuladd_negone_fmf(
889; CHECK-NEXT:    [[SUB:%.*]] = fsub nnan ninf nsz half [[Y:%.*]], [[X:%.*]]
890; CHECK-NEXT:    ret half [[SUB]]
891;
892  %sub = call nnan ninf nsz half @llvm.fmuladd.f16(half %x, half -1.0, half %y)
893  ret half %sub
894}
895
896define <2 x half> @fma_negone_vec(<2 x half> %x, <2 x half> %y) {
897; CHECK-LABEL: @fma_negone_vec(
898; CHECK-NEXT:    [[SUB:%.*]] = fsub <2 x half> [[Y:%.*]], [[X:%.*]]
899; CHECK-NEXT:    ret <2 x half> [[SUB]]
900;
901  %sub = call <2 x half> @llvm.fma.v2f16(<2 x half> %x, <2 x half> splat(half -1.0), <2 x half> %y)
902  ret <2 x half> %sub
903}
904
905define <2 x half> @fma_negone_vec_partial_undef(<2 x half> %x, <2 x half> %y) {
906; CHECK-LABEL: @fma_negone_vec_partial_undef(
907; CHECK-NEXT:    [[SUB:%.*]] = call <2 x half> @llvm.fma.v2f16(<2 x half> [[X:%.*]], <2 x half> <half undef, half 0xHBC00>, <2 x half> [[Y:%.*]])
908; CHECK-NEXT:    ret <2 x half> [[SUB]]
909;
910  %sub = call <2 x half> @llvm.fma.v2f16(<2 x half> %x, <2 x half> <half undef, half -1.0>, <2 x half> %y)
911  ret <2 x half> %sub
912}
913
914; negative tests
915
916define half @fma_non_negone(half %x, half %y) {
917; CHECK-LABEL: @fma_non_negone(
918; CHECK-NEXT:    [[SUB:%.*]] = call half @llvm.fma.f16(half [[X:%.*]], half 0xHBE00, half [[Y:%.*]])
919; CHECK-NEXT:    ret half [[SUB]]
920;
921  %sub = call half @llvm.fma.f16(half %x, half -1.5, half %y)
922  ret half %sub
923}
924