• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
12define 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.
23define 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.
36define 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.
49define 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.
62define 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.
75define 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.
86define 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.
99define 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.
112define 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.
125define 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.
138define 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.
149define 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.
162define 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.
175define 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.
186define 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.
197define 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.
208define 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.
219define 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.
230define 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.
242define 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.
252define 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.
262define 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.
275define 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.
286define 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.
297define 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.
308define 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.
319define 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.
330define 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.
341define 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.
352define 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.
363define 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.
374define 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.
385define 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.
396define 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.
406define 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 }
418