1 ; RUN: opt -basicaa -loop-accesses -analyze < %s | FileCheck %s 2 3 ; This loop: 4 ; 5 ; int **A; 6 ; for (i) 7 ; for (j) { 8 ; A[i][j] = A[i-1][j] * B[j] 9 ; B[j+1] = 2 // backward dep between this and the previous 10 ; } 11 ; 12 ; is transformed by Load-PRE to stash away A[i] for the next iteration of the 13 ; outer loop: 14 ; 15 ; Curr = A[0]; // Prev_0 16 ; for (i: 1..N) { 17 ; Prev = Curr; // Prev = PHI (Prev_0, Curr) 18 ; Curr = A[i]; 19 ; for (j: 0..N) { 20 ; Curr[j] = Prev[j] * B[j] 21 ; B[j+1] = 2 // backward dep between this and the previous 22 ; } 23 ; } 24 ; 25 ; Since A[i] and A[i-1] are likely to be independent, getUnderlyingObjects 26 ; should not assume that Curr and Prev share the same underlying object. 27 ; 28 ; If it did we would try to dependence-analyze Curr and Prev and the analysis 29 ; would fail with non-constant distance. 30 ; 31 ; To illustrate one of the negative consequences of this, if the loop has a 32 ; backward dependence we won't detect this but instead fully fall back on 33 ; memchecks (that is what LAA does after encountering a case of non-constant 34 ; distance). 35 36 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" 37 target triple = "x86_64-apple-macosx10.10.0" 38 39 ; CHECK: for_j.body: 40 ; CHECK-NEXT: Report: unsafe dependent memory operations in loop 41 ; CHECK-NEXT: Dependences: 42 ; CHECK-NEXT: Backward: 43 ; CHECK-NEXT: %loadB = load i8, i8* %gepB, align 1 -> 44 ; CHECK-NEXT: store i8 2, i8* %gepB_plus_one, align 1 45 46 define void @f(i8** noalias %A, i8* noalias %B, i64 %N) { 47 for_i.preheader: 48 %prev_0 = load i8*, i8** %A, align 8 49 br label %for_i.body 50 51 for_i.body: 52 %i = phi i64 [1, %for_i.preheader], [%i.1, %for_j.end] 53 %prev = phi i8* [%prev_0, %for_i.preheader], [%curr, %for_j.end] 54 %gep = getelementptr inbounds i8*, i8** %A, i64 %i 55 %curr = load i8*, i8** %gep, align 8 56 br label %for_j.preheader 57 58 for_j.preheader: 59 br label %for_j.body 60 61 for_j.body: 62 %j = phi i64 [0, %for_j.preheader], [%j.1, %for_j.body] 63 64 %gepPrev = getelementptr inbounds i8, i8* %prev, i64 %j 65 %gepCurr = getelementptr inbounds i8, i8* %curr, i64 %j 66 %gepB = getelementptr inbounds i8, i8* %B, i64 %j 67 68 %loadPrev = load i8, i8* %gepPrev, align 1 69 %loadB = load i8, i8* %gepB, align 1 70 71 %mul = mul i8 %loadPrev, %loadB 72 73 store i8 %mul, i8* %gepCurr, align 1 74 75 %gepB_plus_one = getelementptr inbounds i8, i8* %gepB, i64 1 76 store i8 2, i8* %gepB_plus_one, align 1 77 78 %j.1 = add nuw i64 %j, 1 79 %exitcondj = icmp eq i64 %j.1, %N 80 br i1 %exitcondj, label %for_j.end, label %for_j.body 81 82 for_j.end: 83 84 %i.1 = add nuw i64 %i, 1 85 %exitcond = icmp eq i64 %i.1, %N 86 br i1 %exitcond, label %for_i.end, label %for_i.body 87 88 for_i.end: 89 ret void 90 } 91