[SystemZ] Improve handling of PC-relative addresses
[oota-llvm.git] / test / CodeGen / SystemZ / memcpy-02.ll
1 ; Test load/store pairs that act as memcpys.
2 ;
3 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
4
5 @g1 = global i8 1
6 @g2 = global i16 2
7 @g3 = global i32 3
8 @g4 = global i64 4
9 @g5 = external global fp128, align 16
10
11 ; Test the simple i8 case.
12 define void @f1(i8 *%ptr1) {
13 ; CHECK-LABEL: f1:
14 ; CHECK: mvc 1(1,%r2), 0(%r2)
15 ; CHECK: br %r14
16   %ptr2 = getelementptr i8 *%ptr1, i64 1
17   %val = load i8 *%ptr1
18   store i8 %val, i8 *%ptr2
19   ret void
20 }
21
22 ; Test i8 cases where the value is zero-extended to 32 bits.
23 define void @f2(i8 *%ptr1) {
24 ; CHECK-LABEL: f2:
25 ; CHECK: mvc 1(1,%r2), 0(%r2)
26 ; CHECK: br %r14
27   %ptr2 = getelementptr i8 *%ptr1, i64 1
28   %val = load i8 *%ptr1
29   %ext = zext i8 %val to i32
30   %trunc = trunc i32 %ext to i8
31   store i8 %trunc, i8 *%ptr2
32   ret void
33 }
34
35 ; Test i8 cases where the value is zero-extended to 64 bits.
36 define void @f3(i8 *%ptr1) {
37 ; CHECK-LABEL: f3:
38 ; CHECK: mvc 1(1,%r2), 0(%r2)
39 ; CHECK: br %r14
40   %ptr2 = getelementptr i8 *%ptr1, i64 1
41   %val = load i8 *%ptr1
42   %ext = zext i8 %val to i64
43   %trunc = trunc i64 %ext to i8
44   store i8 %trunc, i8 *%ptr2
45   ret void
46 }
47
48 ; Test i8 cases where the value is sign-extended to 32 bits.
49 define void @f4(i8 *%ptr1) {
50 ; CHECK-LABEL: f4:
51 ; CHECK: mvc 1(1,%r2), 0(%r2)
52 ; CHECK: br %r14
53   %ptr2 = getelementptr i8 *%ptr1, i64 1
54   %val = load i8 *%ptr1
55   %ext = sext i8 %val to i32
56   %trunc = trunc i32 %ext to i8
57   store i8 %trunc, i8 *%ptr2
58   ret void
59 }
60
61 ; Test i8 cases where the value is sign-extended to 64 bits.
62 define void @f5(i8 *%ptr1) {
63 ; CHECK-LABEL: f5:
64 ; CHECK: mvc 1(1,%r2), 0(%r2)
65 ; CHECK: br %r14
66   %ptr2 = getelementptr i8 *%ptr1, i64 1
67   %val = load i8 *%ptr1
68   %ext = sext i8 %val to i64
69   %trunc = trunc i64 %ext to i8
70   store i8 %trunc, i8 *%ptr2
71   ret void
72 }
73
74 ; Test the simple i16 case.
75 define void @f6(i16 *%ptr1) {
76 ; CHECK-LABEL: f6:
77 ; CHECK: mvc 2(2,%r2), 0(%r2)
78 ; CHECK: br %r14
79   %ptr2 = getelementptr i16 *%ptr1, i64 1
80   %val = load i16 *%ptr1
81   store i16 %val, i16 *%ptr2
82   ret void
83 }
84
85 ; Test i16 cases where the value is zero-extended to 32 bits.
86 define void @f7(i16 *%ptr1) {
87 ; CHECK-LABEL: f7:
88 ; CHECK: mvc 2(2,%r2), 0(%r2)
89 ; CHECK: br %r14
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
95   ret void
96 }
97
98 ; Test i16 cases where the value is zero-extended to 64 bits.
99 define void @f8(i16 *%ptr1) {
100 ; CHECK-LABEL: f8:
101 ; CHECK: mvc 2(2,%r2), 0(%r2)
102 ; CHECK: br %r14
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
108   ret void
109 }
110
111 ; Test i16 cases where the value is sign-extended to 32 bits.
112 define void @f9(i16 *%ptr1) {
113 ; CHECK-LABEL: f9:
114 ; CHECK: mvc 2(2,%r2), 0(%r2)
115 ; CHECK: br %r14
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
121   ret void
122 }
123
124 ; Test i16 cases where the value is sign-extended to 64 bits.
125 define void @f10(i16 *%ptr1) {
126 ; CHECK-LABEL: f10:
127 ; CHECK: mvc 2(2,%r2), 0(%r2)
128 ; CHECK: br %r14
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
134   ret void
135 }
136
137 ; Test the simple i32 case.
138 define void @f11(i32 *%ptr1) {
139 ; CHECK-LABEL: f11:
140 ; CHECK: mvc 4(4,%r2), 0(%r2)
141 ; CHECK: br %r14
142   %ptr2 = getelementptr i32 *%ptr1, i64 1
143   %val = load i32 *%ptr1
144   store i32 %val, i32 *%ptr2
145   ret void
146 }
147
148 ; Test i32 cases where the value is zero-extended to 64 bits.
149 define void @f12(i32 *%ptr1) {
150 ; CHECK-LABEL: f12:
151 ; CHECK: mvc 4(4,%r2), 0(%r2)
152 ; CHECK: br %r14
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
158   ret void
159 }
160
161 ; Test i32 cases where the value is sign-extended to 64 bits.
162 define void @f13(i32 *%ptr1) {
163 ; CHECK-LABEL: f13:
164 ; CHECK: mvc 4(4,%r2), 0(%r2)
165 ; CHECK: br %r14
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
171   ret void
172 }
173
174 ; Test the i64 case.
175 define void @f14(i64 *%ptr1) {
176 ; CHECK-LABEL: f14:
177 ; CHECK: mvc 8(8,%r2), 0(%r2)
178 ; CHECK: br %r14
179   %ptr2 = getelementptr i64 *%ptr1, i64 1
180   %val = load i64 *%ptr1
181   store i64 %val, i64 *%ptr2
182   ret void
183 }
184
185 ; Test the f32 case.
186 define void @f15(float *%ptr1) {
187 ; CHECK-LABEL: f15:
188 ; CHECK: mvc 4(4,%r2), 0(%r2)
189 ; CHECK: br %r14
190   %ptr2 = getelementptr float *%ptr1, i64 1
191   %val = load float *%ptr1
192   store float %val, float *%ptr2
193   ret void
194 }
195
196 ; Test the f64 case.
197 define void @f16(double *%ptr1) {
198 ; CHECK-LABEL: f16:
199 ; CHECK: mvc 8(8,%r2), 0(%r2)
200 ; CHECK: br %r14
201   %ptr2 = getelementptr double *%ptr1, i64 1
202   %val = load double *%ptr1
203   store double %val, double *%ptr2
204   ret void
205 }
206
207 ; Test the f128 case.
208 define void @f17(fp128 *%ptr1) {
209 ; CHECK-LABEL: f17:
210 ; CHECK: mvc 16(16,%r2), 0(%r2)
211 ; CHECK: br %r14
212   %ptr2 = getelementptr fp128 *%ptr1, i64 1
213   %val = load fp128 *%ptr1
214   store fp128 %val, fp128 *%ptr2
215   ret void
216 }
217
218 ; Make sure that we don't use MVC if the load is volatile.
219 define void @f18(i64 *%ptr1) {
220 ; CHECK-LABEL: f18:
221 ; CHECK-NOT: mvc
222 ; CHECK: br %r14
223   %ptr2 = getelementptr i64 *%ptr1, i64 1
224   %val = load volatile i64 *%ptr1
225   store i64 %val, i64 *%ptr2
226   ret void
227 }
228
229 ; ...likewise the store.
230 define void @f19(i64 *%ptr1) {
231 ; CHECK-LABEL: f19:
232 ; CHECK-NOT: mvc
233 ; CHECK: br %r14
234   %ptr2 = getelementptr i64 *%ptr1, i64 1
235   %val = load i64 *%ptr1
236   store volatile i64 %val, i64 *%ptr2
237   ret void
238 }
239
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) {
243 ; CHECK-LABEL: f20:
244 ; CHECK: mvc 0(8,%r3), 0(%r2)
245 ; CHECK: br %r14
246   %val = load i64 *%ptr1
247   store i64 %val, i64 *%ptr2
248   ret void
249 }
250
251 ; ...but if the loads aren't aligned, we can't be sure.
252 define void @f21(i64 *%ptr1, i64 *%ptr2) {
253 ; CHECK-LABEL: f21:
254 ; CHECK-NOT: mvc
255 ; CHECK: br %r14
256   %val = load i64 *%ptr1, align 2
257   store i64 %val, i64 *%ptr2, align 2
258   ret void
259 }
260
261 ; Test a case where there is definite overlap.
262 define void @f22(i64 %base) {
263 ; CHECK-LABEL: f22:
264 ; CHECK-NOT: mvc
265 ; CHECK: br %r14
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
271   ret void
272 }
273
274 ; Test that we can use MVC for global addresses for i8.
275 define void @f23(i8 *%ptr) {
276 ; CHECK-LABEL: f23:
277 ; CHECK: larl [[REG:%r[0-5]]], g1
278 ; CHECK: mvc 0(1,%r2), 0([[REG]])
279 ; CHECK: br %r14
280   %val = load i8 *@g1
281   store i8 %val, i8 *%ptr
282   ret void
283 }
284
285 ; ...and again with the global on the store.
286 define void @f24(i8 *%ptr) {
287 ; CHECK-LABEL: f24:
288 ; CHECK: larl [[REG:%r[0-5]]], g1
289 ; CHECK: mvc 0(1,[[REG]]), 0(%r2)
290 ; CHECK: br %r14
291   %val = load i8 *%ptr
292   store i8 %val, i8 *@g1
293   ret void
294 }
295
296 ; Test that we use LHRL for i16.
297 define void @f25(i16 *%ptr) {
298 ; CHECK-LABEL: f25:
299 ; CHECK: lhrl [[REG:%r[0-5]]], g2
300 ; CHECK: sth [[REG]], 0(%r2)
301 ; CHECK: br %r14
302   %val = load i16 *@g2
303   store i16 %val, i16 *%ptr
304   ret void
305 }
306
307 ; ...likewise STHRL.
308 define void @f26(i16 *%ptr) {
309 ; CHECK-LABEL: f26:
310 ; CHECK: lh [[REG:%r[0-5]]], 0(%r2)
311 ; CHECK: sthrl [[REG]], g2
312 ; CHECK: br %r14
313   %val = load i16 *%ptr
314   store i16 %val, i16 *@g2
315   ret void
316 }
317
318 ; Test that we use LRL for i32.
319 define void @f27(i32 *%ptr) {
320 ; CHECK-LABEL: f27:
321 ; CHECK: lrl [[REG:%r[0-5]]], g3
322 ; CHECK: st [[REG]], 0(%r2)
323 ; CHECK: br %r14
324   %val = load i32 *@g3
325   store i32 %val, i32 *%ptr
326   ret void
327 }
328
329 ; ...likewise STRL.
330 define void @f28(i32 *%ptr) {
331 ; CHECK-LABEL: f28:
332 ; CHECK: l [[REG:%r[0-5]]], 0(%r2)
333 ; CHECK: strl [[REG]], g3
334 ; CHECK: br %r14
335   %val = load i32 *%ptr
336   store i32 %val, i32 *@g3
337   ret void
338 }
339
340 ; Test that we use LGRL for i64.
341 define void @f29(i64 *%ptr) {
342 ; CHECK-LABEL: f29:
343 ; CHECK: lgrl [[REG:%r[0-5]]], g4
344 ; CHECK: stg [[REG]], 0(%r2)
345 ; CHECK: br %r14
346   %val = load i64 *@g4
347   store i64 %val, i64 *%ptr
348   ret void
349 }
350
351 ; ...likewise STGRL.
352 define void @f30(i64 *%ptr) {
353 ; CHECK-LABEL: f30:
354 ; CHECK: lg [[REG:%r[0-5]]], 0(%r2)
355 ; CHECK: stgrl [[REG]], g4
356 ; CHECK: br %r14
357   %val = load i64 *%ptr
358   store i64 %val, i64 *@g4
359   ret void
360 }
361
362 ; Test that we can use MVC for global addresses for fp128.
363 define void @f31(fp128 *%ptr) {
364 ; CHECK-LABEL: f31:
365 ; CHECK: larl [[REG:%r[0-5]]], g5
366 ; CHECK: mvc 0(16,%r2), 0([[REG]])
367 ; CHECK: br %r14
368   %val = load fp128 *@g5, align 16
369   store fp128 %val, fp128 *%ptr, align 16
370   ret void
371 }
372
373 ; ...and again with the global on the store.
374 define void @f32(fp128 *%ptr) {
375 ; CHECK-LABEL: f32:
376 ; CHECK: larl [[REG:%r[0-5]]], g5
377 ; CHECK: mvc 0(16,[[REG]]), 0(%r2)
378 ; CHECK: br %r14
379   %val = load fp128 *%ptr, align 16
380   store fp128 %val, fp128 *@g5, align 16
381   ret void
382 }
383
384 ; Test a case where offset disambiguation is enough.
385 define void @f33(i64 *%ptr1) {
386 ; CHECK-LABEL: f33:
387 ; CHECK: mvc 8(8,%r2), 0(%r2)
388 ; CHECK: br %r14
389   %ptr2 = getelementptr i64 *%ptr1, i64 1
390   %val = load i64 *%ptr1, align 1
391   store i64 %val, i64 *%ptr2, align 1
392   ret void
393 }
394
395 ; Test f21 in cases where TBAA tells us there is no alias.
396 define void @f34(i64 *%ptr1, i64 *%ptr2) {
397 ; CHECK-LABEL: f34:
398 ; CHECK: mvc 0(8,%r3), 0(%r2)
399 ; CHECK: br %r14
400   %val = load i64 *%ptr1, align 2, !tbaa !1
401   store i64 %val, i64 *%ptr2, align 2, !tbaa !2
402   ret void
403 }
404
405 ; Test f21 in cases where TBAA is present but doesn't help.
406 define void @f35(i64 *%ptr1, i64 *%ptr2) {
407 ; CHECK-LABEL: f35:
408 ; CHECK-NOT: mvc
409 ; CHECK: br %r14
410   %val = load i64 *%ptr1, align 2, !tbaa !1
411   store i64 %val, i64 *%ptr2, align 2, !tbaa !1
412   ret void
413 }
414
415 !0 = metadata !{ metadata !"root" }
416 !1 = metadata !{ metadata !"set1", metadata !0 }
417 !2 = metadata !{ metadata !"set2", metadata !0 }