1; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
2
3declare double @llvm.fma.f64(double %f1, double %f2, double %f3)
4
5define double @f1(double %f1, double %f2, double %acc) {
6; CHECK-LABEL: f1:
7; CHECK: msdbr %f4, %f0, %f2
8; CHECK: ldr %f0, %f4
9; CHECK: br %r14
10  %negacc = fsub double -0.0, %acc
11  %res = call double @llvm.fma.f64 (double %f1, double %f2, double %negacc)
12  ret double %res
13}
14
15define double @f2(double %f1, double *%ptr, double %acc) {
16; CHECK-LABEL: f2:
17; CHECK: msdb %f2, %f0, 0(%r2)
18; CHECK: ldr %f0, %f2
19; CHECK: br %r14
20  %f2 = load double *%ptr
21  %negacc = fsub double -0.0, %acc
22  %res = call double @llvm.fma.f64 (double %f1, double %f2, double %negacc)
23  ret double %res
24}
25
26define double @f3(double %f1, double *%base, double %acc) {
27; CHECK-LABEL: f3:
28; CHECK: msdb %f2, %f0, 4088(%r2)
29; CHECK: ldr %f0, %f2
30; CHECK: br %r14
31  %ptr = getelementptr double *%base, i64 511
32  %f2 = load double *%ptr
33  %negacc = fsub double -0.0, %acc
34  %res = call double @llvm.fma.f64 (double %f1, double %f2, double %negacc)
35  ret double %res
36}
37
38define double @f4(double %f1, double *%base, double %acc) {
39; The important thing here is that we don't generate an out-of-range
40; displacement.  Other sequences besides this one would be OK.
41;
42; CHECK-LABEL: f4:
43; CHECK: aghi %r2, 4096
44; CHECK: msdb %f2, %f0, 0(%r2)
45; CHECK: ldr %f0, %f2
46; CHECK: br %r14
47  %ptr = getelementptr double *%base, i64 512
48  %f2 = load double *%ptr
49  %negacc = fsub double -0.0, %acc
50  %res = call double @llvm.fma.f64 (double %f1, double %f2, double %negacc)
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: msdb %f2, %f0, 0(%r2)
61; CHECK: ldr %f0, %f2
62; CHECK: br %r14
63  %ptr = getelementptr double *%base, i64 -1
64  %f2 = load double *%ptr
65  %negacc = fsub double -0.0, %acc
66  %res = call double @llvm.fma.f64 (double %f1, double %f2, double %negacc)
67  ret double %res
68}
69
70define double @f6(double %f1, double *%base, i64 %index, double %acc) {
71; CHECK-LABEL: f6:
72; CHECK: sllg %r1, %r3, 3
73; CHECK: msdb %f2, %f0, 0(%r1,%r2)
74; CHECK: ldr %f0, %f2
75; CHECK: br %r14
76  %ptr = getelementptr double *%base, i64 %index
77  %f2 = load double *%ptr
78  %negacc = fsub double -0.0, %acc
79  %res = call double @llvm.fma.f64 (double %f1, double %f2, double %negacc)
80  ret double %res
81}
82
83define double @f7(double %f1, double *%base, i64 %index, double %acc) {
84; CHECK-LABEL: f7:
85; CHECK: sllg %r1, %r3, 3
86; CHECK: msdb %f2, %f0, 4088({{%r1,%r2|%r2,%r1}})
87; CHECK: ldr %f0, %f2
88; CHECK: br %r14
89  %index2 = add i64 %index, 511
90  %ptr = getelementptr double *%base, i64 %index2
91  %f2 = load double *%ptr
92  %negacc = fsub double -0.0, %acc
93  %res = call double @llvm.fma.f64 (double %f1, double %f2, double %negacc)
94  ret double %res
95}
96
97define double @f8(double %f1, double *%base, i64 %index, double %acc) {
98; CHECK-LABEL: f8:
99; CHECK: sllg %r1, %r3, 3
100; CHECK: lay %r1, 4096({{%r1,%r2|%r2,%r1}})
101; CHECK: msdb %f2, %f0, 0(%r1)
102; CHECK: ldr %f0, %f2
103; CHECK: br %r14
104  %index2 = add i64 %index, 512
105  %ptr = getelementptr double *%base, i64 %index2
106  %f2 = load double *%ptr
107  %negacc = fsub double -0.0, %acc
108  %res = call double @llvm.fma.f64 (double %f1, double %f2, double %negacc)
109  ret double %res
110}
111