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