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