1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -verify-machineinstrs -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr < %s -mtriple=powerpc64-unknown-linux -mcpu=pwr8 | FileCheck %s
3; RUN: llc -verify-machineinstrs -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr < %s -mtriple=powerpc64le-unknown-linux -mcpu=pwr9 | FileCheck %s
4; RUN: llc -verify-machineinstrs -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr < %s -mtriple=powerpc64le-unknown-linux -mcpu=pwr8 -mattr=-vsx | FileCheck %s -check-prefix=NOVSX
5
6declare float @llvm.experimental.constrained.fadd.f32(float, float, metadata, metadata)
7declare double @llvm.experimental.constrained.fadd.f64(double, double, metadata, metadata)
8declare <4 x float> @llvm.experimental.constrained.fadd.v4f32(<4 x float>, <4 x float>, metadata, metadata)
9declare <2 x double> @llvm.experimental.constrained.fadd.v2f64(<2 x double>, <2 x double>, metadata, metadata)
10
11declare float @llvm.experimental.constrained.fsub.f32(float, float, metadata, metadata)
12declare double @llvm.experimental.constrained.fsub.f64(double, double, metadata, metadata)
13declare <4 x float> @llvm.experimental.constrained.fsub.v4f32(<4 x float>, <4 x float>, metadata, metadata)
14declare <2 x double> @llvm.experimental.constrained.fsub.v2f64(<2 x double>, <2 x double>, metadata, metadata)
15
16declare float @llvm.experimental.constrained.fmul.f32(float, float, metadata, metadata)
17declare double @llvm.experimental.constrained.fmul.f64(double, double, metadata, metadata)
18declare <4 x float> @llvm.experimental.constrained.fmul.v4f32(<4 x float>, <4 x float>, metadata, metadata)
19declare <2 x double> @llvm.experimental.constrained.fmul.v2f64(<2 x double>, <2 x double>, metadata, metadata)
20
21declare float @llvm.experimental.constrained.fdiv.f32(float, float, metadata, metadata)
22declare double @llvm.experimental.constrained.fdiv.f64(double, double, metadata, metadata)
23declare <4 x float> @llvm.experimental.constrained.fdiv.v4f32(<4 x float>, <4 x float>, metadata, metadata)
24declare <2 x double> @llvm.experimental.constrained.fdiv.v2f64(<2 x double>, <2 x double>, metadata, metadata)
25
26declare float @llvm.experimental.constrained.fma.f32(float, float, float, metadata, metadata)
27declare double @llvm.experimental.constrained.fma.f64(double, double, double, metadata, metadata)
28declare <4 x float> @llvm.experimental.constrained.fma.v4f32(<4 x float>, <4 x float>, <4 x float>, metadata, metadata)
29declare <2 x double> @llvm.experimental.constrained.fma.v2f64(<2 x double>, <2 x double>, <2 x double>, metadata, metadata)
30
31declare float @llvm.experimental.constrained.sqrt.f32(float, metadata, metadata)
32declare double @llvm.experimental.constrained.sqrt.f64(double, metadata, metadata)
33declare <4 x float> @llvm.experimental.constrained.sqrt.v4f32(<4 x float>, metadata, metadata)
34declare <2 x double> @llvm.experimental.constrained.sqrt.v2f64(<2 x double>, metadata, metadata)
35
36define float @fadd_f32(float %f1, float %f2) #0 {
37; CHECK-LABEL: fadd_f32:
38; CHECK:       # %bb.0:
39; CHECK-NEXT:    xsaddsp f1, f1, f2
40; CHECK-NEXT:    blr
41;
42; NOVSX-LABEL: fadd_f32:
43; NOVSX:       # %bb.0:
44; NOVSX-NEXT:    fadds f1, f1, f2
45; NOVSX-NEXT:    blr
46  %res = call float @llvm.experimental.constrained.fadd.f32(
47                        float %f1, float %f2,
48                        metadata !"round.dynamic",
49                        metadata !"fpexcept.strict") #0
50  ret float %res
51}
52
53define double @fadd_f64(double %f1, double %f2) #0 {
54; CHECK-LABEL: fadd_f64:
55; CHECK:       # %bb.0:
56; CHECK-NEXT:    xsadddp f1, f1, f2
57; CHECK-NEXT:    blr
58;
59; NOVSX-LABEL: fadd_f64:
60; NOVSX:       # %bb.0:
61; NOVSX-NEXT:    fadd f1, f1, f2
62; NOVSX-NEXT:    blr
63  %res = call double @llvm.experimental.constrained.fadd.f64(
64                        double %f1, double %f2,
65                        metadata !"round.dynamic",
66                        metadata !"fpexcept.strict") #0
67  ret double %res
68}
69
70define <4 x float> @fadd_v4f32(<4 x float> %vf1, <4 x float> %vf2) #0 {
71; CHECK-LABEL: fadd_v4f32:
72; CHECK:       # %bb.0:
73; CHECK-NEXT:    xvaddsp v2, v2, v3
74; CHECK-NEXT:    blr
75;
76; NOVSX-LABEL: fadd_v4f32:
77; NOVSX:       # %bb.0:
78; NOVSX-NEXT:    addi r3, r1, -32
79; NOVSX-NEXT:    addi r4, r1, -48
80; NOVSX-NEXT:    stvx v3, 0, r3
81; NOVSX-NEXT:    stvx v2, 0, r4
82; NOVSX-NEXT:    addi r3, r1, -16
83; NOVSX-NEXT:    lfs f0, -20(r1)
84; NOVSX-NEXT:    lfs f1, -36(r1)
85; NOVSX-NEXT:    fadds f0, f1, f0
86; NOVSX-NEXT:    lfs f1, -40(r1)
87; NOVSX-NEXT:    stfs f0, -4(r1)
88; NOVSX-NEXT:    lfs f0, -24(r1)
89; NOVSX-NEXT:    fadds f0, f1, f0
90; NOVSX-NEXT:    lfs f1, -44(r1)
91; NOVSX-NEXT:    stfs f0, -8(r1)
92; NOVSX-NEXT:    lfs f0, -28(r1)
93; NOVSX-NEXT:    fadds f0, f1, f0
94; NOVSX-NEXT:    lfs f1, -48(r1)
95; NOVSX-NEXT:    stfs f0, -12(r1)
96; NOVSX-NEXT:    lfs f0, -32(r1)
97; NOVSX-NEXT:    fadds f0, f1, f0
98; NOVSX-NEXT:    stfs f0, -16(r1)
99; NOVSX-NEXT:    lvx v2, 0, r3
100; NOVSX-NEXT:    blr
101  %res = call <4 x float> @llvm.experimental.constrained.fadd.v4f32(
102                        <4 x float> %vf1, <4 x float> %vf2,
103                        metadata !"round.dynamic",
104                        metadata !"fpexcept.strict") #0
105  ret <4 x float> %res
106}
107
108define <2 x double> @fadd_v2f64(<2 x double> %vf1, <2 x double> %vf2) #0 {
109; CHECK-LABEL: fadd_v2f64:
110; CHECK:       # %bb.0:
111; CHECK-NEXT:    xvadddp v2, v2, v3
112; CHECK-NEXT:    blr
113;
114; NOVSX-LABEL: fadd_v2f64:
115; NOVSX:       # %bb.0:
116; NOVSX-NEXT:    fadd f2, f2, f4
117; NOVSX-NEXT:    fadd f1, f1, f3
118; NOVSX-NEXT:    blr
119  %res = call <2 x double> @llvm.experimental.constrained.fadd.v2f64(
120                        <2 x double> %vf1, <2 x double> %vf2,
121                        metadata !"round.dynamic",
122                        metadata !"fpexcept.strict") #0
123  ret <2 x double> %res
124}
125
126define float @fsub_f32(float %f1, float %f2) #0 {
127; CHECK-LABEL: fsub_f32:
128; CHECK:       # %bb.0:
129; CHECK-NEXT:    xssubsp f1, f1, f2
130; CHECK-NEXT:    blr
131;
132; NOVSX-LABEL: fsub_f32:
133; NOVSX:       # %bb.0:
134; NOVSX-NEXT:    fsubs f1, f1, f2
135; NOVSX-NEXT:    blr
136
137  %res = call float @llvm.experimental.constrained.fsub.f32(
138                        float %f1, float %f2,
139                        metadata !"round.dynamic",
140                        metadata !"fpexcept.strict") #0
141  ret float %res;
142}
143
144define double @fsub_f64(double %f1, double %f2) #0 {
145; CHECK-LABEL: fsub_f64:
146; CHECK:       # %bb.0:
147; CHECK-NEXT:    xssubdp f1, f1, f2
148; CHECK-NEXT:    blr
149;
150; NOVSX-LABEL: fsub_f64:
151; NOVSX:       # %bb.0:
152; NOVSX-NEXT:    fsub f1, f1, f2
153; NOVSX-NEXT:    blr
154
155  %res = call double @llvm.experimental.constrained.fsub.f64(
156                        double %f1, double %f2,
157                        metadata !"round.dynamic",
158                        metadata !"fpexcept.strict") #0
159  ret double %res;
160}
161
162define <4 x float> @fsub_v4f32(<4 x float> %vf1, <4 x float> %vf2) #0 {
163; CHECK-LABEL: fsub_v4f32:
164; CHECK:       # %bb.0:
165; CHECK-NEXT:    xvsubsp v2, v2, v3
166; CHECK-NEXT:    blr
167;
168; NOVSX-LABEL: fsub_v4f32:
169; NOVSX:       # %bb.0:
170; NOVSX-NEXT:    addi r3, r1, -32
171; NOVSX-NEXT:    addi r4, r1, -48
172; NOVSX-NEXT:    stvx v3, 0, r3
173; NOVSX-NEXT:    stvx v2, 0, r4
174; NOVSX-NEXT:    addi r3, r1, -16
175; NOVSX-NEXT:    lfs f0, -20(r1)
176; NOVSX-NEXT:    lfs f1, -36(r1)
177; NOVSX-NEXT:    fsubs f0, f1, f0
178; NOVSX-NEXT:    lfs f1, -40(r1)
179; NOVSX-NEXT:    stfs f0, -4(r1)
180; NOVSX-NEXT:    lfs f0, -24(r1)
181; NOVSX-NEXT:    fsubs f0, f1, f0
182; NOVSX-NEXT:    lfs f1, -44(r1)
183; NOVSX-NEXT:    stfs f0, -8(r1)
184; NOVSX-NEXT:    lfs f0, -28(r1)
185; NOVSX-NEXT:    fsubs f0, f1, f0
186; NOVSX-NEXT:    lfs f1, -48(r1)
187; NOVSX-NEXT:    stfs f0, -12(r1)
188; NOVSX-NEXT:    lfs f0, -32(r1)
189; NOVSX-NEXT:    fsubs f0, f1, f0
190; NOVSX-NEXT:    stfs f0, -16(r1)
191; NOVSX-NEXT:    lvx v2, 0, r3
192; NOVSX-NEXT:    blr
193  %res = call <4 x float> @llvm.experimental.constrained.fsub.v4f32(
194                        <4 x float> %vf1, <4 x float> %vf2,
195                        metadata !"round.dynamic",
196                        metadata !"fpexcept.strict") #0
197  ret <4 x float> %res;
198}
199
200define <2 x double> @fsub_v2f64(<2 x double> %vf1, <2 x double> %vf2) #0 {
201; CHECK-LABEL: fsub_v2f64:
202; CHECK:       # %bb.0:
203; CHECK-NEXT:    xvsubdp v2, v2, v3
204; CHECK-NEXT:    blr
205;
206; NOVSX-LABEL: fsub_v2f64:
207; NOVSX:       # %bb.0:
208; NOVSX-NEXT:    fsub f2, f2, f4
209; NOVSX-NEXT:    fsub f1, f1, f3
210; NOVSX-NEXT:    blr
211  %res = call <2 x double> @llvm.experimental.constrained.fsub.v2f64(
212                        <2 x double> %vf1, <2 x double> %vf2,
213                        metadata !"round.dynamic",
214                        metadata !"fpexcept.strict") #0
215  ret <2 x double> %res;
216}
217
218define float @fmul_f32(float %f1, float %f2) #0 {
219; CHECK-LABEL: fmul_f32:
220; CHECK:       # %bb.0:
221; CHECK-NEXT:    xsmulsp f1, f1, f2
222; CHECK-NEXT:    blr
223;
224; NOVSX-LABEL: fmul_f32:
225; NOVSX:       # %bb.0:
226; NOVSX-NEXT:    fmuls f1, f1, f2
227; NOVSX-NEXT:    blr
228
229  %res = call float @llvm.experimental.constrained.fmul.f32(
230                        float %f1, float %f2,
231                        metadata !"round.dynamic",
232                        metadata !"fpexcept.strict") #0
233  ret float %res;
234}
235
236define double @fmul_f64(double %f1, double %f2) #0 {
237; CHECK-LABEL: fmul_f64:
238; CHECK:       # %bb.0:
239; CHECK-NEXT:    xsmuldp f1, f1, f2
240; CHECK-NEXT:    blr
241;
242; NOVSX-LABEL: fmul_f64:
243; NOVSX:       # %bb.0:
244; NOVSX-NEXT:    fmul f1, f1, f2
245; NOVSX-NEXT:    blr
246
247  %res = call double @llvm.experimental.constrained.fmul.f64(
248                        double %f1, double %f2,
249                        metadata !"round.dynamic",
250                        metadata !"fpexcept.strict") #0
251  ret double %res;
252}
253
254define <4 x float> @fmul_v4f32(<4 x float> %vf1, <4 x float> %vf2) #0 {
255; CHECK-LABEL: fmul_v4f32:
256; CHECK:       # %bb.0:
257; CHECK-NEXT:    xvmulsp v2, v2, v3
258; CHECK-NEXT:    blr
259;
260; NOVSX-LABEL: fmul_v4f32:
261; NOVSX:       # %bb.0:
262; NOVSX-NEXT:    addi r3, r1, -32
263; NOVSX-NEXT:    addi r4, r1, -48
264; NOVSX-NEXT:    stvx v3, 0, r3
265; NOVSX-NEXT:    stvx v2, 0, r4
266; NOVSX-NEXT:    addi r3, r1, -16
267; NOVSX-NEXT:    lfs f0, -20(r1)
268; NOVSX-NEXT:    lfs f1, -36(r1)
269; NOVSX-NEXT:    fmuls f0, f1, f0
270; NOVSX-NEXT:    lfs f1, -40(r1)
271; NOVSX-NEXT:    stfs f0, -4(r1)
272; NOVSX-NEXT:    lfs f0, -24(r1)
273; NOVSX-NEXT:    fmuls f0, f1, f0
274; NOVSX-NEXT:    lfs f1, -44(r1)
275; NOVSX-NEXT:    stfs f0, -8(r1)
276; NOVSX-NEXT:    lfs f0, -28(r1)
277; NOVSX-NEXT:    fmuls f0, f1, f0
278; NOVSX-NEXT:    lfs f1, -48(r1)
279; NOVSX-NEXT:    stfs f0, -12(r1)
280; NOVSX-NEXT:    lfs f0, -32(r1)
281; NOVSX-NEXT:    fmuls f0, f1, f0
282; NOVSX-NEXT:    stfs f0, -16(r1)
283; NOVSX-NEXT:    lvx v2, 0, r3
284; NOVSX-NEXT:    blr
285  %res = call <4 x float> @llvm.experimental.constrained.fmul.v4f32(
286                        <4 x float> %vf1, <4 x float> %vf2,
287                        metadata !"round.dynamic",
288                        metadata !"fpexcept.strict") #0
289  ret <4 x float> %res;
290}
291
292define <2 x double> @fmul_v2f64(<2 x double> %vf1, <2 x double> %vf2) #0 {
293; CHECK-LABEL: fmul_v2f64:
294; CHECK:       # %bb.0:
295; CHECK-NEXT:    xvmuldp v2, v2, v3
296; CHECK-NEXT:    blr
297;
298; NOVSX-LABEL: fmul_v2f64:
299; NOVSX:       # %bb.0:
300; NOVSX-NEXT:    fmul f2, f2, f4
301; NOVSX-NEXT:    fmul f1, f1, f3
302; NOVSX-NEXT:    blr
303  %res = call <2 x double> @llvm.experimental.constrained.fmul.v2f64(
304                        <2 x double> %vf1, <2 x double> %vf2,
305                        metadata !"round.dynamic",
306                        metadata !"fpexcept.strict") #0
307  ret <2 x double> %res;
308}
309
310define float @fdiv_f32(float %f1, float %f2) #0 {
311; CHECK-LABEL: fdiv_f32:
312; CHECK:       # %bb.0:
313; CHECK-NEXT:    xsdivsp f1, f1, f2
314; CHECK-NEXT:    blr
315;
316; NOVSX-LABEL: fdiv_f32:
317; NOVSX:       # %bb.0:
318; NOVSX-NEXT:    fdivs f1, f1, f2
319; NOVSX-NEXT:    blr
320
321  %res = call float @llvm.experimental.constrained.fdiv.f32(
322                        float %f1, float %f2,
323                        metadata !"round.dynamic",
324                        metadata !"fpexcept.strict") #0
325  ret float %res;
326}
327
328define double @fdiv_f64(double %f1, double %f2) #0 {
329; CHECK-LABEL: fdiv_f64:
330; CHECK:       # %bb.0:
331; CHECK-NEXT:    xsdivdp f1, f1, f2
332; CHECK-NEXT:    blr
333;
334; NOVSX-LABEL: fdiv_f64:
335; NOVSX:       # %bb.0:
336; NOVSX-NEXT:    fdiv f1, f1, f2
337; NOVSX-NEXT:    blr
338
339  %res = call double @llvm.experimental.constrained.fdiv.f64(
340                        double %f1, double %f2,
341                        metadata !"round.dynamic",
342                        metadata !"fpexcept.strict") #0
343  ret double %res;
344}
345
346define <4 x float> @fdiv_v4f32(<4 x float> %vf1, <4 x float> %vf2) #0 {
347; CHECK-LABEL: fdiv_v4f32:
348; CHECK:       # %bb.0:
349; CHECK-NEXT:    xvdivsp v2, v2, v3
350; CHECK-NEXT:    blr
351;
352; NOVSX-LABEL: fdiv_v4f32:
353; NOVSX:       # %bb.0:
354; NOVSX-NEXT:    addi r3, r1, -32
355; NOVSX-NEXT:    addi r4, r1, -48
356; NOVSX-NEXT:    stvx v3, 0, r3
357; NOVSX-NEXT:    stvx v2, 0, r4
358; NOVSX-NEXT:    addi r3, r1, -16
359; NOVSX-NEXT:    lfs f0, -20(r1)
360; NOVSX-NEXT:    lfs f1, -36(r1)
361; NOVSX-NEXT:    fdivs f0, f1, f0
362; NOVSX-NEXT:    lfs f1, -40(r1)
363; NOVSX-NEXT:    stfs f0, -4(r1)
364; NOVSX-NEXT:    lfs f0, -24(r1)
365; NOVSX-NEXT:    fdivs f0, f1, f0
366; NOVSX-NEXT:    lfs f1, -44(r1)
367; NOVSX-NEXT:    stfs f0, -8(r1)
368; NOVSX-NEXT:    lfs f0, -28(r1)
369; NOVSX-NEXT:    fdivs f0, f1, f0
370; NOVSX-NEXT:    lfs f1, -48(r1)
371; NOVSX-NEXT:    stfs f0, -12(r1)
372; NOVSX-NEXT:    lfs f0, -32(r1)
373; NOVSX-NEXT:    fdivs f0, f1, f0
374; NOVSX-NEXT:    stfs f0, -16(r1)
375; NOVSX-NEXT:    lvx v2, 0, r3
376; NOVSX-NEXT:    blr
377  %res = call <4 x float> @llvm.experimental.constrained.fdiv.v4f32(
378                        <4 x float> %vf1, <4 x float> %vf2,
379                        metadata !"round.dynamic",
380                        metadata !"fpexcept.strict") #0
381  ret <4 x float> %res
382}
383
384define <2 x double> @fdiv_v2f64(<2 x double> %vf1, <2 x double> %vf2) #0 {
385; CHECK-LABEL: fdiv_v2f64:
386; CHECK:       # %bb.0:
387; CHECK-NEXT:    xvdivdp v2, v2, v3
388; CHECK-NEXT:    blr
389;
390; NOVSX-LABEL: fdiv_v2f64:
391; NOVSX:       # %bb.0:
392; NOVSX-NEXT:    fdiv f2, f2, f4
393; NOVSX-NEXT:    fdiv f1, f1, f3
394; NOVSX-NEXT:    blr
395  %res = call <2 x double> @llvm.experimental.constrained.fdiv.v2f64(
396                        <2 x double> %vf1, <2 x double> %vf2,
397                        metadata !"round.dynamic",
398                        metadata !"fpexcept.strict") #0
399  ret <2 x double> %res
400}
401
402define double @no_fma_fold(double %f1, double %f2, double %f3) #0 {
403; CHECK-LABEL: no_fma_fold:
404; CHECK:       # %bb.0:
405; CHECK-NEXT:    xsmuldp f0, f1, f2
406; CHECK-NEXT:    xsadddp f1, f0, f3
407; CHECK-NEXT:    blr
408;
409; NOVSX-LABEL: no_fma_fold:
410; NOVSX:       # %bb.0:
411; NOVSX-NEXT:    fmul f0, f1, f2
412; NOVSX-NEXT:    fadd f1, f0, f3
413; NOVSX-NEXT:    blr
414  %mul = call double @llvm.experimental.constrained.fmul.f64(
415                        double %f1, double %f2,
416                        metadata !"round.dynamic",
417                        metadata !"fpexcept.strict") #0
418  %add = call double @llvm.experimental.constrained.fadd.f64(
419                        double %mul, double %f3,
420                        metadata !"round.dynamic",
421                        metadata !"fpexcept.strict") #0
422  ret double %add
423}
424
425define float @fmadd_f32(float %f0, float %f1, float %f2) #0 {
426; CHECK-LABEL: fmadd_f32:
427; CHECK:       # %bb.0:
428; CHECK-NEXT:    xsmaddasp f3, f1, f2
429; CHECK-NEXT:    fmr f1, f3
430; CHECK-NEXT:    blr
431;
432; NOVSX-LABEL: fmadd_f32:
433; NOVSX:       # %bb.0:
434; NOVSX-NEXT:    fmadds f1, f1, f2, f3
435; NOVSX-NEXT:    blr
436  %res = call float @llvm.experimental.constrained.fma.f32(
437                        float %f0, float %f1, float %f2,
438                        metadata !"round.dynamic",
439                        metadata !"fpexcept.strict") #0
440  ret float %res
441}
442
443define double @fmadd_f64(double %f0, double %f1, double %f2) #0 {
444; CHECK-LABEL: fmadd_f64:
445; CHECK:       # %bb.0:
446; CHECK-NEXT:    xsmaddadp f3, f1, f2
447; CHECK-NEXT:    fmr f1, f3
448; CHECK-NEXT:    blr
449;
450; NOVSX-LABEL: fmadd_f64:
451; NOVSX:       # %bb.0:
452; NOVSX-NEXT:    fmadd f1, f1, f2, f3
453; NOVSX-NEXT:    blr
454  %res = call double @llvm.experimental.constrained.fma.f64(
455                        double %f0, double %f1, double %f2,
456                        metadata !"round.dynamic",
457                        metadata !"fpexcept.strict") #0
458  ret double %res
459}
460
461define <4 x float> @fmadd_v4f32(<4 x float> %vf0, <4 x float> %vf1, <4 x float> %vf2) #0 {
462; CHECK-LABEL: fmadd_v4f32:
463; CHECK:       # %bb.0:
464; CHECK-NEXT:    xvmaddasp v4, v2, v3
465; CHECK-NEXT:    vmr v2, v4
466; CHECK-NEXT:    blr
467;
468; NOVSX-LABEL: fmadd_v4f32:
469; NOVSX:       # %bb.0:
470; NOVSX-NEXT:    addi r3, r1, -32
471; NOVSX-NEXT:    addi r4, r1, -48
472; NOVSX-NEXT:    stvx v4, 0, r3
473; NOVSX-NEXT:    addi r3, r1, -64
474; NOVSX-NEXT:    stvx v3, 0, r4
475; NOVSX-NEXT:    stvx v2, 0, r3
476; NOVSX-NEXT:    addi r3, r1, -16
477; NOVSX-NEXT:    lfs f0, -20(r1)
478; NOVSX-NEXT:    lfs f1, -36(r1)
479; NOVSX-NEXT:    lfs f2, -52(r1)
480; NOVSX-NEXT:    fmadds f0, f2, f1, f0
481; NOVSX-NEXT:    lfs f1, -40(r1)
482; NOVSX-NEXT:    lfs f2, -56(r1)
483; NOVSX-NEXT:    stfs f0, -4(r1)
484; NOVSX-NEXT:    lfs f0, -24(r1)
485; NOVSX-NEXT:    fmadds f0, f2, f1, f0
486; NOVSX-NEXT:    lfs f1, -44(r1)
487; NOVSX-NEXT:    lfs f2, -60(r1)
488; NOVSX-NEXT:    stfs f0, -8(r1)
489; NOVSX-NEXT:    lfs f0, -28(r1)
490; NOVSX-NEXT:    fmadds f0, f2, f1, f0
491; NOVSX-NEXT:    lfs f1, -48(r1)
492; NOVSX-NEXT:    lfs f2, -64(r1)
493; NOVSX-NEXT:    stfs f0, -12(r1)
494; NOVSX-NEXT:    lfs f0, -32(r1)
495; NOVSX-NEXT:    fmadds f0, f2, f1, f0
496; NOVSX-NEXT:    stfs f0, -16(r1)
497; NOVSX-NEXT:    lvx v2, 0, r3
498; NOVSX-NEXT:    blr
499  %res = call <4 x float> @llvm.experimental.constrained.fma.v4f32(
500                        <4 x float> %vf0, <4 x float> %vf1, <4 x float> %vf2,
501                        metadata !"round.dynamic",
502                        metadata !"fpexcept.strict") #0
503  ret <4 x float> %res
504}
505
506define <2 x double> @fmadd_v2f64(<2 x double> %vf0, <2 x double> %vf1, <2 x double> %vf2) #0 {
507; CHECK-LABEL: fmadd_v2f64:
508; CHECK:       # %bb.0:
509; CHECK-NEXT:    xvmaddadp v4, v2, v3
510; CHECK-NEXT:    vmr v2, v4
511; CHECK-NEXT:    blr
512;
513; NOVSX-LABEL: fmadd_v2f64:
514; NOVSX:       # %bb.0:
515; NOVSX-NEXT:    fmadd f2, f2, f4, f6
516; NOVSX-NEXT:    fmadd f1, f1, f3, f5
517; NOVSX-NEXT:    blr
518  %res = call <2 x double> @llvm.experimental.constrained.fma.v2f64(
519                        <2 x double> %vf0, <2 x double> %vf1, <2 x double> %vf2,
520                        metadata !"round.dynamic",
521                        metadata !"fpexcept.strict") #0
522  ret <2 x double> %res
523}
524
525define float @fmsub_f32(float %f0, float %f1, float %f2) #0 {
526; CHECK-LABEL: fmsub_f32:
527; CHECK:       # %bb.0:
528; CHECK-NEXT:    xsmsubasp f3, f1, f2
529; CHECK-NEXT:    fmr f1, f3
530; CHECK-NEXT:    blr
531;
532; NOVSX-LABEL: fmsub_f32:
533; NOVSX:       # %bb.0:
534; NOVSX-NEXT:    fmsubs f1, f1, f2, f3
535; NOVSX-NEXT:    blr
536  %neg = fneg float %f2
537  %res = call float @llvm.experimental.constrained.fma.f32(
538                        float %f0, float %f1, float %neg,
539                        metadata !"round.dynamic",
540                        metadata !"fpexcept.strict") #0
541  ret float %res
542}
543
544define double @fmsub_f64(double %f0, double %f1, double %f2) #0 {
545; CHECK-LABEL: fmsub_f64:
546; CHECK:       # %bb.0:
547; CHECK-NEXT:    xsmsubadp f3, f1, f2
548; CHECK-NEXT:    fmr f1, f3
549; CHECK-NEXT:    blr
550;
551; NOVSX-LABEL: fmsub_f64:
552; NOVSX:       # %bb.0:
553; NOVSX-NEXT:    fmsub f1, f1, f2, f3
554; NOVSX-NEXT:    blr
555  %neg = fneg double %f2
556  %res = call double @llvm.experimental.constrained.fma.f64(
557                        double %f0, double %f1, double %neg,
558                        metadata !"round.dynamic",
559                        metadata !"fpexcept.strict") #0
560  ret double %res
561}
562
563define <4 x float> @fmsub_v4f32(<4 x float> %vf0, <4 x float> %vf1, <4 x float> %vf2) #0 {
564; CHECK-LABEL: fmsub_v4f32:
565; CHECK:       # %bb.0:
566; CHECK-NEXT:    xvmsubasp v4, v2, v3
567; CHECK-NEXT:    vmr v2, v4
568; CHECK-NEXT:    blr
569;
570; NOVSX-LABEL: fmsub_v4f32:
571; NOVSX:       # %bb.0:
572; NOVSX-NEXT:    vspltisb v5, -1
573; NOVSX-NEXT:    addi r3, r1, -48
574; NOVSX-NEXT:    addi r4, r1, -64
575; NOVSX-NEXT:    stvx v3, 0, r3
576; NOVSX-NEXT:    addi r3, r1, -32
577; NOVSX-NEXT:    stvx v2, 0, r4
578; NOVSX-NEXT:    vslw v5, v5, v5
579; NOVSX-NEXT:    vsubfp v4, v5, v4
580; NOVSX-NEXT:    stvx v4, 0, r3
581; NOVSX-NEXT:    addi r3, r1, -16
582; NOVSX-NEXT:    lfs f0, -36(r1)
583; NOVSX-NEXT:    lfs f1, -52(r1)
584; NOVSX-NEXT:    lfs f2, -20(r1)
585; NOVSX-NEXT:    fmadds f0, f1, f0, f2
586; NOVSX-NEXT:    lfs f1, -56(r1)
587; NOVSX-NEXT:    lfs f2, -24(r1)
588; NOVSX-NEXT:    stfs f0, -4(r1)
589; NOVSX-NEXT:    lfs f0, -40(r1)
590; NOVSX-NEXT:    fmadds f0, f1, f0, f2
591; NOVSX-NEXT:    lfs f1, -60(r1)
592; NOVSX-NEXT:    lfs f2, -28(r1)
593; NOVSX-NEXT:    stfs f0, -8(r1)
594; NOVSX-NEXT:    lfs f0, -44(r1)
595; NOVSX-NEXT:    fmadds f0, f1, f0, f2
596; NOVSX-NEXT:    lfs f1, -64(r1)
597; NOVSX-NEXT:    lfs f2, -32(r1)
598; NOVSX-NEXT:    stfs f0, -12(r1)
599; NOVSX-NEXT:    lfs f0, -48(r1)
600; NOVSX-NEXT:    fmadds f0, f1, f0, f2
601; NOVSX-NEXT:    stfs f0, -16(r1)
602; NOVSX-NEXT:    lvx v2, 0, r3
603; NOVSX-NEXT:    blr
604  %neg = fneg <4 x float> %vf2
605  %res = call <4 x float> @llvm.experimental.constrained.fma.v4f32(
606                        <4 x float> %vf0, <4 x float> %vf1, <4 x float> %neg,
607                        metadata !"round.dynamic",
608                        metadata !"fpexcept.strict") #0
609  ret <4 x float> %res
610}
611
612define <2 x double> @fmsub_v2f64(<2 x double> %vf0, <2 x double> %vf1, <2 x double> %vf2) #0 {
613; CHECK-LABEL: fmsub_v2f64:
614; CHECK:       # %bb.0:
615; CHECK-NEXT:    xvmsubadp v4, v2, v3
616; CHECK-NEXT:    vmr v2, v4
617; CHECK-NEXT:    blr
618;
619; NOVSX-LABEL: fmsub_v2f64:
620; NOVSX:       # %bb.0:
621; NOVSX-NEXT:    fmsub f2, f2, f4, f6
622; NOVSX-NEXT:    fmsub f1, f1, f3, f5
623; NOVSX-NEXT:    blr
624  %neg = fneg <2 x double> %vf2
625  %res = call <2 x double> @llvm.experimental.constrained.fma.v2f64(
626                        <2 x double> %vf0, <2 x double> %vf1, <2 x double> %neg,
627                        metadata !"round.dynamic",
628                        metadata !"fpexcept.strict") #0
629  ret <2 x double> %res
630}
631
632define float @fnmadd_f32(float %f0, float %f1, float %f2) #0 {
633; CHECK-LABEL: fnmadd_f32:
634; CHECK:       # %bb.0:
635; CHECK-NEXT:    xsnmaddasp f3, f1, f2
636; CHECK-NEXT:    fmr f1, f3
637; CHECK-NEXT:    blr
638;
639; NOVSX-LABEL: fnmadd_f32:
640; NOVSX:       # %bb.0:
641; NOVSX-NEXT:    fnmadds f1, f1, f2, f3
642; NOVSX-NEXT:    blr
643  %fma = call float @llvm.experimental.constrained.fma.f32(
644                        float %f0, float %f1, float %f2,
645                        metadata !"round.dynamic",
646                        metadata !"fpexcept.strict") #0
647  %res = fneg float %fma
648  ret float %res
649}
650
651define double @fnmadd_f64(double %f0, double %f1, double %f2) #0 {
652; CHECK-LABEL: fnmadd_f64:
653; CHECK:       # %bb.0:
654; CHECK-NEXT:    xsnmaddadp f3, f1, f2
655; CHECK-NEXT:    fmr f1, f3
656; CHECK-NEXT:    blr
657;
658; NOVSX-LABEL: fnmadd_f64:
659; NOVSX:       # %bb.0:
660; NOVSX-NEXT:    fnmadd f1, f1, f2, f3
661; NOVSX-NEXT:    blr
662  %fma = call double @llvm.experimental.constrained.fma.f64(
663                        double %f0, double %f1, double %f2,
664                        metadata !"round.dynamic",
665                        metadata !"fpexcept.strict") #0
666  %res = fneg double %fma
667  ret double %res
668}
669
670define <4 x float> @fnmadd_v4f32(<4 x float> %vf0, <4 x float> %vf1, <4 x float> %vf2) #0 {
671; CHECK-LABEL: fnmadd_v4f32:
672; CHECK:       # %bb.0:
673; CHECK-NEXT:    xvmaddasp v4, v2, v3
674; CHECK-NEXT:    xvnegsp v2, v4
675; CHECK-NEXT:    blr
676;
677; NOVSX-LABEL: fnmadd_v4f32:
678; NOVSX:       # %bb.0:
679; NOVSX-NEXT:    addi r3, r1, -32
680; NOVSX-NEXT:    addi r4, r1, -48
681; NOVSX-NEXT:    stvx v4, 0, r3
682; NOVSX-NEXT:    addi r3, r1, -64
683; NOVSX-NEXT:    stvx v3, 0, r4
684; NOVSX-NEXT:    stvx v2, 0, r3
685; NOVSX-NEXT:    vspltisb v2, -1
686; NOVSX-NEXT:    addi r3, r1, -16
687; NOVSX-NEXT:    lfs f0, -20(r1)
688; NOVSX-NEXT:    lfs f1, -36(r1)
689; NOVSX-NEXT:    lfs f2, -52(r1)
690; NOVSX-NEXT:    vslw v2, v2, v2
691; NOVSX-NEXT:    fmadds f0, f2, f1, f0
692; NOVSX-NEXT:    lfs f1, -40(r1)
693; NOVSX-NEXT:    lfs f2, -56(r1)
694; NOVSX-NEXT:    stfs f0, -4(r1)
695; NOVSX-NEXT:    lfs f0, -24(r1)
696; NOVSX-NEXT:    fmadds f0, f2, f1, f0
697; NOVSX-NEXT:    lfs f1, -44(r1)
698; NOVSX-NEXT:    lfs f2, -60(r1)
699; NOVSX-NEXT:    stfs f0, -8(r1)
700; NOVSX-NEXT:    lfs f0, -28(r1)
701; NOVSX-NEXT:    fmadds f0, f2, f1, f0
702; NOVSX-NEXT:    lfs f1, -48(r1)
703; NOVSX-NEXT:    lfs f2, -64(r1)
704; NOVSX-NEXT:    stfs f0, -12(r1)
705; NOVSX-NEXT:    lfs f0, -32(r1)
706; NOVSX-NEXT:    fmadds f0, f2, f1, f0
707; NOVSX-NEXT:    stfs f0, -16(r1)
708; NOVSX-NEXT:    lvx v3, 0, r3
709; NOVSX-NEXT:    vsubfp v2, v2, v3
710; NOVSX-NEXT:    blr
711  %fma = call <4 x float> @llvm.experimental.constrained.fma.v4f32(
712                        <4 x float> %vf0, <4 x float> %vf1, <4 x float> %vf2,
713                        metadata !"round.dynamic",
714                        metadata !"fpexcept.strict") #0
715  %res = fneg <4 x float> %fma
716  ret <4 x float> %res
717}
718
719define <2 x double> @fnmadd_v2f64(<2 x double> %vf0, <2 x double> %vf1, <2 x double> %vf2) #0 {
720; CHECK-LABEL: fnmadd_v2f64:
721; CHECK:       # %bb.0:
722; CHECK-NEXT:    xvnmaddadp v4, v2, v3
723; CHECK-NEXT:    vmr v2, v4
724; CHECK-NEXT:    blr
725;
726; NOVSX-LABEL: fnmadd_v2f64:
727; NOVSX:       # %bb.0:
728; NOVSX-NEXT:    fnmadd f2, f2, f4, f6
729; NOVSX-NEXT:    fnmadd f1, f1, f3, f5
730; NOVSX-NEXT:    blr
731  %fma = call <2 x double> @llvm.experimental.constrained.fma.v2f64(
732                        <2 x double> %vf0, <2 x double> %vf1, <2 x double> %vf2,
733                        metadata !"round.dynamic",
734                        metadata !"fpexcept.strict") #0
735  %res = fneg <2 x double> %fma
736  ret <2 x double> %res
737}
738
739define float @fnmsub_f32(float %f0, float %f1, float %f2) #0 {
740; CHECK-LABEL: fnmsub_f32:
741; CHECK:       # %bb.0:
742; CHECK-NEXT:    xsnmsubasp f3, f1, f2
743; CHECK-NEXT:    fmr f1, f3
744; CHECK-NEXT:    blr
745;
746; NOVSX-LABEL: fnmsub_f32:
747; NOVSX:       # %bb.0:
748; NOVSX-NEXT:    fnmsubs f1, f1, f2, f3
749; NOVSX-NEXT:    blr
750  %neg = fneg float %f2
751  %fma = call float @llvm.experimental.constrained.fma.f32(
752                        float %f0, float %f1, float %neg,
753                        metadata !"round.dynamic",
754                        metadata !"fpexcept.strict") #0
755  %res = fneg float %fma
756  ret float %res
757}
758
759define double @fnmsub_f64(double %f0, double %f1, double %f2) #0 {
760; CHECK-LABEL: fnmsub_f64:
761; CHECK:       # %bb.0:
762; CHECK-NEXT:    xsnmsubadp f3, f1, f2
763; CHECK-NEXT:    fmr f1, f3
764; CHECK-NEXT:    blr
765;
766; NOVSX-LABEL: fnmsub_f64:
767; NOVSX:       # %bb.0:
768; NOVSX-NEXT:    fnmsub f1, f1, f2, f3
769; NOVSX-NEXT:    blr
770  %neg = fneg double %f2
771  %fma = call double @llvm.experimental.constrained.fma.f64(
772                        double %f0, double %f1, double %neg,
773                        metadata !"round.dynamic",
774                        metadata !"fpexcept.strict") #0
775  %res = fneg double %fma
776  ret double %res
777}
778
779define <4 x float> @fnmsub_v4f32(<4 x float> %vf0, <4 x float> %vf1, <4 x float> %vf2) #0 {
780; CHECK-LABEL: fnmsub_v4f32:
781; CHECK:       # %bb.0:
782; CHECK-NEXT:    xvnmsubasp v4, v2, v3
783; CHECK-NEXT:    vmr v2, v4
784; CHECK-NEXT:    blr
785;
786; NOVSX-LABEL: fnmsub_v4f32:
787; NOVSX:       # %bb.0:
788; NOVSX-NEXT:    vspltisb v5, -1
789; NOVSX-NEXT:    addi r3, r1, -48
790; NOVSX-NEXT:    addi r4, r1, -64
791; NOVSX-NEXT:    stvx v3, 0, r3
792; NOVSX-NEXT:    addi r3, r1, -32
793; NOVSX-NEXT:    stvx v2, 0, r4
794; NOVSX-NEXT:    vslw v5, v5, v5
795; NOVSX-NEXT:    vsubfp v4, v5, v4
796; NOVSX-NEXT:    stvx v4, 0, r3
797; NOVSX-NEXT:    addi r3, r1, -16
798; NOVSX-NEXT:    lfs f0, -36(r1)
799; NOVSX-NEXT:    lfs f1, -52(r1)
800; NOVSX-NEXT:    lfs f2, -20(r1)
801; NOVSX-NEXT:    fmadds f0, f1, f0, f2
802; NOVSX-NEXT:    lfs f1, -56(r1)
803; NOVSX-NEXT:    lfs f2, -24(r1)
804; NOVSX-NEXT:    stfs f0, -4(r1)
805; NOVSX-NEXT:    lfs f0, -40(r1)
806; NOVSX-NEXT:    fmadds f0, f1, f0, f2
807; NOVSX-NEXT:    lfs f1, -60(r1)
808; NOVSX-NEXT:    lfs f2, -28(r1)
809; NOVSX-NEXT:    stfs f0, -8(r1)
810; NOVSX-NEXT:    lfs f0, -44(r1)
811; NOVSX-NEXT:    fmadds f0, f1, f0, f2
812; NOVSX-NEXT:    lfs f1, -64(r1)
813; NOVSX-NEXT:    lfs f2, -32(r1)
814; NOVSX-NEXT:    stfs f0, -12(r1)
815; NOVSX-NEXT:    lfs f0, -48(r1)
816; NOVSX-NEXT:    fmadds f0, f1, f0, f2
817; NOVSX-NEXT:    stfs f0, -16(r1)
818; NOVSX-NEXT:    lvx v2, 0, r3
819; NOVSX-NEXT:    vsubfp v2, v5, v2
820; NOVSX-NEXT:    blr
821  %neg = fneg <4 x float> %vf2
822  %fma = call <4 x float> @llvm.experimental.constrained.fma.v4f32(
823                        <4 x float> %vf0, <4 x float> %vf1, <4 x float> %neg,
824                        metadata !"round.dynamic",
825                        metadata !"fpexcept.strict") #0
826  %res = fneg <4 x float> %fma
827  ret <4 x float> %res
828}
829
830define <2 x double> @fnmsub_v2f64(<2 x double> %vf0, <2 x double> %vf1, <2 x double> %vf2) #0 {
831; CHECK-LABEL: fnmsub_v2f64:
832; CHECK:       # %bb.0:
833; CHECK-NEXT:    xvnmsubadp v4, v2, v3
834; CHECK-NEXT:    vmr v2, v4
835; CHECK-NEXT:    blr
836;
837; NOVSX-LABEL: fnmsub_v2f64:
838; NOVSX:       # %bb.0:
839; NOVSX-NEXT:    fnmsub f2, f2, f4, f6
840; NOVSX-NEXT:    fnmsub f1, f1, f3, f5
841; NOVSX-NEXT:    blr
842  %neg = fneg <2 x double> %vf2
843  %fma = call <2 x double> @llvm.experimental.constrained.fma.v2f64(
844                        <2 x double> %vf0, <2 x double> %vf1, <2 x double> %neg,
845                        metadata !"round.dynamic",
846                        metadata !"fpexcept.strict") #0
847  %res = fneg <2 x double> %fma
848  ret <2 x double> %res
849}
850
851define float @fsqrt_f32(float %f1) #0 {
852; CHECK-LABEL: fsqrt_f32:
853; CHECK:       # %bb.0:
854; CHECK-NEXT:    xssqrtsp f1, f1
855; CHECK-NEXT:    blr
856;
857; NOVSX-LABEL: fsqrt_f32:
858; NOVSX:       # %bb.0:
859; NOVSX-NEXT:    fsqrts f1, f1
860; NOVSX-NEXT:    blr
861  %res = call float @llvm.experimental.constrained.sqrt.f32(
862                        float %f1,
863                        metadata !"round.dynamic",
864                        metadata !"fpexcept.strict") #0
865  ret float %res
866}
867
868define double @fsqrt_f64(double %f1) #0 {
869; CHECK-LABEL: fsqrt_f64:
870; CHECK:       # %bb.0:
871; CHECK-NEXT:    xssqrtdp f1, f1
872; CHECK-NEXT:    blr
873;
874; NOVSX-LABEL: fsqrt_f64:
875; NOVSX:       # %bb.0:
876; NOVSX-NEXT:    fsqrt f1, f1
877; NOVSX-NEXT:    blr
878  %res = call double @llvm.experimental.constrained.sqrt.f64(
879                        double %f1,
880                        metadata !"round.dynamic",
881                        metadata !"fpexcept.strict") #0
882  ret double %res
883}
884
885define <4 x float> @fsqrt_v4f32(<4 x float> %vf1) #0 {
886; CHECK-LABEL: fsqrt_v4f32:
887; CHECK:       # %bb.0:
888; CHECK-NEXT:    xvsqrtsp v2, v2
889; CHECK-NEXT:    blr
890;
891; NOVSX-LABEL: fsqrt_v4f32:
892; NOVSX:       # %bb.0:
893; NOVSX-NEXT:    addi r3, r1, -32
894; NOVSX-NEXT:    stvx v2, 0, r3
895; NOVSX-NEXT:    addi r3, r1, -16
896; NOVSX-NEXT:    lfs f0, -20(r1)
897; NOVSX-NEXT:    fsqrts f0, f0
898; NOVSX-NEXT:    stfs f0, -4(r1)
899; NOVSX-NEXT:    lfs f0, -24(r1)
900; NOVSX-NEXT:    fsqrts f0, f0
901; NOVSX-NEXT:    stfs f0, -8(r1)
902; NOVSX-NEXT:    lfs f0, -28(r1)
903; NOVSX-NEXT:    fsqrts f0, f0
904; NOVSX-NEXT:    stfs f0, -12(r1)
905; NOVSX-NEXT:    lfs f0, -32(r1)
906; NOVSX-NEXT:    fsqrts f0, f0
907; NOVSX-NEXT:    stfs f0, -16(r1)
908; NOVSX-NEXT:    lvx v2, 0, r3
909; NOVSX-NEXT:    blr
910  %res = call <4 x float> @llvm.experimental.constrained.sqrt.v4f32(
911                        <4 x float> %vf1,
912                        metadata !"round.dynamic",
913                        metadata !"fpexcept.strict") #0
914  ret <4 x float> %res
915}
916
917define <2 x double> @fsqrt_v2f64(<2 x double> %vf1) #0 {
918; CHECK-LABEL: fsqrt_v2f64:
919; CHECK:       # %bb.0:
920; CHECK-NEXT:    xvsqrtdp v2, v2
921; CHECK-NEXT:    blr
922;
923; NOVSX-LABEL: fsqrt_v2f64:
924; NOVSX:       # %bb.0:
925; NOVSX-NEXT:    fsqrt f2, f2
926; NOVSX-NEXT:    fsqrt f1, f1
927; NOVSX-NEXT:    blr
928  %res = call <2 x double> @llvm.experimental.constrained.sqrt.v2f64(
929                        <2 x double> %vf1,
930                        metadata !"round.dynamic",
931                        metadata !"fpexcept.strict") #0
932  ret <2 x double> %res
933}
934
935attributes #0 = { strictfp }
936