1 ; Test load/store pairs that act as memcpys.
3 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
9 @g5 = external global fp128, align 16
11 ; Test the simple i8 case.
12 define void @f1(i8 *%ptr1) {
14 ; CHECK: mvc 1(1,%r2), 0(%r2)
16 %ptr2 = getelementptr i8 *%ptr1, i64 1
18 store i8 %val, i8 *%ptr2
22 ; Test i8 cases where the value is zero-extended to 32 bits.
23 define void @f2(i8 *%ptr1) {
25 ; CHECK: mvc 1(1,%r2), 0(%r2)
27 %ptr2 = getelementptr i8 *%ptr1, i64 1
29 %ext = zext i8 %val to i32
30 %trunc = trunc i32 %ext to i8
31 store i8 %trunc, i8 *%ptr2
35 ; Test i8 cases where the value is zero-extended to 64 bits.
36 define void @f3(i8 *%ptr1) {
38 ; CHECK: mvc 1(1,%r2), 0(%r2)
40 %ptr2 = getelementptr i8 *%ptr1, i64 1
42 %ext = zext i8 %val to i64
43 %trunc = trunc i64 %ext to i8
44 store i8 %trunc, i8 *%ptr2
48 ; Test i8 cases where the value is sign-extended to 32 bits.
49 define void @f4(i8 *%ptr1) {
51 ; CHECK: mvc 1(1,%r2), 0(%r2)
53 %ptr2 = getelementptr i8 *%ptr1, i64 1
55 %ext = sext i8 %val to i32
56 %trunc = trunc i32 %ext to i8
57 store i8 %trunc, i8 *%ptr2
61 ; Test i8 cases where the value is sign-extended to 64 bits.
62 define void @f5(i8 *%ptr1) {
64 ; CHECK: mvc 1(1,%r2), 0(%r2)
66 %ptr2 = getelementptr i8 *%ptr1, i64 1
68 %ext = sext i8 %val to i64
69 %trunc = trunc i64 %ext to i8
70 store i8 %trunc, i8 *%ptr2
74 ; Test the simple i16 case.
75 define void @f6(i16 *%ptr1) {
77 ; CHECK: mvc 2(2,%r2), 0(%r2)
79 %ptr2 = getelementptr i16 *%ptr1, i64 1
80 %val = load i16 *%ptr1
81 store i16 %val, i16 *%ptr2
85 ; Test i16 cases where the value is zero-extended to 32 bits.
86 define void @f7(i16 *%ptr1) {
88 ; CHECK: mvc 2(2,%r2), 0(%r2)
90 %ptr2 = getelementptr i16 *%ptr1, i64 1
91 %val = load i16 *%ptr1
92 %ext = zext i16 %val to i32
93 %trunc = trunc i32 %ext to i16
94 store i16 %trunc, i16 *%ptr2
98 ; Test i16 cases where the value is zero-extended to 64 bits.
99 define void @f8(i16 *%ptr1) {
101 ; CHECK: mvc 2(2,%r2), 0(%r2)
103 %ptr2 = getelementptr i16 *%ptr1, i64 1
104 %val = load i16 *%ptr1
105 %ext = zext i16 %val to i64
106 %trunc = trunc i64 %ext to i16
107 store i16 %trunc, i16 *%ptr2
111 ; Test i16 cases where the value is sign-extended to 32 bits.
112 define void @f9(i16 *%ptr1) {
114 ; CHECK: mvc 2(2,%r2), 0(%r2)
116 %ptr2 = getelementptr i16 *%ptr1, i64 1
117 %val = load i16 *%ptr1
118 %ext = sext i16 %val to i32
119 %trunc = trunc i32 %ext to i16
120 store i16 %trunc, i16 *%ptr2
124 ; Test i16 cases where the value is sign-extended to 64 bits.
125 define void @f10(i16 *%ptr1) {
127 ; CHECK: mvc 2(2,%r2), 0(%r2)
129 %ptr2 = getelementptr i16 *%ptr1, i64 1
130 %val = load i16 *%ptr1
131 %ext = sext i16 %val to i64
132 %trunc = trunc i64 %ext to i16
133 store i16 %trunc, i16 *%ptr2
137 ; Test the simple i32 case.
138 define void @f11(i32 *%ptr1) {
140 ; CHECK: mvc 4(4,%r2), 0(%r2)
142 %ptr2 = getelementptr i32 *%ptr1, i64 1
143 %val = load i32 *%ptr1
144 store i32 %val, i32 *%ptr2
148 ; Test i32 cases where the value is zero-extended to 64 bits.
149 define void @f12(i32 *%ptr1) {
151 ; CHECK: mvc 4(4,%r2), 0(%r2)
153 %ptr2 = getelementptr i32 *%ptr1, i64 1
154 %val = load i32 *%ptr1
155 %ext = zext i32 %val to i64
156 %trunc = trunc i64 %ext to i32
157 store i32 %trunc, i32 *%ptr2
161 ; Test i32 cases where the value is sign-extended to 64 bits.
162 define void @f13(i32 *%ptr1) {
164 ; CHECK: mvc 4(4,%r2), 0(%r2)
166 %ptr2 = getelementptr i32 *%ptr1, i64 1
167 %val = load i32 *%ptr1
168 %ext = sext i32 %val to i64
169 %trunc = trunc i64 %ext to i32
170 store i32 %trunc, i32 *%ptr2
175 define void @f14(i64 *%ptr1) {
177 ; CHECK: mvc 8(8,%r2), 0(%r2)
179 %ptr2 = getelementptr i64 *%ptr1, i64 1
180 %val = load i64 *%ptr1
181 store i64 %val, i64 *%ptr2
186 define void @f15(float *%ptr1) {
188 ; CHECK: mvc 4(4,%r2), 0(%r2)
190 %ptr2 = getelementptr float *%ptr1, i64 1
191 %val = load float *%ptr1
192 store float %val, float *%ptr2
197 define void @f16(double *%ptr1) {
199 ; CHECK: mvc 8(8,%r2), 0(%r2)
201 %ptr2 = getelementptr double *%ptr1, i64 1
202 %val = load double *%ptr1
203 store double %val, double *%ptr2
207 ; Test the f128 case.
208 define void @f17(fp128 *%ptr1) {
210 ; CHECK: mvc 16(16,%r2), 0(%r2)
212 %ptr2 = getelementptr fp128 *%ptr1, i64 1
213 %val = load fp128 *%ptr1
214 store fp128 %val, fp128 *%ptr2
218 ; Make sure that we don't use MVC if the load is volatile.
219 define void @f18(i64 *%ptr1) {
223 %ptr2 = getelementptr i64 *%ptr1, i64 1
224 %val = load volatile i64 *%ptr1
225 store i64 %val, i64 *%ptr2
229 ; ...likewise the store.
230 define void @f19(i64 *%ptr1) {
234 %ptr2 = getelementptr i64 *%ptr1, i64 1
235 %val = load i64 *%ptr1
236 store volatile i64 %val, i64 *%ptr2
240 ; Test that MVC is used for aligned loads and stores, even if there is
241 ; no way of telling whether they alias.
242 define void @f20(i64 *%ptr1, i64 *%ptr2) {
244 ; CHECK: mvc 0(8,%r3), 0(%r2)
246 %val = load i64 *%ptr1
247 store i64 %val, i64 *%ptr2
251 ; ...but if the loads aren't aligned, we can't be sure.
252 define void @f21(i64 *%ptr1, i64 *%ptr2) {
256 %val = load i64 *%ptr1, align 2
257 store i64 %val, i64 *%ptr2, align 2
261 ; Test a case where there is definite overlap.
262 define void @f22(i64 %base) {
266 %add = add i64 %base, 1
267 %ptr1 = inttoptr i64 %base to i64 *
268 %ptr2 = inttoptr i64 %add to i64 *
269 %val = load i64 *%ptr1, align 1
270 store i64 %val, i64 *%ptr2, align 1
274 ; Test that we can use MVC for global addresses for i8.
275 define void @f23(i8 *%ptr) {
277 ; CHECK: larl [[REG:%r[0-5]]], g1
278 ; CHECK: mvc 0(1,%r2), 0([[REG]])
281 store i8 %val, i8 *%ptr
285 ; ...and again with the global on the store.
286 define void @f24(i8 *%ptr) {
288 ; CHECK: larl [[REG:%r[0-5]]], g1
289 ; CHECK: mvc 0(1,[[REG]]), 0(%r2)
292 store i8 %val, i8 *@g1
296 ; Test that we use LHRL for i16.
297 define void @f25(i16 *%ptr) {
299 ; CHECK: lhrl [[REG:%r[0-5]]], g2
300 ; CHECK: sth [[REG]], 0(%r2)
303 store i16 %val, i16 *%ptr
308 define void @f26(i16 *%ptr) {
310 ; CHECK: lh [[REG:%r[0-5]]], 0(%r2)
311 ; CHECK: sthrl [[REG]], g2
313 %val = load i16 *%ptr
314 store i16 %val, i16 *@g2
318 ; Test that we use LRL for i32.
319 define void @f27(i32 *%ptr) {
321 ; CHECK: lrl [[REG:%r[0-5]]], g3
322 ; CHECK: st [[REG]], 0(%r2)
325 store i32 %val, i32 *%ptr
330 define void @f28(i32 *%ptr) {
332 ; CHECK: l [[REG:%r[0-5]]], 0(%r2)
333 ; CHECK: strl [[REG]], g3
335 %val = load i32 *%ptr
336 store i32 %val, i32 *@g3
340 ; Test that we use LGRL for i64.
341 define void @f29(i64 *%ptr) {
343 ; CHECK: lgrl [[REG:%r[0-5]]], g4
344 ; CHECK: stg [[REG]], 0(%r2)
347 store i64 %val, i64 *%ptr
352 define void @f30(i64 *%ptr) {
354 ; CHECK: lg [[REG:%r[0-5]]], 0(%r2)
355 ; CHECK: stgrl [[REG]], g4
357 %val = load i64 *%ptr
358 store i64 %val, i64 *@g4
362 ; Test that we can use MVC for global addresses for fp128.
363 define void @f31(fp128 *%ptr) {
365 ; CHECK: larl [[REG:%r[0-5]]], g5
366 ; CHECK: mvc 0(16,%r2), 0([[REG]])
368 %val = load fp128 *@g5, align 16
369 store fp128 %val, fp128 *%ptr, align 16
373 ; ...and again with the global on the store.
374 define void @f32(fp128 *%ptr) {
376 ; CHECK: larl [[REG:%r[0-5]]], g5
377 ; CHECK: mvc 0(16,[[REG]]), 0(%r2)
379 %val = load fp128 *%ptr, align 16
380 store fp128 %val, fp128 *@g5, align 16
384 ; Test a case where offset disambiguation is enough.
385 define void @f33(i64 *%ptr1) {
387 ; CHECK: mvc 8(8,%r2), 0(%r2)
389 %ptr2 = getelementptr i64 *%ptr1, i64 1
390 %val = load i64 *%ptr1, align 1
391 store i64 %val, i64 *%ptr2, align 1
395 ; Test f21 in cases where TBAA tells us there is no alias.
396 define void @f34(i64 *%ptr1, i64 *%ptr2) {
398 ; CHECK: mvc 0(8,%r3), 0(%r2)
400 %val = load i64 *%ptr1, align 2, !tbaa !1
401 store i64 %val, i64 *%ptr2, align 2, !tbaa !2
405 ; Test f21 in cases where TBAA is present but doesn't help.
406 define void @f35(i64 *%ptr1, i64 *%ptr2) {
410 %val = load i64 *%ptr1, align 2, !tbaa !1
411 store i64 %val, i64 *%ptr2, align 2, !tbaa !1
415 !0 = metadata !{ metadata !"root" }
416 !1 = metadata !{ metadata !"set1", metadata !0 }
417 !2 = metadata !{ metadata !"set2", metadata !0 }