1; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx,+fma -fp-contract=fast | FileCheck %s --check-prefix=ALL --check-prefix=CHECK_FMA
2; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx,+fma4,+fma -fp-contract=fast | FileCheck %s --check-prefix=ALL --check-prefix=CHECK_FMA
3; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx,+fma4 -fp-contract=fast | FileCheck %s --check-prefix=ALL --check-prefix=CHECK_FMA4
4
5;
6; Patterns (+ fneg variants): add(mul(x,y),z), sub(mul(x,y),z)
7;
8
9define <4 x float> @test_x86_fmadd_ps(<4 x float> %a0, <4 x float> %a1, <4 x float> %a2) {
10; CHECK_FMA-LABEL: test_x86_fmadd_ps:
11; CHECK_FMA:       # BB#0:
12; CHECK_FMA-NEXT:    vfmadd213ps %xmm2, %xmm1, %xmm0
13; CHECK_FMA-NEXT:    retq
14;
15; CHECK_FMA4-LABEL: test_x86_fmadd_ps:
16; CHECK_FMA4:       # BB#0:
17; CHECK_FMA4-NEXT:    vfmaddps %xmm2, %xmm1, %xmm0, %xmm0
18; CHECK_FMA4-NEXT:    retq
19  %x = fmul <4 x float> %a0, %a1
20  %res = fadd <4 x float> %x, %a2
21  ret <4 x float> %res
22}
23
24define <4 x float> @test_x86_fmsub_ps(<4 x float> %a0, <4 x float> %a1, <4 x float> %a2) {
25; CHECK_FMA-LABEL: test_x86_fmsub_ps:
26; CHECK_FMA:       # BB#0:
27; CHECK_FMA-NEXT:    vfmsub213ps %xmm2, %xmm1, %xmm0
28; CHECK_FMA-NEXT:    retq
29;
30; CHECK_FMA4-LABEL: test_x86_fmsub_ps:
31; CHECK_FMA4:       # BB#0:
32; CHECK_FMA4-NEXT:    vfmsubps %xmm2, %xmm1, %xmm0, %xmm0
33; CHECK_FMA4-NEXT:    retq
34  %x = fmul <4 x float> %a0, %a1
35  %res = fsub <4 x float> %x, %a2
36  ret <4 x float> %res
37}
38
39define <4 x float> @test_x86_fnmadd_ps(<4 x float> %a0, <4 x float> %a1, <4 x float> %a2) {
40; CHECK_FMA-LABEL: test_x86_fnmadd_ps:
41; CHECK_FMA:       # BB#0:
42; CHECK_FMA-NEXT:    vfnmadd213ps %xmm2, %xmm1, %xmm0
43; CHECK_FMA-NEXT:    retq
44;
45; CHECK_FMA4-LABEL: test_x86_fnmadd_ps:
46; CHECK_FMA4:       # BB#0:
47; CHECK_FMA4-NEXT:    vfnmaddps %xmm2, %xmm1, %xmm0, %xmm0
48; CHECK_FMA4-NEXT:    retq
49  %x = fmul <4 x float> %a0, %a1
50  %res = fsub <4 x float> %a2, %x
51  ret <4 x float> %res
52}
53
54define <4 x float> @test_x86_fnmsub_ps(<4 x float> %a0, <4 x float> %a1, <4 x float> %a2) {
55; CHECK_FMA-LABEL: test_x86_fnmsub_ps:
56; CHECK_FMA:       # BB#0:
57; CHECK_FMA-NEXT:    vfnmsub213ps %xmm2, %xmm1, %xmm0
58; CHECK_FMA-NEXT:    retq
59;
60; CHECK_FMA4-LABEL: test_x86_fnmsub_ps:
61; CHECK_FMA4:       # BB#0:
62; CHECK_FMA4-NEXT:    vfnmsubps %xmm2, %xmm1, %xmm0, %xmm0
63; CHECK_FMA4-NEXT:    retq
64  %x = fmul <4 x float> %a0, %a1
65  %y = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %x
66  %res = fsub <4 x float> %y, %a2
67  ret <4 x float> %res
68}
69
70define <8 x float> @test_x86_fmadd_ps_y(<8 x float> %a0, <8 x float> %a1, <8 x float> %a2) {
71; CHECK_FMA-LABEL: test_x86_fmadd_ps_y:
72; CHECK_FMA:       # BB#0:
73; CHECK_FMA-NEXT:    vfmadd213ps %ymm2, %ymm1, %ymm0
74; CHECK_FMA-NEXT:    retq
75;
76; CHECK_FMA4-LABEL: test_x86_fmadd_ps_y:
77; CHECK_FMA4:       # BB#0:
78; CHECK_FMA4-NEXT:    vfmaddps %ymm2, %ymm1, %ymm0, %ymm0
79; CHECK_FMA4-NEXT:    retq
80  %x = fmul <8 x float> %a0, %a1
81  %res = fadd <8 x float> %x, %a2
82  ret <8 x float> %res
83}
84
85define <8 x float> @test_x86_fmsub_ps_y(<8 x float> %a0, <8 x float> %a1, <8 x float> %a2) {
86; CHECK_FMA-LABEL: test_x86_fmsub_ps_y:
87; CHECK_FMA:       # BB#0:
88; CHECK_FMA-NEXT:    vfmsub213ps %ymm2, %ymm1, %ymm0
89; CHECK_FMA-NEXT:    retq
90;
91; CHECK_FMA4-LABEL: test_x86_fmsub_ps_y:
92; CHECK_FMA4:       # BB#0:
93; CHECK_FMA4-NEXT:    vfmsubps %ymm2, %ymm1, %ymm0, %ymm0
94; CHECK_FMA4-NEXT:    retq
95  %x = fmul <8 x float> %a0, %a1
96  %res = fsub <8 x float> %x, %a2
97  ret <8 x float> %res
98}
99
100define <8 x float> @test_x86_fnmadd_ps_y(<8 x float> %a0, <8 x float> %a1, <8 x float> %a2) {
101; CHECK_FMA-LABEL: test_x86_fnmadd_ps_y:
102; CHECK_FMA:       # BB#0:
103; CHECK_FMA-NEXT:    vfnmadd213ps %ymm2, %ymm1, %ymm0
104; CHECK_FMA-NEXT:    retq
105;
106; CHECK_FMA4-LABEL: test_x86_fnmadd_ps_y:
107; CHECK_FMA4:       # BB#0:
108; CHECK_FMA4-NEXT:    vfnmaddps %ymm2, %ymm1, %ymm0, %ymm0
109; CHECK_FMA4-NEXT:    retq
110  %x = fmul <8 x float> %a0, %a1
111  %res = fsub <8 x float> %a2, %x
112  ret <8 x float> %res
113}
114
115define <8 x float> @test_x86_fnmsub_ps_y(<8 x float> %a0, <8 x float> %a1, <8 x float> %a2) {
116; CHECK_FMA-LABEL: test_x86_fnmsub_ps_y:
117; CHECK_FMA:       # BB#0:
118; CHECK_FMA-NEXT:    vfnmsub213ps %ymm2, %ymm1, %ymm0
119; CHECK_FMA-NEXT:    retq
120;
121; CHECK_FMA4-LABEL: test_x86_fnmsub_ps_y:
122; CHECK_FMA4:       # BB#0:
123; CHECK_FMA4-NEXT:    vfnmsubps %ymm2, %ymm1, %ymm0, %ymm0
124; CHECK_FMA4-NEXT:    retq
125  %x = fmul <8 x float> %a0, %a1
126  %y = fsub <8 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %x
127  %res = fsub <8 x float> %y, %a2
128  ret <8 x float> %res
129}
130
131define <4 x double> @test_x86_fmadd_pd_y(<4 x double> %a0, <4 x double> %a1, <4 x double> %a2) {
132; CHECK_FMA-LABEL: test_x86_fmadd_pd_y:
133; CHECK_FMA:       # BB#0:
134; CHECK_FMA-NEXT:    vfmadd213pd %ymm2, %ymm1, %ymm0
135; CHECK_FMA-NEXT:    retq
136;
137; CHECK_FMA4-LABEL: test_x86_fmadd_pd_y:
138; CHECK_FMA4:       # BB#0:
139; CHECK_FMA4-NEXT:    vfmaddpd %ymm2, %ymm1, %ymm0, %ymm0
140; CHECK_FMA4-NEXT:    retq
141  %x = fmul <4 x double> %a0, %a1
142  %res = fadd <4 x double> %x, %a2
143  ret <4 x double> %res
144}
145
146define <4 x double> @test_x86_fmsub_pd_y(<4 x double> %a0, <4 x double> %a1, <4 x double> %a2) {
147; CHECK_FMA-LABEL: test_x86_fmsub_pd_y:
148; CHECK_FMA:       # BB#0:
149; CHECK_FMA-NEXT:    vfmsub213pd %ymm2, %ymm1, %ymm0
150; CHECK_FMA-NEXT:    retq
151;
152; CHECK_FMA4-LABEL: test_x86_fmsub_pd_y:
153; CHECK_FMA4:       # BB#0:
154; CHECK_FMA4-NEXT:    vfmsubpd %ymm2, %ymm1, %ymm0, %ymm0
155; CHECK_FMA4-NEXT:    retq
156  %x = fmul <4 x double> %a0, %a1
157  %res = fsub <4 x double> %x, %a2
158  ret <4 x double> %res
159}
160
161define <2 x double> @test_x86_fmsub_pd(<2 x double> %a0, <2 x double> %a1, <2 x double> %a2) {
162; CHECK_FMA-LABEL: test_x86_fmsub_pd:
163; CHECK_FMA:       # BB#0:
164; CHECK_FMA-NEXT:    vfmsub213pd %xmm2, %xmm1, %xmm0
165; CHECK_FMA-NEXT:    retq
166;
167; CHECK_FMA4-LABEL: test_x86_fmsub_pd:
168; CHECK_FMA4:       # BB#0:
169; CHECK_FMA4-NEXT:    vfmsubpd %xmm2, %xmm1, %xmm0, %xmm0
170; CHECK_FMA4-NEXT:    retq
171  %x = fmul <2 x double> %a0, %a1
172  %res = fsub <2 x double> %x, %a2
173  ret <2 x double> %res
174}
175
176define float @test_x86_fnmadd_ss(float %a0, float %a1, float %a2) {
177; CHECK_FMA-LABEL: test_x86_fnmadd_ss:
178; CHECK_FMA:       # BB#0:
179; CHECK_FMA-NEXT:    vfnmadd213ss %xmm2, %xmm1, %xmm0
180; CHECK_FMA-NEXT:    retq
181;
182; CHECK_FMA4-LABEL: test_x86_fnmadd_ss:
183; CHECK_FMA4:       # BB#0:
184; CHECK_FMA4-NEXT:    vfnmaddss %xmm2, %xmm1, %xmm0, %xmm0
185; CHECK_FMA4-NEXT:    retq
186  %x = fmul float %a0, %a1
187  %res = fsub float %a2, %x
188  ret float %res
189}
190
191define double @test_x86_fnmadd_sd(double %a0, double %a1, double %a2) {
192; CHECK_FMA-LABEL: test_x86_fnmadd_sd:
193; CHECK_FMA:       # BB#0:
194; CHECK_FMA-NEXT:    vfnmadd213sd %xmm2, %xmm1, %xmm0
195; CHECK_FMA-NEXT:    retq
196;
197; CHECK_FMA4-LABEL: test_x86_fnmadd_sd:
198; CHECK_FMA4:       # BB#0:
199; CHECK_FMA4-NEXT:    vfnmaddsd %xmm2, %xmm1, %xmm0, %xmm0
200; CHECK_FMA4-NEXT:    retq
201  %x = fmul double %a0, %a1
202  %res = fsub double %a2, %x
203  ret double %res
204}
205
206define double @test_x86_fmsub_sd(double %a0, double %a1, double %a2) {
207; CHECK_FMA-LABEL: test_x86_fmsub_sd:
208; CHECK_FMA:       # BB#0:
209; CHECK_FMA-NEXT:    vfmsub213sd %xmm2, %xmm1, %xmm0
210; CHECK_FMA-NEXT:    retq
211;
212; CHECK_FMA4-LABEL: test_x86_fmsub_sd:
213; CHECK_FMA4:       # BB#0:
214; CHECK_FMA4-NEXT:    vfmsubsd %xmm2, %xmm1, %xmm0, %xmm0
215; CHECK_FMA4-NEXT:    retq
216  %x = fmul double %a0, %a1
217  %res = fsub double %x, %a2
218  ret double %res
219}
220
221define float @test_x86_fnmsub_ss(float %a0, float %a1, float %a2) {
222; CHECK_FMA-LABEL: test_x86_fnmsub_ss:
223; CHECK_FMA:       # BB#0:
224; CHECK_FMA-NEXT:    vfnmsub213ss %xmm2, %xmm1, %xmm0
225; CHECK_FMA-NEXT:    retq
226;
227; CHECK_FMA4-LABEL: test_x86_fnmsub_ss:
228; CHECK_FMA4:       # BB#0:
229; CHECK_FMA4-NEXT:    vfnmsubss %xmm2, %xmm1, %xmm0, %xmm0
230; CHECK_FMA4-NEXT:    retq
231  %x = fsub float -0.000000e+00, %a0
232  %y = fmul float %x, %a1
233  %res = fsub float %y, %a2
234  ret float %res
235}
236
237define <4 x float> @test_x86_fmadd_ps_load(<4 x float>* %a0, <4 x float> %a1, <4 x float> %a2) {
238; CHECK_FMA-LABEL: test_x86_fmadd_ps_load:
239; CHECK_FMA:       # BB#0:
240; CHECK_FMA-NEXT:    vfmadd132ps (%rdi), %xmm1, %xmm0
241; CHECK_FMA-NEXT:    retq
242;
243; CHECK_FMA4-LABEL: test_x86_fmadd_ps_load:
244; CHECK_FMA4:       # BB#0:
245; CHECK_FMA4-NEXT:    vfmaddps %xmm1, (%rdi), %xmm0, %xmm0
246; CHECK_FMA4-NEXT:    retq
247  %x = load <4 x float>, <4 x float>* %a0
248  %y = fmul <4 x float> %x, %a1
249  %res = fadd <4 x float> %y, %a2
250  ret <4 x float> %res
251}
252
253define <4 x float> @test_x86_fmsub_ps_load(<4 x float>* %a0, <4 x float> %a1, <4 x float> %a2) {
254; CHECK_FMA-LABEL: test_x86_fmsub_ps_load:
255; CHECK_FMA:       # BB#0:
256; CHECK_FMA-NEXT:    vfmsub132ps (%rdi), %xmm1, %xmm0
257; CHECK_FMA-NEXT:    retq
258;
259; CHECK_FMA4-LABEL: test_x86_fmsub_ps_load:
260; CHECK_FMA4:       # BB#0:
261; CHECK_FMA4-NEXT:    vfmsubps %xmm1, (%rdi), %xmm0, %xmm0
262; CHECK_FMA4-NEXT:    retq
263  %x = load <4 x float>, <4 x float>* %a0
264  %y = fmul <4 x float> %x, %a1
265  %res = fsub <4 x float> %y, %a2
266  ret <4 x float> %res
267}
268
269;
270; Patterns (+ fneg variants): mul(add(1.0,x),y), mul(sub(1.0,x),y), mul(sub(x,1.0),y)
271;
272
273define <4 x float> @test_v4f32_mul_add_x_one_y(<4 x float> %x, <4 x float> %y) {
274; CHECK_FMA-LABEL: test_v4f32_mul_add_x_one_y:
275; CHECK_FMA:       # BB#0:
276; CHECK_FMA-NEXT:    vfmadd213ps %xmm1, %xmm1, %xmm0
277; CHECK_FMA-NEXT:    retq
278;
279; CHECK_FMA4-LABEL: test_v4f32_mul_add_x_one_y:
280; CHECK_FMA4:       # BB#0:
281; CHECK_FMA4-NEXT:    vfmaddps %xmm1, %xmm1, %xmm0, %xmm0
282; CHECK_FMA4-NEXT:    retq
283  %a = fadd <4 x float> %x, <float 1.0, float 1.0, float 1.0, float 1.0>
284  %m = fmul <4 x float> %a, %y
285  ret <4 x float> %m
286}
287
288define <4 x float> @test_v4f32_mul_y_add_x_one(<4 x float> %x, <4 x float> %y) {
289; CHECK_FMA-LABEL: test_v4f32_mul_y_add_x_one:
290; CHECK_FMA:       # BB#0:
291; CHECK_FMA-NEXT:    vfmadd213ps %xmm1, %xmm1, %xmm0
292; CHECK_FMA-NEXT:    retq
293;
294; CHECK_FMA4-LABEL: test_v4f32_mul_y_add_x_one:
295; CHECK_FMA4:       # BB#0:
296; CHECK_FMA4-NEXT:    vfmaddps %xmm1, %xmm1, %xmm0, %xmm0
297; CHECK_FMA4-NEXT:    retq
298  %a = fadd <4 x float> %x, <float 1.0, float 1.0, float 1.0, float 1.0>
299  %m = fmul <4 x float> %y, %a
300  ret <4 x float> %m
301}
302
303define <4 x float> @test_v4f32_mul_add_x_negone_y(<4 x float> %x, <4 x float> %y) {
304; CHECK_FMA-LABEL: test_v4f32_mul_add_x_negone_y:
305; CHECK_FMA:       # BB#0:
306; CHECK_FMA-NEXT:    vfmsub213ps %xmm1, %xmm1, %xmm0
307; CHECK_FMA-NEXT:    retq
308;
309; CHECK_FMA4-LABEL: test_v4f32_mul_add_x_negone_y:
310; CHECK_FMA4:       # BB#0:
311; CHECK_FMA4-NEXT:    vfmsubps %xmm1, %xmm1, %xmm0, %xmm0
312; CHECK_FMA4-NEXT:    retq
313  %a = fadd <4 x float> %x, <float -1.0, float -1.0, float -1.0, float -1.0>
314  %m = fmul <4 x float> %a, %y
315  ret <4 x float> %m
316}
317
318define <4 x float> @test_v4f32_mul_y_add_x_negone(<4 x float> %x, <4 x float> %y) {
319; CHECK_FMA-LABEL: test_v4f32_mul_y_add_x_negone:
320; CHECK_FMA:       # BB#0:
321; CHECK_FMA-NEXT:    vfmsub213ps %xmm1, %xmm1, %xmm0
322; CHECK_FMA-NEXT:    retq
323;
324; CHECK_FMA4-LABEL: test_v4f32_mul_y_add_x_negone:
325; CHECK_FMA4:       # BB#0:
326; CHECK_FMA4-NEXT:    vfmsubps %xmm1, %xmm1, %xmm0, %xmm0
327; CHECK_FMA4-NEXT:    retq
328  %a = fadd <4 x float> %x, <float -1.0, float -1.0, float -1.0, float -1.0>
329  %m = fmul <4 x float> %y, %a
330  ret <4 x float> %m
331}
332
333define <4 x float> @test_v4f32_mul_sub_one_x_y(<4 x float> %x, <4 x float> %y) {
334; CHECK_FMA-LABEL: test_v4f32_mul_sub_one_x_y:
335; CHECK_FMA:       # BB#0:
336; CHECK_FMA-NEXT:    vfnmadd213ps %xmm1, %xmm1, %xmm0
337; CHECK_FMA-NEXT:    retq
338;
339; CHECK_FMA4-LABEL: test_v4f32_mul_sub_one_x_y:
340; CHECK_FMA4:       # BB#0:
341; CHECK_FMA4-NEXT:    vfnmaddps %xmm1, %xmm1, %xmm0, %xmm0
342; CHECK_FMA4-NEXT:    retq
343  %s = fsub <4 x float> <float 1.0, float 1.0, float 1.0, float 1.0>, %x
344  %m = fmul <4 x float> %s, %y
345  ret <4 x float> %m
346}
347
348define <4 x float> @test_v4f32_mul_y_sub_one_x(<4 x float> %x, <4 x float> %y) {
349; CHECK_FMA-LABEL: test_v4f32_mul_y_sub_one_x:
350; CHECK_FMA:       # BB#0:
351; CHECK_FMA-NEXT:    vfnmadd213ps %xmm1, %xmm1, %xmm0
352; CHECK_FMA-NEXT:    retq
353;
354; CHECK_FMA4-LABEL: test_v4f32_mul_y_sub_one_x:
355; CHECK_FMA4:       # BB#0:
356; CHECK_FMA4-NEXT:    vfnmaddps %xmm1, %xmm1, %xmm0, %xmm0
357; CHECK_FMA4-NEXT:    retq
358  %s = fsub <4 x float> <float 1.0, float 1.0, float 1.0, float 1.0>, %x
359  %m = fmul <4 x float> %y, %s
360  ret <4 x float> %m
361}
362
363define <4 x float> @test_v4f32_mul_sub_negone_x_y(<4 x float> %x, <4 x float> %y) {
364; CHECK_FMA-LABEL: test_v4f32_mul_sub_negone_x_y:
365; CHECK_FMA:       # BB#0:
366; CHECK_FMA-NEXT:    vfnmsub213ps %xmm1, %xmm1, %xmm0
367; CHECK_FMA-NEXT:    retq
368;
369; CHECK_FMA4-LABEL: test_v4f32_mul_sub_negone_x_y:
370; CHECK_FMA4:       # BB#0:
371; CHECK_FMA4-NEXT:    vfnmsubps %xmm1, %xmm1, %xmm0, %xmm0
372; CHECK_FMA4-NEXT:    retq
373  %s = fsub <4 x float> <float -1.0, float -1.0, float -1.0, float -1.0>, %x
374  %m = fmul <4 x float> %s, %y
375  ret <4 x float> %m
376}
377
378define <4 x float> @test_v4f32_mul_y_sub_negone_x(<4 x float> %x, <4 x float> %y) {
379; CHECK_FMA-LABEL: test_v4f32_mul_y_sub_negone_x:
380; CHECK_FMA:       # BB#0:
381; CHECK_FMA-NEXT:    vfnmsub213ps %xmm1, %xmm1, %xmm0
382; CHECK_FMA-NEXT:    retq
383;
384; CHECK_FMA4-LABEL: test_v4f32_mul_y_sub_negone_x:
385; CHECK_FMA4:       # BB#0:
386; CHECK_FMA4-NEXT:    vfnmsubps %xmm1, %xmm1, %xmm0, %xmm0
387; CHECK_FMA4-NEXT:    retq
388  %s = fsub <4 x float> <float -1.0, float -1.0, float -1.0, float -1.0>, %x
389  %m = fmul <4 x float> %y, %s
390  ret <4 x float> %m
391}
392
393define <4 x float> @test_v4f32_mul_sub_x_one_y(<4 x float> %x, <4 x float> %y) {
394; CHECK_FMA-LABEL: test_v4f32_mul_sub_x_one_y:
395; CHECK_FMA:       # BB#0:
396; CHECK_FMA-NEXT:    vfmsub213ps %xmm1, %xmm1, %xmm0
397; CHECK_FMA-NEXT:    retq
398;
399; CHECK_FMA4-LABEL: test_v4f32_mul_sub_x_one_y:
400; CHECK_FMA4:       # BB#0:
401; CHECK_FMA4-NEXT:    vfmsubps %xmm1, %xmm1, %xmm0, %xmm0
402; CHECK_FMA4-NEXT:    retq
403  %s = fsub <4 x float> %x, <float 1.0, float 1.0, float 1.0, float 1.0>
404  %m = fmul <4 x float> %s, %y
405  ret <4 x float> %m
406}
407
408define <4 x float> @test_v4f32_mul_y_sub_x_one(<4 x float> %x, <4 x float> %y) {
409; CHECK_FMA-LABEL: test_v4f32_mul_y_sub_x_one:
410; CHECK_FMA:       # BB#0:
411; CHECK_FMA-NEXT:    vfmsub213ps %xmm1, %xmm1, %xmm0
412; CHECK_FMA-NEXT:    retq
413;
414; CHECK_FMA4-LABEL: test_v4f32_mul_y_sub_x_one:
415; CHECK_FMA4:       # BB#0:
416; CHECK_FMA4-NEXT:    vfmsubps %xmm1, %xmm1, %xmm0, %xmm0
417; CHECK_FMA4-NEXT:    retq
418  %s = fsub <4 x float> %x, <float 1.0, float 1.0, float 1.0, float 1.0>
419  %m = fmul <4 x float> %y, %s
420  ret <4 x float> %m
421}
422
423define <4 x float> @test_v4f32_mul_sub_x_negone_y(<4 x float> %x, <4 x float> %y) {
424; CHECK_FMA-LABEL: test_v4f32_mul_sub_x_negone_y:
425; CHECK_FMA:       # BB#0:
426; CHECK_FMA-NEXT:    vfmadd213ps %xmm1, %xmm1, %xmm0
427; CHECK_FMA-NEXT:    retq
428;
429; CHECK_FMA4-LABEL: test_v4f32_mul_sub_x_negone_y:
430; CHECK_FMA4:       # BB#0:
431; CHECK_FMA4-NEXT:    vfmaddps %xmm1, %xmm1, %xmm0, %xmm0
432; CHECK_FMA4-NEXT:    retq
433  %s = fsub <4 x float> %x, <float -1.0, float -1.0, float -1.0, float -1.0>
434  %m = fmul <4 x float> %s, %y
435  ret <4 x float> %m
436}
437
438define <4 x float> @test_v4f32_mul_y_sub_x_negone(<4 x float> %x, <4 x float> %y) {
439; CHECK_FMA-LABEL: test_v4f32_mul_y_sub_x_negone:
440; CHECK_FMA:       # BB#0:
441; CHECK_FMA-NEXT:    vfmadd213ps %xmm1, %xmm1, %xmm0
442; CHECK_FMA-NEXT:    retq
443;
444; CHECK_FMA4-LABEL: test_v4f32_mul_y_sub_x_negone:
445; CHECK_FMA4:       # BB#0:
446; CHECK_FMA4-NEXT:    vfmaddps %xmm1, %xmm1, %xmm0, %xmm0
447; CHECK_FMA4-NEXT:    retq
448  %s = fsub <4 x float> %x, <float -1.0, float -1.0, float -1.0, float -1.0>
449  %m = fmul <4 x float> %y, %s
450  ret <4 x float> %m
451}
452
453;
454; Interpolation Patterns: add(mul(x,t),mul(sub(1.0,t),y))
455;
456
457define float @test_f32_interp(float %x, float %y, float %t) {
458; CHECK_FMA-LABEL: test_f32_interp:
459; CHECK_FMA:       # BB#0:
460; CHECK_FMA-NEXT:    vfnmadd213ss %xmm1, %xmm2, %xmm1
461; CHECK_FMA-NEXT:    vfmadd213ss %xmm1, %xmm2, %xmm0
462; CHECK_FMA-NEXT:    retq
463;
464; CHECK_FMA4-LABEL: test_f32_interp:
465; CHECK_FMA4:       # BB#0:
466; CHECK_FMA4-NEXT:    vfnmaddss %xmm1, %xmm1, %xmm2, %xmm1
467; CHECK_FMA4-NEXT:    vfmaddss %xmm1, %xmm2, %xmm0, %xmm0
468; CHECK_FMA4-NEXT:    retq
469  %t1 = fsub float 1.0, %t
470  %tx = fmul float %x, %t
471  %ty = fmul float %y, %t1
472  %r = fadd float %tx, %ty
473  ret float %r
474}
475
476define <4 x float> @test_v4f32_interp(<4 x float> %x, <4 x float> %y, <4 x float> %t) {
477; CHECK_FMA-LABEL: test_v4f32_interp:
478; CHECK_FMA:       # BB#0:
479; CHECK_FMA-NEXT:    vfnmadd213ps %xmm1, %xmm2, %xmm1
480; CHECK_FMA-NEXT:    vfmadd213ps %xmm1, %xmm2, %xmm0
481; CHECK_FMA-NEXT:    retq
482;
483; CHECK_FMA4-LABEL: test_v4f32_interp:
484; CHECK_FMA4:       # BB#0:
485; CHECK_FMA4-NEXT:    vfnmaddps %xmm1, %xmm1, %xmm2, %xmm1
486; CHECK_FMA4-NEXT:    vfmaddps %xmm1, %xmm2, %xmm0, %xmm0
487; CHECK_FMA4-NEXT:    retq
488  %t1 = fsub <4 x float> <float 1.0, float 1.0, float 1.0, float 1.0>, %t
489  %tx = fmul <4 x float> %x, %t
490  %ty = fmul <4 x float> %y, %t1
491  %r = fadd <4 x float> %tx, %ty
492  ret <4 x float> %r
493}
494
495define <8 x float> @test_v8f32_interp(<8 x float> %x, <8 x float> %y, <8 x float> %t) {
496; CHECK_FMA-LABEL: test_v8f32_interp:
497; CHECK_FMA:       # BB#0:
498; CHECK_FMA-NEXT:    vfnmadd213ps %ymm1, %ymm2, %ymm1
499; CHECK_FMA-NEXT:    vfmadd213ps %ymm1, %ymm2, %ymm0
500; CHECK_FMA-NEXT:    retq
501;
502; CHECK_FMA4-LABEL: test_v8f32_interp:
503; CHECK_FMA4:       # BB#0:
504; CHECK_FMA4-NEXT:    vfnmaddps %ymm1, %ymm1, %ymm2, %ymm1
505; CHECK_FMA4-NEXT:    vfmaddps %ymm1, %ymm2, %ymm0, %ymm0
506; CHECK_FMA4-NEXT:    retq
507  %t1 = fsub <8 x float> <float 1.0, float 1.0, float 1.0, float 1.0, float 1.0, float 1.0, float 1.0, float 1.0>, %t
508  %tx = fmul <8 x float> %x, %t
509  %ty = fmul <8 x float> %y, %t1
510  %r = fadd <8 x float> %tx, %ty
511  ret <8 x float> %r
512}
513
514define double @test_f64_interp(double %x, double %y, double %t) {
515; CHECK_FMA-LABEL: test_f64_interp:
516; CHECK_FMA:       # BB#0:
517; CHECK_FMA-NEXT:    vfnmadd213sd %xmm1, %xmm2, %xmm1
518; CHECK_FMA-NEXT:    vfmadd213sd %xmm1, %xmm2, %xmm0
519; CHECK_FMA-NEXT:    retq
520;
521; CHECK_FMA4-LABEL: test_f64_interp:
522; CHECK_FMA4:       # BB#0:
523; CHECK_FMA4-NEXT:    vfnmaddsd %xmm1, %xmm1, %xmm2, %xmm1
524; CHECK_FMA4-NEXT:    vfmaddsd %xmm1, %xmm2, %xmm0, %xmm0
525; CHECK_FMA4-NEXT:    retq
526  %t1 = fsub double 1.0, %t
527  %tx = fmul double %x, %t
528  %ty = fmul double %y, %t1
529  %r = fadd double %tx, %ty
530  ret double %r
531}
532
533define <2 x double> @test_v2f64_interp(<2 x double> %x, <2 x double> %y, <2 x double> %t) {
534; CHECK_FMA-LABEL: test_v2f64_interp:
535; CHECK_FMA:       # BB#0:
536; CHECK_FMA-NEXT:    vfnmadd213pd %xmm1, %xmm2, %xmm1
537; CHECK_FMA-NEXT:    vfmadd213pd %xmm1, %xmm2, %xmm0
538; CHECK_FMA-NEXT:    retq
539;
540; CHECK_FMA4-LABEL: test_v2f64_interp:
541; CHECK_FMA4:       # BB#0:
542; CHECK_FMA4-NEXT:    vfnmaddpd %xmm1, %xmm1, %xmm2, %xmm1
543; CHECK_FMA4-NEXT:    vfmaddpd %xmm1, %xmm2, %xmm0, %xmm0
544; CHECK_FMA4-NEXT:    retq
545  %t1 = fsub <2 x double> <double 1.0, double 1.0>, %t
546  %tx = fmul <2 x double> %x, %t
547  %ty = fmul <2 x double> %y, %t1
548  %r = fadd <2 x double> %tx, %ty
549  ret <2 x double> %r
550}
551
552define <4 x double> @test_v4f64_interp(<4 x double> %x, <4 x double> %y, <4 x double> %t) {
553; CHECK_FMA-LABEL: test_v4f64_interp:
554; CHECK_FMA:       # BB#0:
555; CHECK_FMA-NEXT:    vfnmadd213pd %ymm1, %ymm2, %ymm1
556; CHECK_FMA-NEXT:    vfmadd213pd %ymm1, %ymm2, %ymm0
557; CHECK_FMA-NEXT:    retq
558;
559; CHECK_FMA4-LABEL: test_v4f64_interp:
560; CHECK_FMA4:       # BB#0:
561; CHECK_FMA4-NEXT:    vfnmaddpd %ymm1, %ymm1, %ymm2, %ymm1
562; CHECK_FMA4-NEXT:    vfmaddpd %ymm1, %ymm2, %ymm0, %ymm0
563; CHECK_FMA4-NEXT:    retq
564  %t1 = fsub <4 x double> <double 1.0, double 1.0, double 1.0, double 1.0>, %t
565  %tx = fmul <4 x double> %x, %t
566  %ty = fmul <4 x double> %y, %t1
567  %r = fadd <4 x double> %tx, %ty
568  ret <4 x double> %r
569}
570
571; (fma x, c1, (fmul x, c2)) -> (fmul x, c1+c2)
572
573define <4 x float> @test_v4f32_fma_x_c1_fmul_x_c2(<4 x float> %x) #0 {
574; ALL-LABEL: test_v4f32_fma_x_c1_fmul_x_c2:
575; ALL:       # BB#0:
576; ALL-NEXT:    vmulps {{.*}}(%rip), %xmm0, %xmm0
577; ALL-NEXT:    retq
578  %m0 = fmul <4 x float> %x, <float 1.0, float 2.0, float 3.0, float 4.0>
579  %m1 = fmul <4 x float> %x, <float 4.0, float 3.0, float 2.0, float 1.0>
580  %a  = fadd <4 x float> %m0, %m1
581  ret <4 x float> %a
582}
583
584; (fma (fmul x, c1), c2, y) -> (fma x, c1*c2, y)
585
586define <4 x float> @test_v4f32_fma_fmul_x_c1_c2_y(<4 x float> %x, <4 x float> %y) #0 {
587; CHECK_FMA-LABEL: test_v4f32_fma_fmul_x_c1_c2_y:
588; CHECK_FMA:       # BB#0:
589; CHECK_FMA-NEXT:    vfmadd132ps {{.*}}(%rip), %xmm1, %xmm0
590; CHECK_FMA-NEXT:    retq
591;
592; CHECK_FMA4-LABEL: test_v4f32_fma_fmul_x_c1_c2_y:
593; CHECK_FMA4:       # BB#0:
594; CHECK_FMA4-NEXT:    vfmaddps %xmm1, {{.*}}(%rip), %xmm0, %xmm0
595; CHECK_FMA4-NEXT:    retq
596  %m0 = fmul <4 x float> %x,  <float 1.0, float 2.0, float 3.0, float 4.0>
597  %m1 = fmul <4 x float> %m0, <float 4.0, float 3.0, float 2.0, float 1.0>
598  %a  = fadd <4 x float> %m1, %y
599  ret <4 x float> %a
600}
601
602attributes #0 = { "unsafe-fp-math"="true" }
603