1 ; Test memory-to-memory ANDs.
3 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
8 ; Test the simple i8 case.
9 define void @f1(i8 *%ptr1) {
11 ; CHECK: nc 1(1,%r2), 0(%r2)
13 %ptr2 = getelementptr i8 *%ptr1, i64 1
16 %and = and i8 %val, %old
17 store i8 %and, i8 *%ptr2
21 ; ...and again in reverse.
22 define void @f2(i8 *%ptr1) {
24 ; CHECK: nc 1(1,%r2), 0(%r2)
26 %ptr2 = getelementptr i8 *%ptr1, i64 1
29 %and = and i8 %old, %val
30 store i8 %and, i8 *%ptr2
34 ; Test i8 cases where one value is zero-extended to 32 bits and the other
36 define void @f3(i8 *%ptr1) {
38 ; CHECK: nc 1(1,%r2), 0(%r2)
40 %ptr2 = getelementptr i8 *%ptr1, i64 1
42 %extval = zext i8 %val to i32
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
51 ; ...and again with the extension types reversed.
52 define void @f4(i8 *%ptr1) {
54 ; CHECK: nc 1(1,%r2), 0(%r2)
56 %ptr2 = getelementptr i8 *%ptr1, i64 1
58 %extval = sext i8 %val to i32
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
67 ; ...and again with two sign extensions.
68 define void @f5(i8 *%ptr1) {
70 ; CHECK: nc 1(1,%r2), 0(%r2)
72 %ptr2 = getelementptr i8 *%ptr1, i64 1
74 %extval = sext i8 %val to i32
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
83 ; ...and again with two zero extensions.
84 define void @f6(i8 *%ptr1) {
86 ; CHECK: nc 1(1,%r2), 0(%r2)
88 %ptr2 = getelementptr i8 *%ptr1, i64 1
90 %extval = zext i8 %val to i32
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
99 ; Test i8 cases where the value is extended to 64 bits (just one case
101 define void @f7(i8 *%ptr1) {
103 ; CHECK: nc 1(1,%r2), 0(%r2)
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
116 ; Test the simple i16 case.
117 define void @f8(i16 *%ptr1) {
119 ; CHECK: nc 2(2,%r2), 0(%r2)
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
129 ; Test i16 cases where the value is extended to 32 bits.
130 define void @f9(i16 *%ptr1) {
132 ; CHECK: nc 2(2,%r2), 0(%r2)
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
145 ; Test i16 cases where the value is extended to 64 bits.
146 define void @f10(i16 *%ptr1) {
148 ; CHECK: nc 2(2,%r2), 0(%r2)
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
161 ; Test the simple i32 case.
162 define void @f11(i32 *%ptr1) {
164 ; CHECK: nc 4(4,%r2), 0(%r2)
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
174 ; Test i32 cases where the value is extended to 64 bits.
175 define void @f12(i32 *%ptr1) {
177 ; CHECK: nc 4(4,%r2), 0(%r2)
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
191 define void @f13(i64 *%ptr1) {
193 ; CHECK: nc 8(8,%r2), 0(%r2)
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
203 ; Make sure that we don't use NC if the first load is volatile.
204 define void @f14(i64 *%ptr1) {
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
216 ; ...likewise the second.
217 define void @f15(i64 *%ptr1) {
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
229 ; ...likewise the store.
230 define void @f16(i64 *%ptr1) {
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
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) {
246 ; CHECK: nc 0(8,%r3), 0(%r2)
248 %val = load i64 *%ptr1
249 %old = load i64 *%ptr2
250 %and = and i64 %old, %val
251 store i64 %and, i64 *%ptr2
255 ; ...but if one of the loads isn't aligned, we can't be sure.
256 define void @f18(i64 *%ptr1, i64 *%ptr2) {
260 %val = load i64 *%ptr1, align 2
261 %old = load i64 *%ptr2
262 %and = and i64 %old, %val
263 store i64 %and, i64 *%ptr2
267 ; Repeat the previous test with the operands in the opposite order.
268 define void @f19(i64 *%ptr1, i64 *%ptr2) {
272 %val = load i64 *%ptr1, align 2
273 %old = load i64 *%ptr2
274 %and = and i64 %val, %old
275 store i64 %and, i64 *%ptr2
279 ; ...and again with the other operand being unaligned.
280 define void @f20(i64 *%ptr1, i64 *%ptr2) {
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
291 ; Test a case where there is definite overlap.
292 define void @f21(i64 %base) {
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
306 ; Test that we can use NC for global addresses for i8.
307 define void @f22(i8 *%ptr) {
309 ; CHECK: larl [[REG:%r[0-5]]], g1
310 ; CHECK: nc 0(1,%r2), 0([[REG]])
314 %and = and i8 %val, %old
315 store i8 %and, i8 *%ptr
319 ; ...and again with the global on the store.
320 define void @f23(i8 *%ptr) {
322 ; CHECK: larl [[REG:%r[0-5]]], g1
323 ; CHECK: nc 0(1,[[REG]]), 0(%r2)
327 %and = and i8 %val, %old
328 store i8 %and, i8 *@g1
332 ; Test that we use NC even where LHRL and STHRL are available.
333 define void @f24(i16 *%ptr) {
335 ; CHECK: larl [[REG:%r[0-5]]], g2
336 ; CHECK: nc 0(2,%r2), 0([[REG]])
339 %old = load i16 *%ptr
340 %and = and i16 %val, %old
341 store i16 %and, i16 *%ptr
345 ; ...likewise on the other side.
346 define void @f25(i16 *%ptr) {
348 ; CHECK: larl [[REG:%r[0-5]]], g2
349 ; CHECK: nc 0(2,[[REG]]), 0(%r2)
351 %val = load i16 *%ptr
353 %and = and i16 %val, %old
354 store i16 %and, i16 *@g2
358 ; Test a case where offset disambiguation is enough.
359 define void @f26(i64 *%ptr1) {
361 ; CHECK: nc 8(8,%r2), 0(%r2)
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
371 ; Test a case where TBAA tells us there is no alias.
372 define void @f27(i64 *%ptr1, i64 *%ptr2) {
374 ; CHECK: nc 0(8,%r3), 0(%r2)
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
383 ; Test a case where TBAA information is present but doesn't help.
384 define void @f28(i64 *%ptr1, i64 *%ptr2) {
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
395 !0 = metadata !{ metadata !"root" }
396 !1 = metadata !{ metadata !"set1", metadata !0 }
397 !2 = metadata !{ metadata !"set2", metadata !0 }