1 ; RUN: opt -passes='print<access-info>' -disable-output < %s 2>&1 | FileCheck %s
3 target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
5 ; Following cases are no dependence.
7 ; void nodep_Read_Write(int *A) {
9 ; for (unsigned i = 0; i < 1024; i+=3)
13 ; CHECK: function 'nodep_Read_Write':
14 ; CHECK-NEXT: for.body:
15 ; CHECK-NEXT: Memory dependences are safe
16 ; CHECK-NEXT: Dependences:
17 ; CHECK-NEXT: Run-time memory checks:
19 define void @nodep_Read_Write(ptr nocapture %A) {
21 %add.ptr = getelementptr inbounds i32, ptr %A, i64 1
24 for.cond.cleanup: ; preds = %for.body
27 for.body: ; preds = %entry, %for.body
28 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
29 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv
30 %0 = load i32, ptr %arrayidx, align 4
31 %add = add nsw i32 %0, 1
32 %arrayidx2 = getelementptr inbounds i32, ptr %add.ptr, i64 %indvars.iv
33 store i32 %add, ptr %arrayidx2, align 4
34 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 3
35 %cmp = icmp ult i64 %indvars.iv.next, 1024
36 br i1 %cmp, label %for.body, label %for.cond.cleanup
39 ; int nodep_Write_Read(int *A) {
41 ; for (unsigned i = 0; i < 1024; i+=4) {
49 ; CHECK: function 'nodep_Write_Read':
50 ; CHECK-NEXT: for.body:
51 ; CHECK-NEXT: Memory dependences are safe
52 ; CHECK-NEXT: Dependences:
53 ; CHECK-NEXT: Run-time memory checks:
55 define i32 @nodep_Write_Read(ptr nocapture %A) {
59 for.cond.cleanup: ; preds = %for.body
62 for.body: ; preds = %entry, %for.body
63 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
64 %sum.013 = phi i32 [ 0, %entry ], [ %add3, %for.body ]
65 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv
66 %0 = trunc i64 %indvars.iv to i32
67 store i32 %0, ptr %arrayidx, align 4
68 %1 = or disjoint i64 %indvars.iv, 3
69 %arrayidx2 = getelementptr inbounds i32, ptr %A, i64 %1
70 %2 = load i32, ptr %arrayidx2, align 4
71 %add3 = add nsw i32 %2, %sum.013
72 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 4
73 %cmp = icmp ult i64 %indvars.iv.next, 1024
74 br i1 %cmp, label %for.body, label %for.cond.cleanup
77 ; void nodep_Write_Write(int *A) {
78 ; for (unsigned i = 0; i < 1024; i+=2) {
84 ; CHECK: function 'nodep_Write_Write':
85 ; CHECK-NEXT: for.body:
86 ; CHECK-NEXT: Memory dependences are safe
87 ; CHECK-NEXT: Dependences:
88 ; CHECK-NEXT: Run-time memory checks:
90 define void @nodep_Write_Write(ptr nocapture %A) {
94 for.cond.cleanup: ; preds = %for.body
97 for.body: ; preds = %entry, %for.body
98 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
99 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv
100 %0 = trunc i64 %indvars.iv to i32
101 store i32 %0, ptr %arrayidx, align 4
102 %1 = or disjoint i64 %indvars.iv, 1
103 %arrayidx3 = getelementptr inbounds i32, ptr %A, i64 %1
104 %2 = trunc i64 %1 to i32
105 store i32 %2, ptr %arrayidx3, align 4
106 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2
107 %cmp = icmp ult i64 %indvars.iv.next, 1024
108 br i1 %cmp, label %for.body, label %for.cond.cleanup
111 ; Following cases are unsafe depdences and are not vectorizable.
113 ; void unsafe_Read_Write(int *A) {
114 ; for (unsigned i = 0; i < 1024; i+=3)
118 ; CHECK: function 'unsafe_Read_Write':
119 ; CHECK-NEXT: for.body:
120 ; CHECK-NEXT: Report: unsafe dependent memory operations in loop
121 ; CHECK-NEXT: Backward loop carried data dependence.
122 ; CHECK-NEXT: Dependences:
123 ; CHECK-NEXT: Backward:
124 ; CHECK-NEXT: %0 = load i32, ptr %arrayidx, align 4 ->
125 ; CHECK-NEXT: store i32 %add, ptr %arrayidx3, align 4
127 define void @unsafe_Read_Write(ptr nocapture %A) {
131 for.cond.cleanup: ; preds = %for.body
134 for.body: ; preds = %entry, %for.body
135 %i.010 = phi i32 [ 0, %entry ], [ %add1, %for.body ]
136 %idxprom = zext i32 %i.010 to i64
137 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %idxprom
138 %0 = load i32, ptr %arrayidx, align 4
139 %add = add nsw i32 %0, 1
140 %add1 = add i32 %i.010, 3
141 %idxprom2 = zext i32 %add1 to i64
142 %arrayidx3 = getelementptr inbounds i32, ptr %A, i64 %idxprom2
143 store i32 %add, ptr %arrayidx3, align 4
144 %cmp = icmp ult i32 %add1, 1024
145 br i1 %cmp, label %for.body, label %for.cond.cleanup
148 ; int unsafe_Write_Read(int *A) {
150 ; for (unsigned i = 0; i < 1024; i+=4) {
158 ; CHECK: function 'unsafe_Write_Read':
159 ; CHECK-NEXT: for.body:
160 ; CHECK-NEXT: Report: unsafe dependent memory operations in loop
161 ; CHECK-NEXT: Backward loop carried data dependence.
162 ; CHECK-NEXT: Dependences:
163 ; CHECK-NEXT: Backward:
164 ; CHECK-NEXT: store i32 %0, ptr %arrayidx, align 4 ->
165 ; CHECK-NEXT: %1 = load i32, ptr %arrayidx2, align 4
167 define i32 @unsafe_Write_Read(ptr nocapture %A) {
171 for.cond.cleanup: ; preds = %for.body
174 for.body: ; preds = %entry, %for.body
175 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
176 %sum.013 = phi i32 [ 0, %entry ], [ %add3, %for.body ]
177 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv
178 %0 = trunc i64 %indvars.iv to i32
179 store i32 %0, ptr %arrayidx, align 4
180 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 4
181 %arrayidx2 = getelementptr inbounds i32, ptr %A, i64 %indvars.iv.next
182 %1 = load i32, ptr %arrayidx2, align 4
183 %add3 = add nsw i32 %1, %sum.013
184 %cmp = icmp ult i64 %indvars.iv.next, 1024
185 br i1 %cmp, label %for.body, label %for.cond.cleanup
188 ; void unsafe_Write_Write(int *A) {
189 ; for (unsigned i = 0; i < 1024; i+=2) {
195 ; CHECK: function 'unsafe_Write_Write':
196 ; CHECK-NEXT: for.body:
197 ; CHECK-NEXT: Report: unsafe dependent memory operations in loop
198 ; CHECK-NEXT: Backward loop carried data dependence.
199 ; CHECK-NEXT: Dependences:
200 ; CHECK-NEXT: Backward:
201 ; CHECK-NEXT: store i32 %0, ptr %arrayidx, align 4 ->
202 ; CHECK-NEXT: store i32 %2, ptr %arrayidx3, align 4
204 define void @unsafe_Write_Write(ptr nocapture %A) {
208 for.cond.cleanup: ; preds = %for.body
211 for.body: ; preds = %entry, %for.body
212 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
213 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv
214 %0 = trunc i64 %indvars.iv to i32
215 store i32 %0, ptr %arrayidx, align 4
216 %1 = or disjoint i64 %indvars.iv, 1
217 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2
218 %arrayidx3 = getelementptr inbounds i32, ptr %A, i64 %indvars.iv.next
219 %2 = trunc i64 %1 to i32
220 store i32 %2, ptr %arrayidx3, align 4
221 %cmp = icmp ult i64 %indvars.iv.next, 1024
222 br i1 %cmp, label %for.body, label %for.cond.cleanup
225 ; Following cases check that strided accesses can be vectorized.
227 ; void vectorizable_Read_Write(int *A) {
229 ; for (unsigned i = 0; i < 1024; i+=2)
233 ; CHECK: function 'vectorizable_Read_Write':
234 ; CHECK-NEXT: for.body:
235 ; CHECK-NEXT: Memory dependences are safe
236 ; CHECK-NEXT: Dependences:
237 ; CHECK-NEXT: BackwardVectorizable:
238 ; CHECK-NEXT: %0 = load i32, ptr %arrayidx, align 4 ->
239 ; CHECK-NEXT: store i32 %add, ptr %arrayidx2, align 4
241 define void @vectorizable_Read_Write(ptr nocapture %A) {
243 %add.ptr = getelementptr inbounds i32, ptr %A, i64 4
246 for.cond.cleanup: ; preds = %for.body
249 for.body: ; preds = %entry, %for.body
250 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
251 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv
252 %0 = load i32, ptr %arrayidx, align 4
253 %add = add nsw i32 %0, 1
254 %arrayidx2 = getelementptr inbounds i32, ptr %add.ptr, i64 %indvars.iv
255 store i32 %add, ptr %arrayidx2, align 4
256 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2
257 %cmp = icmp ult i64 %indvars.iv.next, 1024
258 br i1 %cmp, label %for.body, label %for.cond.cleanup
261 ; int vectorizable_Write_Read(int *A) {
264 ; for (unsigned i = 0; i < 1024; i+=2) {
272 ; CHECK: function 'vectorizable_Write_Read':
273 ; CHECK-NEXT: for.body:
274 ; CHECK-NEXT: Memory dependences are safe
275 ; CHECK-NEXT: Dependences:
276 ; CHECK-NEXT: BackwardVectorizable:
277 ; CHECK-NEXT: store i32 %0, ptr %arrayidx, align 4 ->
278 ; CHECK-NEXT: %1 = load i32, ptr %arrayidx2, align 4
280 define i32 @vectorizable_Write_Read(ptr nocapture %A) {
282 %add.ptr = getelementptr inbounds i32, ptr %A, i64 4
285 for.cond.cleanup: ; preds = %for.body
288 for.body: ; preds = %entry, %for.body
289 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
290 %sum.013 = phi i32 [ 0, %entry ], [ %add, %for.body ]
291 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv
292 %0 = trunc i64 %indvars.iv to i32
293 store i32 %0, ptr %arrayidx, align 4
294 %arrayidx2 = getelementptr inbounds i32, ptr %add.ptr, i64 %indvars.iv
295 %1 = load i32, ptr %arrayidx2, align 4
296 %add = add nsw i32 %1, %sum.013
297 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2
298 %cmp = icmp ult i64 %indvars.iv.next, 1024
299 br i1 %cmp, label %for.body, label %for.cond.cleanup
302 ; void vectorizable_Write_Write(int *A) {
304 ; for (unsigned i = 0; i < 1024; i+=2) {
310 ; CHECK: function 'vectorizable_Write_Write':
311 ; CHECK-NEXT: for.body:
312 ; CHECK-NEXT: Memory dependences are safe
313 ; CHECK-NEXT: Dependences:
314 ; CHECK-NEXT: BackwardVectorizable:
315 ; CHECK-NEXT: store i32 %0, ptr %arrayidx, align 4 ->
316 ; CHECK-NEXT: store i32 %2, ptr %arrayidx2, align 4
318 define void @vectorizable_Write_Write(ptr nocapture %A) {
320 %add.ptr = getelementptr inbounds i32, ptr %A, i64 4
323 for.cond.cleanup: ; preds = %for.body
326 for.body: ; preds = %entry, %for.body
327 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
328 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv
329 %0 = trunc i64 %indvars.iv to i32
330 store i32 %0, ptr %arrayidx, align 4
331 %1 = or disjoint i64 %indvars.iv, 1
332 %arrayidx2 = getelementptr inbounds i32, ptr %add.ptr, i64 %indvars.iv
333 %2 = trunc i64 %1 to i32
334 store i32 %2, ptr %arrayidx2, align 4
335 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2
336 %cmp = icmp ult i64 %indvars.iv.next, 1024
337 br i1 %cmp, label %for.body, label %for.cond.cleanup
340 ; void vectorizable_unscaled_Read_Write(int *A) {
341 ; int *B = (int *)((char *)A + 14);
342 ; for (unsigned i = 0; i < 1024; i+=2)
346 ; FIXME: This case looks like previous case @vectorizable_Read_Write. It sould
349 ; CHECK: function 'vectorizable_unscaled_Read_Write':
350 ; CHECK-NEXT: for.body:
351 ; CHECK-NEXT: Report: unsafe dependent memory operations in loop
352 ; CHECK-NEXT: Backward loop carried data dependence that prevents store-to-load forwarding.
353 ; CHECK-NEXT: Dependences:
354 ; CHECK-NEXT: BackwardVectorizableButPreventsForwarding:
355 ; CHECK-NEXT: %0 = load i32, ptr %arrayidx, align 4 ->
356 ; CHECK-NEXT: store i32 %add, ptr %arrayidx2, align 4
358 define void @vectorizable_unscaled_Read_Write(ptr nocapture %A) {
360 %add.ptr = getelementptr inbounds i8, ptr %A, i64 14
363 for.cond.cleanup: ; preds = %for.body
366 for.body: ; preds = %entry, %for.body
367 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
368 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv
369 %0 = load i32, ptr %arrayidx, align 4
370 %add = add nsw i32 %0, 1
371 %arrayidx2 = getelementptr inbounds i32, ptr %add.ptr, i64 %indvars.iv
372 store i32 %add, ptr %arrayidx2, align 4
373 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2
374 %cmp = icmp ult i64 %indvars.iv.next, 1024
375 br i1 %cmp, label %for.body, label %for.cond.cleanup
378 ; int vectorizable_unscaled_Write_Read(int *A) {
379 ; int *B = (int *)((char *)A + 17);
381 ; for (unsigned i = 0; i < 1024; i+=2) {
389 ; CHECK: function 'vectorizable_unscaled_Write_Read':
390 ; CHECK-NEXT: for.body:
391 ; CHECK-NEXT: Memory dependences are safe
392 ; CHECK-NEXT: Dependences:
393 ; CHECK-NEXT: BackwardVectorizable:
394 ; CHECK-NEXT: store i32 %0, ptr %arrayidx, align 4 ->
395 ; CHECK-NEXT: %1 = load i32, ptr %arrayidx2, align 4
397 define i32 @vectorizable_unscaled_Write_Read(ptr nocapture %A) {
399 %add.ptr = getelementptr inbounds i8, ptr %A, i64 17
402 for.cond.cleanup: ; preds = %for.body
405 for.body: ; preds = %entry, %for.body
406 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
407 %sum.013 = phi i32 [ 0, %entry ], [ %add, %for.body ]
408 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv
409 %0 = trunc i64 %indvars.iv to i32
410 store i32 %0, ptr %arrayidx, align 4
411 %arrayidx2 = getelementptr inbounds i32, ptr %add.ptr, i64 %indvars.iv
412 %1 = load i32, ptr %arrayidx2, align 4
413 %add = add nsw i32 %1, %sum.013
414 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2
415 %cmp = icmp ult i64 %indvars.iv.next, 1024
416 br i1 %cmp, label %for.body, label %for.cond.cleanup
419 ; void unsafe_unscaled_Read_Write(int *A) {
420 ; int *B = (int *)((char *)A + 11);
421 ; for (unsigned i = 0; i < 1024; i+=2)
425 ; CHECK: function 'unsafe_unscaled_Read_Write':
426 ; CHECK-NEXT: for.body:
427 ; CHECK-NEXT: Report: unsafe dependent memory operations in loop
428 ; CHECK-NEXT: Backward loop carried data dependence.
429 ; CHECK-NEXT: Dependences:
430 ; CHECK-NEXT: Backward:
431 ; CHECK-NEXT: %0 = load i32, ptr %arrayidx, align 4 ->
432 ; CHECK-NEXT: store i32 %add, ptr %arrayidx2, align 4
434 define void @unsafe_unscaled_Read_Write(ptr nocapture %A) {
436 %add.ptr = getelementptr inbounds i8, ptr %A, i64 11
439 for.cond.cleanup: ; preds = %for.body
442 for.body: ; preds = %entry, %for.body
443 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
444 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv
445 %0 = load i32, ptr %arrayidx, align 4
446 %add = add nsw i32 %0, 1
447 %arrayidx2 = getelementptr inbounds i32, ptr %add.ptr, i64 %indvars.iv
448 store i32 %add, ptr %arrayidx2, align 4
449 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2
450 %cmp = icmp ult i64 %indvars.iv.next, 1024
451 br i1 %cmp, label %for.body, label %for.cond.cleanup
454 ; CHECK: function 'unsafe_unscaled_Read_Write2':
455 ; CHECK-NEXT: for.body:
456 ; CHECK-NEXT: Report: unsafe dependent memory operations in loop
457 ; CHECK-NEXT: Backward loop carried data dependence.
458 ; CHECK-NEXT: Dependences:
459 ; CHECK-NEXT: Backward:
460 ; CHECK-NEXT: %0 = load i32, ptr %arrayidx, align 4 ->
461 ; CHECK-NEXT: store i32 %add, ptr %arrayidx2, align 4
463 ; void unsafe_unscaled_Read_Write2(int *A) {
464 ; int *B = (int *)((char *)A + 1);
465 ; for (unsigned i = 0; i < 1024; i+=2)
469 define void @unsafe_unscaled_Read_Write2(ptr nocapture %A) {
471 %add.ptr = getelementptr inbounds i8, ptr %A, i64 1
474 for.cond.cleanup: ; preds = %for.body
477 for.body: ; preds = %entry, %for.body
478 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
479 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv
480 %0 = load i32, ptr %arrayidx, align 4
481 %add = add nsw i32 %0, 1
482 %arrayidx2 = getelementptr inbounds i32, ptr %add.ptr, i64 %indvars.iv
483 store i32 %add, ptr %arrayidx2, align 4
484 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2
485 %cmp = icmp ult i64 %indvars.iv.next, 1024
486 br i1 %cmp, label %for.body, label %for.cond.cleanup
489 ; Following case checks that interleaved stores have dependences with another
490 ; store and can not pass dependence check.
492 ; void interleaved_stores(int *A) {
493 ; int *B = (int *) ((char *)A + 1);
494 ; for(int i = 0; i < 1024; i+=2) {
496 ; A[i+1] = i + 1; // (2)
497 ; B[i+1] = i + 1; // (3)
501 ; The access (2) has overlaps with (1) and (3).
503 ; CHECK: function 'interleaved_stores':
504 ; CHECK-NEXT: for.body:
505 ; CHECK-NEXT: Report: unsafe dependent memory operations in loop
506 ; CHECK-NEXT: Backward loop carried data dependence.
507 ; CHECK-NEXT: Dependences:
508 ; CHECK-NEXT: Backward:
509 ; CHECK-NEXT: store i32 %2, ptr %arrayidx5, align 4 ->
510 ; CHECK-NEXT: store i32 %2, ptr %arrayidx9, align 4
512 ; CHECK-NEXT: store i32 %0, ptr %arrayidx2, align 4 ->
513 ; CHECK-NEXT: store i32 %2, ptr %arrayidx5, align 4
515 define void @interleaved_stores(ptr nocapture %A) {
517 %incdec.ptr = getelementptr inbounds i8, ptr %A, i64 1
520 for.cond.cleanup: ; preds = %for.body
523 for.body: ; preds = %entry, %for.body
524 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
525 %0 = trunc i64 %indvars.iv to i32
526 %arrayidx2 = getelementptr inbounds i32, ptr %incdec.ptr, i64 %indvars.iv
527 store i32 %0, ptr %arrayidx2, align 4
528 %1 = or disjoint i64 %indvars.iv, 1
529 %arrayidx5 = getelementptr inbounds i32, ptr %A, i64 %1
530 %2 = trunc i64 %1 to i32
531 store i32 %2, ptr %arrayidx5, align 4
532 %arrayidx9 = getelementptr inbounds i32, ptr %incdec.ptr, i64 %1
533 store i32 %2, ptr %arrayidx9, align 4
534 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2
535 %cmp = icmp slt i64 %indvars.iv.next, 1024
536 br i1 %cmp, label %for.body, label %for.cond.cleanup