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.fma.f64(double %f1, double %f2, double %f3)
7
8define double @f1(double %f1, double %f2, double %acc) {
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.fma.f64 (double %f1, double %f2, double %acc)
15  ret double %res
16}
17
18define double @f2(double %f1, double *%ptr, double %acc) {
19; CHECK-LABEL: f2:
20; CHECK: madb %f2, %f0, 0(%r2)
21; CHECK: ldr %f0, %f2
22; CHECK: br %r14
23  %f2 = load double, double *%ptr
24  %res = call double @llvm.fma.f64 (double %f1, double %f2, double %acc)
25  ret double %res
26}
27
28define double @f3(double %f1, double *%base, double %acc) {
29; CHECK-LABEL: f3:
30; CHECK: madb %f2, %f0, 4088(%r2)
31; CHECK: ldr %f0, %f2
32; CHECK: br %r14
33  %ptr = getelementptr double, double *%base, i64 511
34  %f2 = load double, double *%ptr
35  %res = call double @llvm.fma.f64 (double %f1, double %f2, double %acc)
36  ret double %res
37}
38
39define double @f4(double %f1, double *%base, double %acc) {
40; The important thing here is that we don't generate an out-of-range
41; displacement.  Other sequences besides this one would be OK.
42;
43; CHECK-LABEL: f4:
44; CHECK: aghi %r2, 4096
45; CHECK: madb %f2, %f0, 0(%r2)
46; CHECK: ldr %f0, %f2
47; CHECK: br %r14
48  %ptr = getelementptr double, double *%base, i64 512
49  %f2 = load double, double *%ptr
50  %res = call double @llvm.fma.f64 (double %f1, double %f2, double %acc)
51  ret double %res
52}
53
54define double @f5(double %f1, double *%base, double %acc) {
55; Here too the important thing is that we don't generate an out-of-range
56; displacement.  Other sequences besides this one would be OK.
57;
58; CHECK-LABEL: f5:
59; CHECK: aghi %r2, -8
60; CHECK: madb %f2, %f0, 0(%r2)
61; CHECK: ldr %f0, %f2
62; CHECK: br %r14
63  %ptr = getelementptr double, double *%base, i64 -1
64  %f2 = load double, double *%ptr
65  %res = call double @llvm.fma.f64 (double %f1, double %f2, double %acc)
66  ret double %res
67}
68
69define double @f6(double %f1, double *%base, i64 %index, double %acc) {
70; CHECK-LABEL: f6:
71; CHECK: sllg %r1, %r3, 3
72; CHECK: madb %f2, %f0, 0(%r1,%r2)
73; CHECK: ldr %f0, %f2
74; CHECK: br %r14
75  %ptr = getelementptr double, double *%base, i64 %index
76  %f2 = load double, double *%ptr
77  %res = call double @llvm.fma.f64 (double %f1, double %f2, double %acc)
78  ret double %res
79}
80
81define double @f7(double %f1, double *%base, i64 %index, double %acc) {
82; CHECK-LABEL: f7:
83; CHECK: sllg %r1, %r3, 3
84; CHECK: madb %f2, %f0, 4088({{%r1,%r2|%r2,%r1}})
85; CHECK: ldr %f0, %f2
86; CHECK: br %r14
87  %index2 = add i64 %index, 511
88  %ptr = getelementptr double, double *%base, i64 %index2
89  %f2 = load double, double *%ptr
90  %res = call double @llvm.fma.f64 (double %f1, double %f2, double %acc)
91  ret double %res
92}
93
94define double @f8(double %f1, double *%base, i64 %index, double %acc) {
95; CHECK-LABEL: f8:
96; CHECK: sllg %r1, %r3, 3
97; CHECK: lay %r1, 4096({{%r1,%r2|%r2,%r1}})
98; CHECK: madb %f2, %f0, 0(%r1)
99; CHECK: ldr %f0, %f2
100; CHECK: br %r14
101  %index2 = add i64 %index, 512
102  %ptr = getelementptr double, double *%base, i64 %index2
103  %f2 = load double, double *%ptr
104  %res = call double @llvm.fma.f64 (double %f1, double %f2, double %acc)
105  ret double %res
106}
107