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