1 ; Test 64-bit conditional stores that are presented as selects.
3 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
5 declare void @foo(i64 *)
7 ; Test with the loaded value first.
8 define void @f1(i64 *%ptr, i64 %alt, i32 %limit) {
11 ; CHECK: jl [[LABEL:[^ ]*]]
13 ; CHECK: stg %r3, 0(%r2)
16 %cond = icmp ult i32 %limit, 42
17 %orig = load i64 *%ptr
18 %res = select i1 %cond, i64 %orig, i64 %alt
19 store i64 %res, i64 *%ptr
23 ; ...and with the loaded value second
24 define void @f2(i64 *%ptr, i64 %alt, i32 %limit) {
27 ; CHECK: jnl [[LABEL:[^ ]*]]
29 ; CHECK: stg %r3, 0(%r2)
32 %cond = icmp ult i32 %limit, 42
33 %orig = load i64 *%ptr
34 %res = select i1 %cond, i64 %alt, i64 %orig
35 store i64 %res, i64 *%ptr
39 ; Check the high end of the aligned STG range.
40 define void @f3(i64 *%base, i64 %alt, i32 %limit) {
43 ; CHECK: jl [[LABEL:[^ ]*]]
45 ; CHECK: stg %r3, 524280(%r2)
48 %ptr = getelementptr i64 *%base, i64 65535
49 %cond = icmp ult i32 %limit, 42
50 %orig = load i64 *%ptr
51 %res = select i1 %cond, i64 %orig, i64 %alt
52 store i64 %res, i64 *%ptr
56 ; Check the next doubleword up, which needs separate address logic.
57 ; Other sequences besides this one would be OK.
58 define void @f4(i64 *%base, i64 %alt, i32 %limit) {
61 ; CHECK: jl [[LABEL:[^ ]*]]
63 ; CHECK: agfi %r2, 524288
64 ; CHECK: stg %r3, 0(%r2)
67 %ptr = getelementptr i64 *%base, i64 65536
68 %cond = icmp ult i32 %limit, 42
69 %orig = load i64 *%ptr
70 %res = select i1 %cond, i64 %orig, i64 %alt
71 store i64 %res, i64 *%ptr
75 ; Check the low end of the STG range.
76 define void @f5(i64 *%base, i64 %alt, i32 %limit) {
79 ; CHECK: jl [[LABEL:[^ ]*]]
81 ; CHECK: stg %r3, -524288(%r2)
84 %ptr = getelementptr i64 *%base, i64 -65536
85 %cond = icmp ult i32 %limit, 42
86 %orig = load i64 *%ptr
87 %res = select i1 %cond, i64 %orig, i64 %alt
88 store i64 %res, i64 *%ptr
92 ; Check the next doubleword down, which needs separate address logic.
93 ; Other sequences besides this one would be OK.
94 define void @f6(i64 *%base, i64 %alt, i32 %limit) {
97 ; CHECK: jl [[LABEL:[^ ]*]]
99 ; CHECK: agfi %r2, -524296
100 ; CHECK: stg %r3, 0(%r2)
103 %ptr = getelementptr i64 *%base, i64 -65537
104 %cond = icmp ult i32 %limit, 42
105 %orig = load i64 *%ptr
106 %res = select i1 %cond, i64 %orig, i64 %alt
107 store i64 %res, i64 *%ptr
111 ; Check that STG allows an index.
112 define void @f7(i64 %base, i64 %index, i64 %alt, i32 %limit) {
115 ; CHECK: jl [[LABEL:[^ ]*]]
117 ; CHECK: stg %r4, 524287(%r3,%r2)
120 %add1 = add i64 %base, %index
121 %add2 = add i64 %add1, 524287
122 %ptr = inttoptr i64 %add2 to i64 *
123 %cond = icmp ult i32 %limit, 42
124 %orig = load i64 *%ptr
125 %res = select i1 %cond, i64 %orig, i64 %alt
126 store i64 %res, i64 *%ptr
130 ; Check that volatile loads are not matched.
131 define void @f8(i64 *%ptr, i64 %alt, i32 %limit) {
133 ; CHECK: lg {{%r[0-5]}}, 0(%r2)
134 ; CHECK: {{jl|jnl}} [[LABEL:[^ ]*]]
136 ; CHECK: stg {{%r[0-5]}}, 0(%r2)
138 %cond = icmp ult i32 %limit, 42
139 %orig = load volatile i64 *%ptr
140 %res = select i1 %cond, i64 %orig, i64 %alt
141 store i64 %res, i64 *%ptr
145 ; ...likewise stores. In this case we should have a conditional load into %r3.
146 define void @f9(i64 *%ptr, i64 %alt, i32 %limit) {
148 ; CHECK: jnl [[LABEL:[^ ]*]]
149 ; CHECK: lg %r3, 0(%r2)
151 ; CHECK: stg %r3, 0(%r2)
153 %cond = icmp ult i32 %limit, 42
154 %orig = load i64 *%ptr
155 %res = select i1 %cond, i64 %orig, i64 %alt
156 store volatile i64 %res, i64 *%ptr
160 ; Check that atomic loads are not matched. The transformation is OK for
161 ; the "unordered" case tested here, but since we don't try to handle atomic
162 ; operations at all in this context, it seems better to assert that than
163 ; to restrict the test to a stronger ordering.
164 define void @f10(i64 *%ptr, i64 %alt, i32 %limit) {
165 ; FIXME: should use a normal load instead of CSG.
167 ; CHECK: csg {{%r[0-5]}}, {{%r[0-5]}}, 0(%r2)
168 ; CHECK: {{jl|jnl}} [[LABEL:[^ ]*]]
170 ; CHECK: stg {{%r[0-5]}}, 0(%r2)
172 %cond = icmp ult i32 %limit, 42
173 %orig = load atomic i64 *%ptr unordered, align 8
174 %res = select i1 %cond, i64 %orig, i64 %alt
175 store i64 %res, i64 *%ptr
179 ; ...likewise stores.
180 define void @f11(i64 *%ptr, i64 %alt, i32 %limit) {
181 ; FIXME: should use a normal store instead of CSG.
183 ; CHECK: jnl [[LABEL:[^ ]*]]
184 ; CHECK: lg %r3, 0(%r2)
186 ; CHECK: csg {{%r[0-5]}}, %r3, 0(%r2)
188 %cond = icmp ult i32 %limit, 42
189 %orig = load i64 *%ptr
190 %res = select i1 %cond, i64 %orig, i64 %alt
191 store atomic i64 %res, i64 *%ptr unordered, align 8
195 ; Try a frame index base.
196 define void @f12(i64 %alt, i32 %limit) {
198 ; CHECK: brasl %r14, foo@PLT
200 ; CHECK: jl [[LABEL:[^ ]*]]
202 ; CHECK: stg {{%r[0-9]+}}, {{[0-9]+}}(%r15)
204 ; CHECK: brasl %r14, foo@PLT
207 call void @foo(i64 *%ptr)
208 %cond = icmp ult i32 %limit, 42
209 %orig = load i64 *%ptr
210 %res = select i1 %cond, i64 %orig, i64 %alt
211 store i64 %res, i64 *%ptr
212 call void @foo(i64 *%ptr)