blob: 4ed23a364adab9834a378c204fe1372aa8ddea45 [file] [log] [blame]
Richard Sandifordb86a8342013-06-27 09:27:40 +00001; Test 64-bit conditional stores that are presented as selects.
2;
Richard Sandiforda68e6f52013-07-25 08:57:02 +00003; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | FileCheck %s
Richard Sandifordb86a8342013-06-27 09:27:40 +00004
5declare void @foo(i64 *)
6
7; Test with the loaded value first.
8define void @f1(i64 *%ptr, i64 %alt, i32 %limit) {
Stephen Lind24ab202013-07-14 06:24:09 +00009; CHECK-LABEL: f1:
Richard Sandifordb86a8342013-06-27 09:27:40 +000010; CHECK-NOT: %r2
11; CHECK: jl [[LABEL:[^ ]*]]
12; CHECK-NOT: %r2
13; CHECK: stg %r3, 0(%r2)
14; CHECK: [[LABEL]]:
15; CHECK: br %r14
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
20 ret void
21}
22
23; ...and with the loaded value second
24define void @f2(i64 *%ptr, i64 %alt, i32 %limit) {
Stephen Lind24ab202013-07-14 06:24:09 +000025; CHECK-LABEL: f2:
Richard Sandifordb86a8342013-06-27 09:27:40 +000026; CHECK-NOT: %r2
Richard Sandiford3d768e32013-07-31 12:30:20 +000027; CHECK: jhe [[LABEL:[^ ]*]]
Richard Sandifordb86a8342013-06-27 09:27:40 +000028; CHECK-NOT: %r2
29; CHECK: stg %r3, 0(%r2)
30; CHECK: [[LABEL]]:
31; CHECK: br %r14
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
36 ret void
37}
38
39; Check the high end of the aligned STG range.
40define void @f3(i64 *%base, i64 %alt, i32 %limit) {
Stephen Lind24ab202013-07-14 06:24:09 +000041; CHECK-LABEL: f3:
Richard Sandifordb86a8342013-06-27 09:27:40 +000042; CHECK-NOT: %r2
43; CHECK: jl [[LABEL:[^ ]*]]
44; CHECK-NOT: %r2
45; CHECK: stg %r3, 524280(%r2)
46; CHECK: [[LABEL]]:
47; CHECK: br %r14
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
53 ret void
54}
55
56; Check the next doubleword up, which needs separate address logic.
57; Other sequences besides this one would be OK.
58define void @f4(i64 *%base, i64 %alt, i32 %limit) {
Stephen Lind24ab202013-07-14 06:24:09 +000059; CHECK-LABEL: f4:
Richard Sandifordb86a8342013-06-27 09:27:40 +000060; CHECK-NOT: %r2
61; CHECK: jl [[LABEL:[^ ]*]]
62; CHECK-NOT: %r2
63; CHECK: agfi %r2, 524288
64; CHECK: stg %r3, 0(%r2)
65; CHECK: [[LABEL]]:
66; CHECK: br %r14
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
72 ret void
73}
74
75; Check the low end of the STG range.
76define void @f5(i64 *%base, i64 %alt, i32 %limit) {
Stephen Lind24ab202013-07-14 06:24:09 +000077; CHECK-LABEL: f5:
Richard Sandifordb86a8342013-06-27 09:27:40 +000078; CHECK-NOT: %r2
79; CHECK: jl [[LABEL:[^ ]*]]
80; CHECK-NOT: %r2
81; CHECK: stg %r3, -524288(%r2)
82; CHECK: [[LABEL]]:
83; CHECK: br %r14
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
89 ret void
90}
91
92; Check the next doubleword down, which needs separate address logic.
93; Other sequences besides this one would be OK.
94define void @f6(i64 *%base, i64 %alt, i32 %limit) {
Stephen Lind24ab202013-07-14 06:24:09 +000095; CHECK-LABEL: f6:
Richard Sandifordb86a8342013-06-27 09:27:40 +000096; CHECK-NOT: %r2
97; CHECK: jl [[LABEL:[^ ]*]]
98; CHECK-NOT: %r2
99; CHECK: agfi %r2, -524296
100; CHECK: stg %r3, 0(%r2)
101; CHECK: [[LABEL]]:
102; CHECK: br %r14
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
108 ret void
109}
110
111; Check that STG allows an index.
112define void @f7(i64 %base, i64 %index, i64 %alt, i32 %limit) {
Stephen Lind24ab202013-07-14 06:24:09 +0000113; CHECK-LABEL: f7:
Richard Sandifordb86a8342013-06-27 09:27:40 +0000114; CHECK-NOT: %r2
115; CHECK: jl [[LABEL:[^ ]*]]
116; CHECK-NOT: %r2
117; CHECK: stg %r4, 524287(%r3,%r2)
118; CHECK: [[LABEL]]:
119; CHECK: br %r14
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
127 ret void
128}
129
130; Check that volatile loads are not matched.
131define void @f8(i64 *%ptr, i64 %alt, i32 %limit) {
Stephen Lind24ab202013-07-14 06:24:09 +0000132; CHECK-LABEL: f8:
Richard Sandifordb86a8342013-06-27 09:27:40 +0000133; CHECK: lg {{%r[0-5]}}, 0(%r2)
134; CHECK: {{jl|jnl}} [[LABEL:[^ ]*]]
135; CHECK: [[LABEL]]:
136; CHECK: stg {{%r[0-5]}}, 0(%r2)
137; CHECK: br %r14
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
142 ret void
143}
144
145; ...likewise stores. In this case we should have a conditional load into %r3.
146define void @f9(i64 *%ptr, i64 %alt, i32 %limit) {
Stephen Lind24ab202013-07-14 06:24:09 +0000147; CHECK-LABEL: f9:
Richard Sandiford3d768e32013-07-31 12:30:20 +0000148; CHECK: jhe [[LABEL:[^ ]*]]
Richard Sandifordb86a8342013-06-27 09:27:40 +0000149; CHECK: lg %r3, 0(%r2)
150; CHECK: [[LABEL]]:
151; CHECK: stg %r3, 0(%r2)
152; CHECK: br %r14
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
157 ret void
158}
159
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.
164define void @f10(i64 *%ptr, i64 %alt, i32 %limit) {
165; FIXME: should use a normal load instead of CSG.
Stephen Lind24ab202013-07-14 06:24:09 +0000166; CHECK-LABEL: f10:
Richard Sandifordb86a8342013-06-27 09:27:40 +0000167; CHECK: csg {{%r[0-5]}}, {{%r[0-5]}}, 0(%r2)
168; CHECK: {{jl|jnl}} [[LABEL:[^ ]*]]
169; CHECK: [[LABEL]]:
170; CHECK: stg {{%r[0-5]}}, 0(%r2)
171; CHECK: br %r14
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
176 ret void
177}
178
179; ...likewise stores.
180define void @f11(i64 *%ptr, i64 %alt, i32 %limit) {
181; FIXME: should use a normal store instead of CSG.
Stephen Lind24ab202013-07-14 06:24:09 +0000182; CHECK-LABEL: f11:
Richard Sandiford3d768e32013-07-31 12:30:20 +0000183; CHECK: jhe [[LABEL:[^ ]*]]
Richard Sandifordb86a8342013-06-27 09:27:40 +0000184; CHECK: lg %r3, 0(%r2)
185; CHECK: [[LABEL]]:
186; CHECK: csg {{%r[0-5]}}, %r3, 0(%r2)
187; CHECK: br %r14
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
192 ret void
193}
194
195; Try a frame index base.
196define void @f12(i64 %alt, i32 %limit) {
Stephen Lind24ab202013-07-14 06:24:09 +0000197; CHECK-LABEL: f12:
Richard Sandifordb86a8342013-06-27 09:27:40 +0000198; CHECK: brasl %r14, foo@PLT
199; CHECK-NOT: %r15
200; CHECK: jl [[LABEL:[^ ]*]]
201; CHECK-NOT: %r15
202; CHECK: stg {{%r[0-9]+}}, {{[0-9]+}}(%r15)
203; CHECK: [[LABEL]]:
204; CHECK: brasl %r14, foo@PLT
205; CHECK: br %r14
206 %ptr = alloca i64
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)
213 ret void
214}