reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
; RUN: opt -basicaa -loop-accesses -analyze < %s | FileCheck %s
; RUN: opt -passes='require<scalar-evolution>,require<aa>,loop(print-access-info)' -disable-output  < %s 2>&1 | FileCheck %s

; This loop:
;
;   int **A;
;   for (i)
;     for (j) {
;        A[i][j] = A[i-1][j] * B[j]
;        B[j+1] = 2       // backward dep between this and the previous
;     }
;
; is transformed by Load-PRE to stash away A[i] for the next iteration of the
; outer loop:
;
;   Curr = A[0];          // Prev_0
;   for (i: 1..N) {
;     Prev = Curr;        // Prev = PHI (Prev_0, Curr)
;     Curr = A[i];
;     for (j: 0..N) {
;        Curr[j] = Prev[j] * B[j]
;        B[j+1] = 2       // backward dep between this and the previous
;     }
;   }
;
; Since A[i] and A[i-1] are likely to be independent, getUnderlyingObjects
; should not assume that Curr and Prev share the same underlying object.
;
; If it did we would try to dependence-analyze Curr and Prev and the analysis
; would fail with non-constant distance.
;
; To illustrate one of the negative consequences of this, if the loop has a
; backward dependence we won't detect this but instead fully fall back on
; memchecks (that is what LAA does after encountering a case of non-constant
; distance).

target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.10.0"

; CHECK: for_j.body:
; CHECK-NEXT: Report: unsafe dependent memory operations in loop
; CHECK-NEXT: Dependences:
; CHECK-NEXT: Backward:
; CHECK-NEXT: %loadB = load i8, i8* %gepB, align 1 ->
; CHECK-NEXT: store i8 2, i8* %gepB_plus_one, align 1

define void @f(i8** noalias %A, i8* noalias %B, i64 %N) {
for_i.preheader:
  %prev_0 = load i8*, i8** %A, align 8
  br label %for_i.body

for_i.body:
  %i = phi i64 [1, %for_i.preheader], [%i.1, %for_j.end]
  %prev = phi i8* [%prev_0, %for_i.preheader], [%curr, %for_j.end]
  %gep = getelementptr inbounds i8*, i8** %A, i64 %i
  %curr = load i8*, i8** %gep, align 8
  br label %for_j.preheader

for_j.preheader:
  br label %for_j.body

for_j.body:
  %j = phi i64 [0, %for_j.preheader], [%j.1, %for_j.body]

  %gepPrev = getelementptr inbounds i8, i8* %prev, i64 %j
  %gepCurr = getelementptr inbounds i8, i8* %curr, i64 %j
  %gepB = getelementptr inbounds i8, i8* %B, i64 %j

  %loadPrev = load i8, i8* %gepPrev, align 1
  %loadB = load i8, i8* %gepB, align 1

  %mul = mul i8 %loadPrev, %loadB

  store i8 %mul, i8* %gepCurr, align 1

  %gepB_plus_one = getelementptr inbounds i8, i8* %gepB, i64 1
  store i8 2, i8* %gepB_plus_one, align 1

  %j.1 = add nuw i64 %j, 1
  %exitcondj = icmp eq i64 %j.1, %N
  br i1 %exitcondj, label %for_j.end, label %for_j.body

for_j.end:

  %i.1 = add nuw i64 %i, 1
  %exitcond = icmp eq i64 %i.1, %N
  br i1 %exitcond, label %for_i.end, label %for_i.body

for_i.end:
  ret void
}