1; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 \
2; RUN:   | FileCheck -check-prefix=CHECK -check-prefix=CHECK-SCALAR %s
3; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z14 \
4; RUN:   | FileCheck -check-prefix=CHECK -check-prefix=CHECK-VECTOR %s
5
6declare float @llvm.experimental.constrained.fma.f32(float %f1, float %f2, float %f3, metadata, metadata)
7
8define float @f1(float %f1, float %f2, float %acc) #0 {
9; CHECK-LABEL: f1:
10; CHECK-SCALAR: msebr %f4, %f0, %f2
11; CHECK-SCALAR: ler %f0, %f4
12; CHECK-VECTOR: wfmssb %f0, %f0, %f2, %f4
13; CHECK: br %r14
14  %negacc = fneg float %acc
15  %res = call float @llvm.experimental.constrained.fma.f32 (
16                        float %f1, float %f2, float %negacc,
17                        metadata !"round.dynamic",
18                        metadata !"fpexcept.strict") #0
19  ret float %res
20}
21
22define float @f2(float %f1, float *%ptr, float %acc) #0 {
23; CHECK-LABEL: f2:
24; CHECK: mseb %f2, %f0, 0(%r2)
25; CHECK-SCALAR: ler %f0, %f2
26; CHECK-VECTOR: ldr %f0, %f2
27; CHECK: br %r14
28  %f2 = load float, float *%ptr
29  %negacc = fneg float %acc
30  %res = call float @llvm.experimental.constrained.fma.f32 (
31                        float %f1, float %f2, float %negacc,
32                        metadata !"round.dynamic",
33                        metadata !"fpexcept.strict") #0
34  ret float %res
35}
36
37define float @f3(float %f1, float *%base, float %acc) #0 {
38; CHECK-LABEL: f3:
39; CHECK: mseb %f2, %f0, 4092(%r2)
40; CHECK-SCALAR: ler %f0, %f2
41; CHECK-VECTOR: ldr %f0, %f2
42; CHECK: br %r14
43  %ptr = getelementptr float, float *%base, i64 1023
44  %f2 = load float, float *%ptr
45  %negacc = fneg float %acc
46  %res = call float @llvm.experimental.constrained.fma.f32 (
47                        float %f1, float %f2, float %negacc,
48                        metadata !"round.dynamic",
49                        metadata !"fpexcept.strict") #0
50  ret float %res
51}
52
53define float @f4(float %f1, float *%base, float %acc) #0 {
54; The important thing here is that we don't generate an out-of-range
55; displacement.  Other sequences besides this one would be OK.
56;
57; CHECK-LABEL: f4:
58; CHECK: aghi %r2, 4096
59; CHECK: mseb %f2, %f0, 0(%r2)
60; CHECK-SCALAR: ler %f0, %f2
61; CHECK-VECTOR: ldr %f0, %f2
62; CHECK: br %r14
63  %ptr = getelementptr float, float *%base, i64 1024
64  %f2 = load float, float *%ptr
65  %negacc = fneg float %acc
66  %res = call float @llvm.experimental.constrained.fma.f32 (
67                        float %f1, float %f2, float %negacc,
68                        metadata !"round.dynamic",
69                        metadata !"fpexcept.strict") #0
70  ret float %res
71}
72
73define float @f5(float %f1, float *%base, float %acc) #0 {
74; Here too the important thing is that we don't generate an out-of-range
75; displacement.  Other sequences besides this one would be OK.
76;
77; CHECK-LABEL: f5:
78; CHECK: aghi %r2, -4
79; CHECK: mseb %f2, %f0, 0(%r2)
80; CHECK-SCALAR: ler %f0, %f2
81; CHECK-VECTOR: ldr %f0, %f2
82; CHECK: br %r14
83  %ptr = getelementptr float, float *%base, i64 -1
84  %f2 = load float, float *%ptr
85  %negacc = fneg float %acc
86  %res = call float @llvm.experimental.constrained.fma.f32 (
87                        float %f1, float %f2, float %negacc,
88                        metadata !"round.dynamic",
89                        metadata !"fpexcept.strict") #0
90  ret float %res
91}
92
93define float @f6(float %f1, float *%base, i64 %index, float %acc) #0 {
94; CHECK-LABEL: f6:
95; CHECK: sllg %r1, %r3, 2
96; CHECK: mseb %f2, %f0, 0(%r1,%r2)
97; CHECK-SCALAR: ler %f0, %f2
98; CHECK-VECTOR: ldr %f0, %f2
99; CHECK: br %r14
100  %ptr = getelementptr float, float *%base, i64 %index
101  %f2 = load float, float *%ptr
102  %negacc = fneg float %acc
103  %res = call float @llvm.experimental.constrained.fma.f32 (
104                        float %f1, float %f2, float %negacc,
105                        metadata !"round.dynamic",
106                        metadata !"fpexcept.strict") #0
107  ret float %res
108}
109
110define float @f7(float %f1, float *%base, i64 %index, float %acc) #0 {
111; CHECK-LABEL: f7:
112; CHECK: sllg %r1, %r3, 2
113; CHECK: mseb %f2, %f0, 4092({{%r1,%r2|%r2,%r1}})
114; CHECK-SCALAR: ler %f0, %f2
115; CHECK-VECTOR: ldr %f0, %f2
116; CHECK: br %r14
117  %index2 = add i64 %index, 1023
118  %ptr = getelementptr float, float *%base, i64 %index2
119  %f2 = load float, float *%ptr
120  %negacc = fneg float %acc
121  %res = call float @llvm.experimental.constrained.fma.f32 (
122                        float %f1, float %f2, float %negacc,
123                        metadata !"round.dynamic",
124                        metadata !"fpexcept.strict") #0
125  ret float %res
126}
127
128define float @f8(float %f1, float *%base, i64 %index, float %acc) #0 {
129; CHECK-LABEL: f8:
130; CHECK: sllg %r1, %r3, 2
131; CHECK: lay %r1, 4096({{%r1,%r2|%r2,%r1}})
132; CHECK: mseb %f2, %f0, 0(%r1)
133; CHECK-SCALAR: ler %f0, %f2
134; CHECK-VECTOR: ldr %f0, %f2
135; CHECK: br %r14
136  %index2 = add i64 %index, 1024
137  %ptr = getelementptr float, float *%base, i64 %index2
138  %f2 = load float, float *%ptr
139  %negacc = fneg float %acc
140  %res = call float @llvm.experimental.constrained.fma.f32 (
141                        float %f1, float %f2, float %negacc,
142                        metadata !"round.dynamic",
143                        metadata !"fpexcept.strict") #0
144  ret float %res
145}
146
147attributes #0 = { strictfp }
148