1 ; Test 64-bit conditional stores that are presented as selects.
3 ; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | FileCheck %s
5 declare void @foo(i64 *)
7 ; Test with the loaded value first.
8 define void @f1(i64 *%ptr, i64 %alt, i32 %limit) {
13 ; CHECK: stg %r3, 0(%r2)
15 %cond = icmp ult i32 %limit, 420
16 %orig = load i64, i64 *%ptr
17 %res = select i1 %cond, i64 %orig, i64 %alt
18 store i64 %res, i64 *%ptr
22 ; ...and with the loaded value second
23 define void @f2(i64 *%ptr, i64 %alt, i32 %limit) {
28 ; CHECK: stg %r3, 0(%r2)
30 %cond = icmp ult i32 %limit, 420
31 %orig = load i64, i64 *%ptr
32 %res = select i1 %cond, i64 %alt, i64 %orig
33 store i64 %res, i64 *%ptr
37 ; Check the high end of the aligned STG range.
38 define void @f3(i64 *%base, i64 %alt, i32 %limit) {
43 ; CHECK: stg %r3, 524280(%r2)
45 %ptr = getelementptr i64, i64 *%base, i64 65535
46 %cond = icmp ult i32 %limit, 420
47 %orig = load i64, i64 *%ptr
48 %res = select i1 %cond, i64 %orig, i64 %alt
49 store i64 %res, i64 *%ptr
53 ; Check the next doubleword up, which needs separate address logic.
54 ; Other sequences besides this one would be OK.
55 define void @f4(i64 *%base, i64 %alt, i32 %limit) {
60 ; CHECK: agfi %r2, 524288
61 ; CHECK: stg %r3, 0(%r2)
63 %ptr = getelementptr i64, i64 *%base, i64 65536
64 %cond = icmp ult i32 %limit, 420
65 %orig = load i64, i64 *%ptr
66 %res = select i1 %cond, i64 %orig, i64 %alt
67 store i64 %res, i64 *%ptr
71 ; Check the low end of the STG range.
72 define void @f5(i64 *%base, i64 %alt, i32 %limit) {
77 ; CHECK: stg %r3, -524288(%r2)
79 %ptr = getelementptr i64, i64 *%base, i64 -65536
80 %cond = icmp ult i32 %limit, 420
81 %orig = load i64, i64 *%ptr
82 %res = select i1 %cond, i64 %orig, i64 %alt
83 store i64 %res, i64 *%ptr
87 ; Check the next doubleword down, which needs separate address logic.
88 ; Other sequences besides this one would be OK.
89 define void @f6(i64 *%base, i64 %alt, i32 %limit) {
94 ; CHECK: agfi %r2, -524296
95 ; CHECK: stg %r3, 0(%r2)
97 %ptr = getelementptr i64, i64 *%base, i64 -65537
98 %cond = icmp ult i32 %limit, 420
99 %orig = load i64, i64 *%ptr
100 %res = select i1 %cond, i64 %orig, i64 %alt
101 store i64 %res, i64 *%ptr
105 ; Check that STG allows an index.
106 define void @f7(i64 %base, i64 %index, i64 %alt, i32 %limit) {
111 ; CHECK: stg %r4, 524287(%r3,%r2)
113 %add1 = add i64 %base, %index
114 %add2 = add i64 %add1, 524287
115 %ptr = inttoptr i64 %add2 to i64 *
116 %cond = icmp ult i32 %limit, 420
117 %orig = load i64, i64 *%ptr
118 %res = select i1 %cond, i64 %orig, i64 %alt
119 store i64 %res, i64 *%ptr
123 ; Check that volatile loads are not matched.
124 define void @f8(i64 *%ptr, i64 %alt, i32 %limit) {
126 ; CHECK: lg {{%r[0-5]}}, 0(%r2)
127 ; CHECK: {{jl|jnl}} [[LABEL:[^ ]*]]
129 ; CHECK: stg {{%r[0-5]}}, 0(%r2)
131 %cond = icmp ult i32 %limit, 420
132 %orig = load volatile i64, i64 *%ptr
133 %res = select i1 %cond, i64 %orig, i64 %alt
134 store i64 %res, i64 *%ptr
138 ; ...likewise stores. In this case we should have a conditional load into %r3.
139 define void @f9(i64 *%ptr, i64 %alt, i32 %limit) {
141 ; CHECK: jhe [[LABEL:[^ ]*]]
142 ; CHECK: lg %r3, 0(%r2)
144 ; CHECK: stg %r3, 0(%r2)
146 %cond = icmp ult i32 %limit, 420
147 %orig = load i64, i64 *%ptr
148 %res = select i1 %cond, i64 %orig, i64 %alt
149 store volatile i64 %res, i64 *%ptr
153 ; Check that atomic loads are not matched. The transformation is OK for
154 ; the "unordered" case tested here, but since we don't try to handle atomic
155 ; operations at all in this context, it seems better to assert that than
156 ; to restrict the test to a stronger ordering.
157 define void @f10(i64 *%ptr, i64 %alt, i32 %limit) {
158 ; FIXME: should use a normal load instead of CSG.
160 ; CHECK: lg {{%r[0-5]}}, 0(%r2)
161 ; CHECK: {{jl|jnl}} [[LABEL:[^ ]*]]
163 ; CHECK: stg {{%r[0-5]}}, 0(%r2)
165 %cond = icmp ult i32 %limit, 420
166 %orig = load atomic i64, i64 *%ptr unordered, align 8
167 %res = select i1 %cond, i64 %orig, i64 %alt
168 store i64 %res, i64 *%ptr
172 ; ...likewise stores.
173 define void @f11(i64 *%ptr, i64 %alt, i32 %limit) {
174 ; FIXME: should use a normal store instead of CSG.
176 ; CHECK: jhe [[LABEL:[^ ]*]]
177 ; CHECK: lg %r3, 0(%r2)
179 ; CHECK: stg %r3, 0(%r2)
181 %cond = icmp ult i32 %limit, 420
182 %orig = load i64, i64 *%ptr
183 %res = select i1 %cond, i64 %orig, i64 %alt
184 store atomic i64 %res, i64 *%ptr unordered, align 8
188 ; Try a frame index base.
189 define void @f12(i64 %alt, i32 %limit) {
191 ; CHECK: brasl %r14, foo@PLT
193 ; CHECK: jl [[LABEL:[^ ]*]]
195 ; CHECK: stg {{%r[0-9]+}}, {{[0-9]+}}(%r15)
197 ; CHECK: brasl %r14, foo@PLT
200 call void @foo(i64 *%ptr)
201 %cond = icmp ult i32 %limit, 420
202 %orig = load i64, i64 *%ptr
203 %res = select i1 %cond, i64 %orig, i64 %alt
204 store i64 %res, i64 *%ptr
205 call void @foo(i64 *%ptr)