[LegalizeVectorTypes] Allow single loads and stores for more short vectors
[oota-llvm.git] / test / CodeGen / SystemZ / and-08.ll
1 ; Test memory-to-memory ANDs.
2 ;
3 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
4
5 @g1src = global i8 1
6 @g1dst = global i8 1
7 @g2src = global i16 2
8 @g2dst = global i16 2
9
10 ; Test the simple i8 case.
11 define void @f1(i8 *%ptr1) {
12 ; CHECK-LABEL: f1:
13 ; CHECK: nc 1(1,%r2), 0(%r2)
14 ; CHECK: br %r14
15   %ptr2 = getelementptr i8, i8 *%ptr1, i64 1
16   %val = load i8 , i8 *%ptr1
17   %old = load i8 , i8 *%ptr2
18   %and = and i8 %val, %old
19   store i8 %and, i8 *%ptr2
20   ret void
21 }
22
23 ; ...and again in reverse.
24 define void @f2(i8 *%ptr1) {
25 ; CHECK-LABEL: f2:
26 ; CHECK: nc 1(1,%r2), 0(%r2)
27 ; CHECK: br %r14
28   %ptr2 = getelementptr i8, i8 *%ptr1, i64 1
29   %val = load i8 , i8 *%ptr1
30   %old = load i8 , i8 *%ptr2
31   %and = and i8 %old, %val
32   store i8 %and, i8 *%ptr2
33   ret void
34 }
35
36 ; Test i8 cases where one value is zero-extended to 32 bits and the other
37 ; sign-extended.
38 define void @f3(i8 *%ptr1) {
39 ; CHECK-LABEL: f3:
40 ; CHECK: nc 1(1,%r2), 0(%r2)
41 ; CHECK: br %r14
42   %ptr2 = getelementptr i8, i8 *%ptr1, i64 1
43   %val = load i8 , i8 *%ptr1
44   %extval = zext i8 %val to i32
45   %old = load i8 , i8 *%ptr2
46   %extold = sext i8 %old to i32
47   %and = and i32 %extval, %extold
48   %trunc = trunc i32 %and to i8
49   store i8 %trunc, i8 *%ptr2
50   ret void
51 }
52
53 ; ...and again with the extension types reversed.
54 define void @f4(i8 *%ptr1) {
55 ; CHECK-LABEL: f4:
56 ; CHECK: nc 1(1,%r2), 0(%r2)
57 ; CHECK: br %r14
58   %ptr2 = getelementptr i8, i8 *%ptr1, i64 1
59   %val = load i8 , i8 *%ptr1
60   %extval = sext i8 %val to i32
61   %old = load i8 , i8 *%ptr2
62   %extold = zext i8 %old to i32
63   %and = and i32 %extval, %extold
64   %trunc = trunc i32 %and to i8
65   store i8 %trunc, i8 *%ptr2
66   ret void
67 }
68
69 ; ...and again with two sign extensions.
70 define void @f5(i8 *%ptr1) {
71 ; CHECK-LABEL: f5:
72 ; CHECK: nc 1(1,%r2), 0(%r2)
73 ; CHECK: br %r14
74   %ptr2 = getelementptr i8, i8 *%ptr1, i64 1
75   %val = load i8 , i8 *%ptr1
76   %extval = sext i8 %val to i32
77   %old = load i8 , i8 *%ptr2
78   %extold = sext i8 %old to i32
79   %and = and i32 %extval, %extold
80   %trunc = trunc i32 %and to i8
81   store i8 %trunc, i8 *%ptr2
82   ret void
83 }
84
85 ; ...and again with two zero extensions.
86 define void @f6(i8 *%ptr1) {
87 ; CHECK-LABEL: f6:
88 ; CHECK: nc 1(1,%r2), 0(%r2)
89 ; CHECK: br %r14
90   %ptr2 = getelementptr i8, i8 *%ptr1, i64 1
91   %val = load i8 , i8 *%ptr1
92   %extval = zext i8 %val to i32
93   %old = load i8 , i8 *%ptr2
94   %extold = zext i8 %old to i32
95   %and = and i32 %extval, %extold
96   %trunc = trunc i32 %and to i8
97   store i8 %trunc, i8 *%ptr2
98   ret void
99 }
100
101 ; Test i8 cases where the value is extended to 64 bits (just one case
102 ; this time).
103 define void @f7(i8 *%ptr1) {
104 ; CHECK-LABEL: f7:
105 ; CHECK: nc 1(1,%r2), 0(%r2)
106 ; CHECK: br %r14
107   %ptr2 = getelementptr i8, i8 *%ptr1, i64 1
108   %val = load i8 , i8 *%ptr1
109   %extval = sext i8 %val to i64
110   %old = load i8 , i8 *%ptr2
111   %extold = zext i8 %old to i64
112   %and = and i64 %extval, %extold
113   %trunc = trunc i64 %and to i8
114   store i8 %trunc, i8 *%ptr2
115   ret void
116 }
117
118 ; Test the simple i16 case.
119 define void @f8(i16 *%ptr1) {
120 ; CHECK-LABEL: f8:
121 ; CHECK: nc 2(2,%r2), 0(%r2)
122 ; CHECK: br %r14
123   %ptr2 = getelementptr i16, i16 *%ptr1, i64 1
124   %val = load i16 , i16 *%ptr1
125   %old = load i16 , i16 *%ptr2
126   %and = and i16 %val, %old
127   store i16 %and, i16 *%ptr2
128   ret void
129 }
130
131 ; Test i16 cases where the value is extended to 32 bits.
132 define void @f9(i16 *%ptr1) {
133 ; CHECK-LABEL: f9:
134 ; CHECK: nc 2(2,%r2), 0(%r2)
135 ; CHECK: br %r14
136   %ptr2 = getelementptr i16, i16 *%ptr1, i64 1
137   %val = load i16 , i16 *%ptr1
138   %extval = zext i16 %val to i32
139   %old = load i16 , i16 *%ptr2
140   %extold = sext i16 %old to i32
141   %and = and i32 %extval, %extold
142   %trunc = trunc i32 %and to i16
143   store i16 %trunc, i16 *%ptr2
144   ret void
145 }
146
147 ; Test i16 cases where the value is extended to 64 bits.
148 define void @f10(i16 *%ptr1) {
149 ; CHECK-LABEL: f10:
150 ; CHECK: nc 2(2,%r2), 0(%r2)
151 ; CHECK: br %r14
152   %ptr2 = getelementptr i16, i16 *%ptr1, i64 1
153   %val = load i16 , i16 *%ptr1
154   %extval = sext i16 %val to i64
155   %old = load i16 , i16 *%ptr2
156   %extold = zext i16 %old to i64
157   %and = and i64 %extval, %extold
158   %trunc = trunc i64 %and to i16
159   store i16 %trunc, i16 *%ptr2
160   ret void
161 }
162
163 ; Test the simple i32 case.
164 define void @f11(i32 *%ptr1) {
165 ; CHECK-LABEL: f11:
166 ; CHECK: nc 4(4,%r2), 0(%r2)
167 ; CHECK: br %r14
168   %ptr2 = getelementptr i32, i32 *%ptr1, i64 1
169   %val = load i32 , i32 *%ptr1
170   %old = load i32 , i32 *%ptr2
171   %and = and i32 %old, %val
172   store i32 %and, i32 *%ptr2
173   ret void
174 }
175
176 ; Test i32 cases where the value is extended to 64 bits.
177 define void @f12(i32 *%ptr1) {
178 ; CHECK-LABEL: f12:
179 ; CHECK: nc 4(4,%r2), 0(%r2)
180 ; CHECK: br %r14
181   %ptr2 = getelementptr i32, i32 *%ptr1, i64 1
182   %val = load i32 , i32 *%ptr1
183   %extval = sext i32 %val to i64
184   %old = load i32 , i32 *%ptr2
185   %extold = zext i32 %old to i64
186   %and = and i64 %extval, %extold
187   %trunc = trunc i64 %and to i32
188   store i32 %trunc, i32 *%ptr2
189   ret void
190 }
191
192 ; Test the i64 case.
193 define void @f13(i64 *%ptr1) {
194 ; CHECK-LABEL: f13:
195 ; CHECK: nc 8(8,%r2), 0(%r2)
196 ; CHECK: br %r14
197   %ptr2 = getelementptr i64, i64 *%ptr1, i64 1
198   %val = load i64 , i64 *%ptr1
199   %old = load i64 , i64 *%ptr2
200   %and = and i64 %old, %val
201   store i64 %and, i64 *%ptr2
202   ret void
203 }
204
205 ; Make sure that we don't use NC if the first load is volatile.
206 define void @f14(i64 *%ptr1) {
207 ; CHECK-LABEL: f14:
208 ; CHECK-NOT: nc
209 ; CHECK: br %r14
210   %ptr2 = getelementptr i64, i64 *%ptr1, i64 1
211   %val = load volatile i64 , i64 *%ptr1
212   %old = load i64 , i64 *%ptr2
213   %and = and i64 %old, %val
214   store i64 %and, i64 *%ptr2
215   ret void
216 }
217
218 ; ...likewise the second.
219 define void @f15(i64 *%ptr1) {
220 ; CHECK-LABEL: f15:
221 ; CHECK-NOT: nc
222 ; CHECK: br %r14
223   %ptr2 = getelementptr i64, i64 *%ptr1, i64 1
224   %val = load i64 , i64 *%ptr1
225   %old = load volatile i64 , i64 *%ptr2
226   %and = and i64 %old, %val
227   store i64 %and, i64 *%ptr2
228   ret void
229 }
230
231 ; ...likewise the store.
232 define void @f16(i64 *%ptr1) {
233 ; CHECK-LABEL: f16:
234 ; CHECK-NOT: nc
235 ; CHECK: br %r14
236   %ptr2 = getelementptr i64, i64 *%ptr1, i64 1
237   %val = load i64 , i64 *%ptr1
238   %old = load i64 , i64 *%ptr2
239   %and = and i64 %old, %val
240   store volatile i64 %and, i64 *%ptr2
241   ret void
242 }
243
244 ; Test that NC is not used for aligned loads and stores if there is
245 ; no way of telling whether they alias.  We don't want to use NC in
246 ; cases where the addresses could be equal.
247 define void @f17(i64 *%ptr1, i64 *%ptr2) {
248 ; CHECK-LABEL: f17:
249 ; CHECK-NOT: nc
250 ; CHECK: br %r14
251   %val = load i64 , i64 *%ptr1
252   %old = load i64 , i64 *%ptr2
253   %and = and i64 %old, %val
254   store i64 %and, i64 *%ptr2
255   ret void
256 }
257
258 ; ...but if one of the loads isn't aligned, we can't be sure.
259 define void @f18(i64 *%ptr1, i64 *%ptr2) {
260 ; CHECK-LABEL: f18:
261 ; CHECK-NOT: nc
262 ; CHECK: br %r14
263   %val = load i64 , i64 *%ptr1, align 2
264   %old = load i64 , i64 *%ptr2
265   %and = and i64 %old, %val
266   store i64 %and, i64 *%ptr2
267   ret void
268 }
269
270 ; Repeat the previous test with the operands in the opposite order.
271 define void @f19(i64 *%ptr1, i64 *%ptr2) {
272 ; CHECK-LABEL: f19:
273 ; CHECK-NOT: nc
274 ; CHECK: br %r14
275   %val = load i64 , i64 *%ptr1, align 2
276   %old = load i64 , i64 *%ptr2
277   %and = and i64 %val, %old
278   store i64 %and, i64 *%ptr2
279   ret void
280 }
281
282 ; ...and again with the other operand being unaligned.
283 define void @f20(i64 *%ptr1, i64 *%ptr2) {
284 ; CHECK-LABEL: f20:
285 ; CHECK-NOT: nc
286 ; CHECK: br %r14
287   %val = load i64 , i64 *%ptr1
288   %old = load i64 , i64 *%ptr2, align 2
289   %and = and i64 %val, %old
290   store i64 %and, i64 *%ptr2, align 2
291   ret void
292 }
293
294 ; Test a case where there is definite overlap.
295 define void @f21(i64 %base) {
296 ; CHECK-LABEL: f21:
297 ; CHECK-NOT: nc
298 ; CHECK: br %r14
299   %add = add i64 %base, 1
300   %ptr1 = inttoptr i64 %base to i64 *
301   %ptr2 = inttoptr i64 %add to i64 *
302   %val = load i64 , i64 *%ptr1
303   %old = load i64 , i64 *%ptr2, align 1
304   %and = and i64 %old, %val
305   store i64 %and, i64 *%ptr2, align 1
306   ret void
307 }
308
309 ; Test that we can use NC for global addresses for i8.
310 define void @f22(i8 *%ptr) {
311 ; CHECK-LABEL: f22:
312 ; CHECK-DAG: larl [[SRC:%r[0-5]]], g1src
313 ; CHECK-DAG: larl [[DST:%r[0-5]]], g1dst
314 ; CHECK: nc 0(1,[[DST]]), 0([[SRC]])
315 ; CHECK: br %r14
316   %val = load i8 , i8 *@g1src
317   %old = load i8 , i8 *@g1dst
318   %and = and i8 %val, %old
319   store i8 %and, i8 *@g1dst
320   ret void
321 }
322
323 ; Test that we use NC even where LHRL and STHRL are available.
324 define void @f23(i16 *%ptr) {
325 ; CHECK-LABEL: f23:
326 ; CHECK-DAG: larl [[SRC:%r[0-5]]], g2src
327 ; CHECK-DAG: larl [[DST:%r[0-5]]], g2dst
328 ; CHECK: nc 0(2,[[DST]]), 0([[SRC]])
329 ; CHECK: br %r14
330   %val = load i16 , i16 *@g2src
331   %old = load i16 , i16 *@g2dst
332   %and = and i16 %val, %old
333   store i16 %and, i16 *@g2dst
334   ret void
335 }
336
337 ; Test a case where offset disambiguation is enough.
338 define void @f24(i64 *%ptr1) {
339 ; CHECK-LABEL: f24:
340 ; CHECK: nc 8(8,%r2), 0(%r2)
341 ; CHECK: br %r14
342   %ptr2 = getelementptr i64, i64 *%ptr1, i64 1
343   %val = load i64 , i64 *%ptr1, align 1
344   %old = load i64 , i64 *%ptr2, align 1
345   %and = and i64 %old, %val
346   store i64 %and, i64 *%ptr2, align 1
347   ret void
348 }
349
350 ; Test a case where TBAA tells us there is no alias.
351 define void @f25(i64 *%ptr1, i64 *%ptr2) {
352 ; CHECK-LABEL: f25:
353 ; CHECK: nc 0(8,%r3), 0(%r2)
354 ; CHECK: br %r14
355   %val = load i64 , i64 *%ptr1, align 2, !tbaa !3
356   %old = load i64 , i64 *%ptr2, align 2, !tbaa !4
357   %and = and i64 %old, %val
358   store i64 %and, i64 *%ptr2, align 2, !tbaa !4
359   ret void
360 }
361
362 ; Test a case where TBAA information is present but doesn't help.
363 define void @f26(i64 *%ptr1, i64 *%ptr2) {
364 ; CHECK-LABEL: f26:
365 ; CHECK-NOT: nc
366 ; CHECK: br %r14
367   %val = load i64 , i64 *%ptr1, align 2, !tbaa !3
368   %old = load i64 , i64 *%ptr2, align 2, !tbaa !3
369   %and = and i64 %old, %val
370   store i64 %and, i64 *%ptr2, align 2, !tbaa !3
371   ret void
372 }
373
374 !0 = !{ !"root" }
375 !1 = !{ !"set1", !0 }
376 !2 = !{ !"set2", !0 }
377 !3 = !{ !1, !1, i64 0}
378 !4 = !{ !2, !2, i64 0}