1; Test f64 conditional stores that are presented as selects.
2;
3; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
4
5declare void @foo(double *)
6
7; Test with the loaded value first.
8define void @f1(double *%ptr, double %alt, i32 %limit) {
9; CHECK-LABEL: f1:
10; CHECK-NOT: %r2
11; CHECK: blr %r14
12; CHECK-NOT: %r2
13; CHECK: std %f0, 0(%r2)
14; CHECK: br %r14
15  %cond = icmp ult i32 %limit, 420
16  %orig = load double , double *%ptr
17  %res = select i1 %cond, double %orig, double %alt
18  store double %res, double *%ptr
19  ret void
20}
21
22; ...and with the loaded value second
23define void @f2(double *%ptr, double %alt, i32 %limit) {
24; CHECK-LABEL: f2:
25; CHECK-NOT: %r2
26; CHECK: bher %r14
27; CHECK-NOT: %r2
28; CHECK: std %f0, 0(%r2)
29; CHECK: br %r14
30  %cond = icmp ult i32 %limit, 420
31  %orig = load double , double *%ptr
32  %res = select i1 %cond, double %alt, double %orig
33  store double %res, double *%ptr
34  ret void
35}
36
37; Check the high end of the aligned STD range.
38define void @f3(double *%base, double %alt, i32 %limit) {
39; CHECK-LABEL: f3:
40; CHECK-NOT: %r2
41; CHECK: blr %r14
42; CHECK-NOT: %r2
43; CHECK: std %f0, 4088(%r2)
44; CHECK: br %r14
45  %ptr = getelementptr double, double *%base, i64 511
46  %cond = icmp ult i32 %limit, 420
47  %orig = load double , double *%ptr
48  %res = select i1 %cond, double %orig, double %alt
49  store double %res, double *%ptr
50  ret void
51}
52
53; Check the next doubleword up, which should use STDY instead of STD.
54define void @f4(double *%base, double %alt, i32 %limit) {
55; CHECK-LABEL: f4:
56; CHECK-NOT: %r2
57; CHECK: blr %r14
58; CHECK-NOT: %r2
59; CHECK: stdy %f0, 4096(%r2)
60; CHECK: br %r14
61  %ptr = getelementptr double, double *%base, i64 512
62  %cond = icmp ult i32 %limit, 420
63  %orig = load double , double *%ptr
64  %res = select i1 %cond, double %orig, double %alt
65  store double %res, double *%ptr
66  ret void
67}
68
69; Check the high end of the aligned STDY range.
70define void @f5(double *%base, double %alt, i32 %limit) {
71; CHECK-LABEL: f5:
72; CHECK-NOT: %r2
73; CHECK: blr %r14
74; CHECK-NOT: %r2
75; CHECK: stdy %f0, 524280(%r2)
76; CHECK: br %r14
77  %ptr = getelementptr double, double *%base, i64 65535
78  %cond = icmp ult i32 %limit, 420
79  %orig = load double , double *%ptr
80  %res = select i1 %cond, double %orig, double %alt
81  store double %res, double *%ptr
82  ret void
83}
84
85; Check the next doubleword up, which needs separate address logic.
86; Other sequences besides this one would be OK.
87define void @f6(double *%base, double %alt, i32 %limit) {
88; CHECK-LABEL: f6:
89; CHECK-NOT: %r2
90; CHECK: blr %r14
91; CHECK-NOT: %r2
92; CHECK: agfi %r2, 524288
93; CHECK: std %f0, 0(%r2)
94; CHECK: br %r14
95  %ptr = getelementptr double, double *%base, i64 65536
96  %cond = icmp ult i32 %limit, 420
97  %orig = load double , double *%ptr
98  %res = select i1 %cond, double %orig, double %alt
99  store double %res, double *%ptr
100  ret void
101}
102
103; Check the low end of the STDY range.
104define void @f7(double *%base, double %alt, i32 %limit) {
105; CHECK-LABEL: f7:
106; CHECK-NOT: %r2
107; CHECK: blr %r14
108; CHECK-NOT: %r2
109; CHECK: stdy %f0, -524288(%r2)
110; CHECK: br %r14
111  %ptr = getelementptr double, double *%base, i64 -65536
112  %cond = icmp ult i32 %limit, 420
113  %orig = load double , double *%ptr
114  %res = select i1 %cond, double %orig, double %alt
115  store double %res, double *%ptr
116  ret void
117}
118
119; Check the next doubleword down, which needs separate address logic.
120; Other sequences besides this one would be OK.
121define void @f8(double *%base, double %alt, i32 %limit) {
122; CHECK-LABEL: f8:
123; CHECK-NOT: %r2
124; CHECK: blr %r14
125; CHECK-NOT: %r2
126; CHECK: agfi %r2, -524296
127; CHECK: std %f0, 0(%r2)
128; CHECK: br %r14
129  %ptr = getelementptr double, double *%base, i64 -65537
130  %cond = icmp ult i32 %limit, 420
131  %orig = load double , double *%ptr
132  %res = select i1 %cond, double %orig, double %alt
133  store double %res, double *%ptr
134  ret void
135}
136
137; Check that STDY allows an index.
138define void @f9(i64 %base, i64 %index, double %alt, i32 %limit) {
139; CHECK-LABEL: f9:
140; CHECK-NOT: %r2
141; CHECK: blr %r14
142; CHECK-NOT: %r2
143; CHECK: stdy %f0, 524287(%r3,%r2)
144; CHECK: br %r14
145  %add1 = add i64 %base, %index
146  %add2 = add i64 %add1, 524287
147  %ptr = inttoptr i64 %add2 to double *
148  %cond = icmp ult i32 %limit, 420
149  %orig = load double , double *%ptr
150  %res = select i1 %cond, double %orig, double %alt
151  store double %res, double *%ptr
152  ret void
153}
154
155; Check that volatile loads are not matched.
156define void @f10(double *%ptr, double %alt, i32 %limit) {
157; CHECK-LABEL: f10:
158; CHECK: ld {{%f[0-5]}}, 0(%r2)
159; CHECK: {{jl|jnl}} [[LABEL:[^ ]*]]
160; CHECK: [[LABEL]]:
161; CHECK: std {{%f[0-5]}}, 0(%r2)
162; CHECK: br %r14
163  %cond = icmp ult i32 %limit, 420
164  %orig = load volatile double , double *%ptr
165  %res = select i1 %cond, double %orig, double %alt
166  store double %res, double *%ptr
167  ret void
168}
169
170; ...likewise stores.  In this case we should have a conditional load into %f0.
171define void @f11(double *%ptr, double %alt, i32 %limit) {
172; CHECK-LABEL: f11:
173; CHECK: jhe [[LABEL:[^ ]*]]
174; CHECK: ld %f0, 0(%r2)
175; CHECK: [[LABEL]]:
176; CHECK: std %f0, 0(%r2)
177; CHECK: br %r14
178  %cond = icmp ult i32 %limit, 420
179  %orig = load double , double *%ptr
180  %res = select i1 %cond, double %orig, double %alt
181  store volatile double %res, double *%ptr
182  ret void
183}
184
185; Try a frame index base.
186define void @f12(double %alt, i32 %limit) {
187; CHECK-LABEL: f12:
188; CHECK: brasl %r14, foo@PLT
189; CHECK-NOT: %r15
190; CHECK: jl [[LABEL:[^ ]*]]
191; CHECK-NOT: %r15
192; CHECK: std {{%f[0-9]+}}, {{[0-9]+}}(%r15)
193; CHECK: [[LABEL]]:
194; CHECK: brasl %r14, foo@PLT
195; CHECK: br %r14
196  %ptr = alloca double
197  call void @foo(double *%ptr)
198  %cond = icmp ult i32 %limit, 420
199  %orig = load double , double *%ptr
200  %res = select i1 %cond, double %orig, double %alt
201  store double %res, double *%ptr
202  call void @foo(double *%ptr)
203  ret void
204}
205