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