summaryrefslogtreecommitdiff
path: root/test/Analysis/LoopAccessAnalysis
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-05-27 18:44:32 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-05-27 18:44:32 +0000
commit5a5ac124e1efaf208671f01c46edb15f29ed2a0b (patch)
treea6140557876943cdd800ee997c9317283394b22c /test/Analysis/LoopAccessAnalysis
parentf03b5bed27d0d2eafd68562ce14f8b5e3f1f0801 (diff)
Notes
Diffstat (limited to 'test/Analysis/LoopAccessAnalysis')
-rw-r--r--test/Analysis/LoopAccessAnalysis/backward-dep-different-types.ll49
-rw-r--r--test/Analysis/LoopAccessAnalysis/resort-to-memchecks-only.ll57
-rw-r--r--test/Analysis/LoopAccessAnalysis/safe-no-checks.ll43
-rw-r--r--test/Analysis/LoopAccessAnalysis/store-to-invariant-check1.ll53
-rw-r--r--test/Analysis/LoopAccessAnalysis/store-to-invariant-check2.ll54
-rw-r--r--test/Analysis/LoopAccessAnalysis/store-to-invariant-check3.ll53
-rw-r--r--test/Analysis/LoopAccessAnalysis/underlying-objects-1.ll47
-rw-r--r--test/Analysis/LoopAccessAnalysis/underlying-objects-2.ll90
-rw-r--r--test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll58
9 files changed, 504 insertions, 0 deletions
diff --git a/test/Analysis/LoopAccessAnalysis/backward-dep-different-types.ll b/test/Analysis/LoopAccessAnalysis/backward-dep-different-types.ll
new file mode 100644
index 000000000000..5d4fb7d3d66c
--- /dev/null
+++ b/test/Analysis/LoopAccessAnalysis/backward-dep-different-types.ll
@@ -0,0 +1,49 @@
+; RUN: opt -loop-accesses -analyze < %s | FileCheck %s
+
+; In this loop just because we access A through different types (int, float)
+; we still have a dependence cycle:
+;
+; for (i = 0; i < n; i++) {
+; A_float = (float *) A;
+; A_float[i + 1] = A[i] * B[i];
+; }
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.10.0"
+
+; CHECK: Report: unsafe dependent memory operations in loop
+; CHECK-NOT: Memory dependences are safe
+
+@B = common global i32* null, align 8
+@A = common global i32* null, align 8
+
+define void @f() {
+entry:
+ %a = load i32*, i32** @A, align 8
+ %b = load i32*, i32** @B, align 8
+ br label %for.body
+
+for.body: ; preds = %for.body, %entry
+ %storemerge3 = phi i64 [ 0, %entry ], [ %add, %for.body ]
+
+ %arrayidxA = getelementptr inbounds i32, i32* %a, i64 %storemerge3
+ %loadA = load i32, i32* %arrayidxA, align 2
+
+ %arrayidxB = getelementptr inbounds i32, i32* %b, i64 %storemerge3
+ %loadB = load i32, i32* %arrayidxB, align 2
+
+ %mul = mul i32 %loadB, %loadA
+
+ %add = add nuw nsw i64 %storemerge3, 1
+
+ %a_float = bitcast i32* %a to float*
+ %arrayidxA_plus_2 = getelementptr inbounds float, float* %a_float, i64 %add
+ %mul_float = sitofp i32 %mul to float
+ store float %mul_float, float* %arrayidxA_plus_2, align 2
+
+ %exitcond = icmp eq i64 %add, 20
+ br i1 %exitcond, label %for.end, label %for.body
+
+for.end: ; preds = %for.body
+ ret void
+}
diff --git a/test/Analysis/LoopAccessAnalysis/resort-to-memchecks-only.ll b/test/Analysis/LoopAccessAnalysis/resort-to-memchecks-only.ll
new file mode 100644
index 000000000000..64f7729fa18a
--- /dev/null
+++ b/test/Analysis/LoopAccessAnalysis/resort-to-memchecks-only.ll
@@ -0,0 +1,57 @@
+; RUN: opt -loop-accesses -analyze < %s | FileCheck %s
+
+; We give up analyzing the dependences in this loop due to non-constant
+; distance between A[i+offset] and A[i] and add memchecks to prove
+; independence. Make sure that no interesting dependences are reported in
+; this case.
+;
+; for (i = 0; i < n; i++)
+; A[i + offset] = A[i] * B[i] * C[i];
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.10.0"
+
+; CHECK: Memory dependences are safe with run-time checks
+; CHECK-NEXT: Interesting Dependences:
+; CHECK-NEXT: Run-time memory checks:
+; CHECK-NEXT: 0:
+; CHECK-NEXT: %arrayidxA2 = getelementptr inbounds i16, i16* %a, i64 %idx
+; CHECK-NEXT: %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %indvar
+
+@B = common global i16* null, align 8
+@A = common global i16* null, align 8
+@C = common global i16* null, align 8
+
+define void @f(i64 %offset) {
+entry:
+ %a = load i16*, i16** @A, align 8
+ %b = load i16*, i16** @B, align 8
+ %c = load i16*, i16** @C, align 8
+ br label %for.body
+
+for.body: ; preds = %for.body, %entry
+ %indvar = phi i64 [ 0, %entry ], [ %add, %for.body ]
+
+ %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %indvar
+ %loadA = load i16, i16* %arrayidxA, align 2
+
+ %arrayidxB = getelementptr inbounds i16, i16* %b, i64 %indvar
+ %loadB = load i16, i16* %arrayidxB, align 2
+
+ %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %indvar
+ %loadC = load i16, i16* %arrayidxC, align 2
+
+ %mul = mul i16 %loadB, %loadA
+ %mul1 = mul i16 %mul, %loadC
+
+ %idx = add i64 %indvar, %offset
+ %arrayidxA2 = getelementptr inbounds i16, i16* %a, i64 %idx
+ store i16 %mul1, i16* %arrayidxA2, align 2
+
+ %add = add nuw nsw i64 %indvar, 1
+ %exitcond = icmp eq i64 %add, 20
+ br i1 %exitcond, label %for.end, label %for.body
+
+for.end: ; preds = %for.body
+ ret void
+}
diff --git a/test/Analysis/LoopAccessAnalysis/safe-no-checks.ll b/test/Analysis/LoopAccessAnalysis/safe-no-checks.ll
new file mode 100644
index 000000000000..fa70c024a9c5
--- /dev/null
+++ b/test/Analysis/LoopAccessAnalysis/safe-no-checks.ll
@@ -0,0 +1,43 @@
+; RUN: opt -basicaa -loop-accesses -analyze < %s | FileCheck %s
+
+; If the arrays don't alias this loop is safe with no memchecks:
+; for (i = 0; i < n; i++)
+; A[i] = A[i+1] * B[i] * C[i];
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.10.0"
+
+; CHECK: Memory dependences are safe{{$}}
+
+define void @f(i16* noalias %a,
+ i16* noalias %b,
+ i16* noalias %c) {
+entry:
+ br label %for.body
+
+for.body: ; preds = %for.body, %entry
+ %ind = phi i64 [ 0, %entry ], [ %add, %for.body ]
+
+ %add = add nuw nsw i64 %ind, 1
+
+ %arrayidxA_plus_2 = getelementptr inbounds i16, i16* %a, i64 %add
+ %loadA_plus_2 = load i16, i16* %arrayidxA_plus_2, align 2
+
+ %arrayidxB = getelementptr inbounds i16, i16* %b, i64 %ind
+ %loadB = load i16, i16* %arrayidxB, align 2
+
+ %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %ind
+ %loadC = load i16, i16* %arrayidxC, align 2
+
+ %mul = mul i16 %loadB, %loadA_plus_2
+ %mul1 = mul i16 %mul, %loadC
+
+ %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %ind
+ store i16 %mul1, i16* %arrayidxA, align 2
+
+ %exitcond = icmp eq i64 %add, 20
+ br i1 %exitcond, label %for.end, label %for.body
+
+for.end: ; preds = %for.body
+ ret void
+}
diff --git a/test/Analysis/LoopAccessAnalysis/store-to-invariant-check1.ll b/test/Analysis/LoopAccessAnalysis/store-to-invariant-check1.ll
new file mode 100644
index 000000000000..8ab8ab2a55b6
--- /dev/null
+++ b/test/Analysis/LoopAccessAnalysis/store-to-invariant-check1.ll
@@ -0,0 +1,53 @@
+; RUN: opt < %s -loop-accesses -analyze | FileCheck %s
+
+; Test to confirm LAA will find store to invariant address.
+; Inner loop has a store to invariant address.
+;
+; for(; i < itr; i++) {
+; for(; j < itr; j++) {
+; var1[i] = var2[j] + var1[i];
+; }
+; }
+
+; CHECK: Store to invariant address was found in loop.
+; CHECK-NOT: Store to invariant address was not found in loop.
+
+define i32 @foo(i32* nocapture %var1, i32* nocapture readonly %var2, i32 %itr) #0 {
+entry:
+ %cmp20 = icmp eq i32 %itr, 0
+ br i1 %cmp20, label %for.end10, label %for.cond1.preheader
+
+for.cond1.preheader: ; preds = %entry, %for.inc8
+ %indvars.iv23 = phi i64 [ %indvars.iv.next24, %for.inc8 ], [ 0, %entry ]
+ %j.022 = phi i32 [ %j.1.lcssa, %for.inc8 ], [ 0, %entry ]
+ %cmp218 = icmp ult i32 %j.022, %itr
+ br i1 %cmp218, label %for.body3.lr.ph, label %for.inc8
+
+for.body3.lr.ph: ; preds = %for.cond1.preheader
+ %arrayidx5 = getelementptr inbounds i32, i32* %var1, i64 %indvars.iv23
+ %0 = zext i32 %j.022 to i64
+ br label %for.body3
+
+for.body3: ; preds = %for.body3, %for.body3.lr.ph
+ %indvars.iv = phi i64 [ %0, %for.body3.lr.ph ], [ %indvars.iv.next, %for.body3 ]
+ %arrayidx = getelementptr inbounds i32, i32* %var2, i64 %indvars.iv
+ %1 = load i32, i32* %arrayidx, align 4
+ %2 = load i32, i32* %arrayidx5, align 4
+ %add = add nsw i32 %2, %1
+ store i32 %add, i32* %arrayidx5, align 4
+ %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+ %lftr.wideiv = trunc i64 %indvars.iv.next to i32
+ %exitcond = icmp eq i32 %lftr.wideiv, %itr
+ br i1 %exitcond, label %for.inc8, label %for.body3
+
+for.inc8: ; preds = %for.body3, %for.cond1.preheader
+ %j.1.lcssa = phi i32 [ %j.022, %for.cond1.preheader ], [ %itr, %for.body3 ]
+ %indvars.iv.next24 = add nuw nsw i64 %indvars.iv23, 1
+ %lftr.wideiv25 = trunc i64 %indvars.iv.next24 to i32
+ %exitcond26 = icmp eq i32 %lftr.wideiv25, %itr
+ br i1 %exitcond26, label %for.end10, label %for.cond1.preheader
+
+for.end10: ; preds = %for.inc8, %entry
+ ret i32 undef
+}
+
diff --git a/test/Analysis/LoopAccessAnalysis/store-to-invariant-check2.ll b/test/Analysis/LoopAccessAnalysis/store-to-invariant-check2.ll
new file mode 100644
index 000000000000..4da090689492
--- /dev/null
+++ b/test/Analysis/LoopAccessAnalysis/store-to-invariant-check2.ll
@@ -0,0 +1,54 @@
+; RUN: opt < %s -loop-accesses -analyze | FileCheck %s
+
+; Test to confirm LAA will not find store to invariant address.
+; Inner loop has no store to invariant address.
+;
+; for(; i < itr; i++) {
+; for(; j < itr; j++) {
+; var2[j] = var2[j] + var1[i];
+; }
+; }
+
+; CHECK: Store to invariant address was not found in loop.
+; CHECK-NOT: Store to invariant address was found in loop.
+
+
+define i32 @foo(i32* nocapture readonly %var1, i32* nocapture %var2, i32 %itr) #0 {
+entry:
+ %cmp20 = icmp eq i32 %itr, 0
+ br i1 %cmp20, label %for.end10, label %for.cond1.preheader
+
+for.cond1.preheader: ; preds = %entry, %for.inc8
+ %indvars.iv23 = phi i64 [ %indvars.iv.next24, %for.inc8 ], [ 0, %entry ]
+ %j.022 = phi i32 [ %j.1.lcssa, %for.inc8 ], [ 0, %entry ]
+ %cmp218 = icmp ult i32 %j.022, %itr
+ br i1 %cmp218, label %for.body3.lr.ph, label %for.inc8
+
+for.body3.lr.ph: ; preds = %for.cond1.preheader
+ %arrayidx5 = getelementptr inbounds i32, i32* %var1, i64 %indvars.iv23
+ %0 = zext i32 %j.022 to i64
+ br label %for.body3
+
+for.body3: ; preds = %for.body3, %for.body3.lr.ph
+ %indvars.iv = phi i64 [ %0, %for.body3.lr.ph ], [ %indvars.iv.next, %for.body3 ]
+ %arrayidx = getelementptr inbounds i32, i32* %var2, i64 %indvars.iv
+ %1 = load i32, i32* %arrayidx, align 4
+ %2 = load i32, i32* %arrayidx5, align 4
+ %add = add nsw i32 %2, %1
+ store i32 %add, i32* %arrayidx, align 4
+ %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+ %lftr.wideiv = trunc i64 %indvars.iv.next to i32
+ %exitcond = icmp eq i32 %lftr.wideiv, %itr
+ br i1 %exitcond, label %for.inc8, label %for.body3
+
+for.inc8: ; preds = %for.body3, %for.cond1.preheader
+ %j.1.lcssa = phi i32 [ %j.022, %for.cond1.preheader ], [ %itr, %for.body3 ]
+ %indvars.iv.next24 = add nuw nsw i64 %indvars.iv23, 1
+ %lftr.wideiv25 = trunc i64 %indvars.iv.next24 to i32
+ %exitcond26 = icmp eq i32 %lftr.wideiv25, %itr
+ br i1 %exitcond26, label %for.end10, label %for.cond1.preheader
+
+for.end10: ; preds = %for.inc8, %entry
+ ret i32 undef
+}
+
diff --git a/test/Analysis/LoopAccessAnalysis/store-to-invariant-check3.ll b/test/Analysis/LoopAccessAnalysis/store-to-invariant-check3.ll
new file mode 100644
index 000000000000..18315a59dc3a
--- /dev/null
+++ b/test/Analysis/LoopAccessAnalysis/store-to-invariant-check3.ll
@@ -0,0 +1,53 @@
+; RUN: opt < %s -loop-accesses -analyze | FileCheck %s
+
+; Test to confirm LAA will find store to invariant address.
+; Inner loop has a store to invariant address.
+;
+; for(; i < itr; i++) {
+; for(; j < itr; j++) {
+; var1[j] = ++var2[i] + var1[j];
+; }
+; }
+
+; CHECK: Store to invariant address was found in loop.
+
+define void @foo(i32* nocapture %var1, i32* nocapture %var2, i32 %itr) #0 {
+entry:
+ %cmp20 = icmp sgt i32 %itr, 0
+ br i1 %cmp20, label %for.cond1.preheader, label %for.end11
+
+for.cond1.preheader: ; preds = %entry, %for.inc9
+ %indvars.iv23 = phi i64 [ %indvars.iv.next24, %for.inc9 ], [ 0, %entry ]
+ %j.022 = phi i32 [ %j.1.lcssa, %for.inc9 ], [ 0, %entry ]
+ %cmp218 = icmp slt i32 %j.022, %itr
+ br i1 %cmp218, label %for.body3.lr.ph, label %for.inc9
+
+for.body3.lr.ph: ; preds = %for.cond1.preheader
+ %arrayidx = getelementptr inbounds i32, i32* %var2, i64 %indvars.iv23
+ %0 = sext i32 %j.022 to i64
+ br label %for.body3
+
+for.body3: ; preds = %for.body3, %for.body3.lr.ph
+ %indvars.iv = phi i64 [ %0, %for.body3.lr.ph ], [ %indvars.iv.next, %for.body3 ]
+ %1 = load i32, i32* %arrayidx, align 4
+ %inc = add nsw i32 %1, 1
+ store i32 %inc, i32* %arrayidx, align 4
+ %arrayidx5 = getelementptr inbounds i32, i32* %var1, i64 %indvars.iv
+ %2 = load i32, i32* %arrayidx5, align 4
+ %add = add nsw i32 %inc, %2
+ store i32 %add, i32* %arrayidx5, align 4
+ %indvars.iv.next = add nsw i64 %indvars.iv, 1
+ %lftr.wideiv = trunc i64 %indvars.iv.next to i32
+ %exitcond = icmp eq i32 %lftr.wideiv, %itr
+ br i1 %exitcond, label %for.inc9, label %for.body3
+
+for.inc9: ; preds = %for.body3, %for.cond1.preheader
+ %j.1.lcssa = phi i32 [ %j.022, %for.cond1.preheader ], [ %itr, %for.body3 ]
+ %indvars.iv.next24 = add nuw nsw i64 %indvars.iv23, 1
+ %lftr.wideiv25 = trunc i64 %indvars.iv.next24 to i32
+ %exitcond26 = icmp eq i32 %lftr.wideiv25, %itr
+ br i1 %exitcond26, label %for.end11, label %for.cond1.preheader
+
+for.end11: ; preds = %for.inc9, %entry
+ ret void
+}
diff --git a/test/Analysis/LoopAccessAnalysis/underlying-objects-1.ll b/test/Analysis/LoopAccessAnalysis/underlying-objects-1.ll
new file mode 100644
index 000000000000..44820ed37222
--- /dev/null
+++ b/test/Analysis/LoopAccessAnalysis/underlying-objects-1.ll
@@ -0,0 +1,47 @@
+; RUN: opt -basicaa -loop-accesses -analyze < %s | FileCheck %s
+
+; In:
+;
+; store_ptr = A;
+; load_ptr = &A[2];
+; for (i = 0; i < n; i++)
+; *store_ptr++ = *load_ptr++ *10; // A[i] = A[i+2] * 10
+;
+; make sure, we look through the PHI to conclude that store_ptr and load_ptr
+; both have A as their underlying object. The dependence is safe for
+; vectorization requiring no memchecks.
+;
+; Otherwise we would try to prove independence with a memcheck that is going
+; to always fail.
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.10.0"
+
+; CHECK: Memory dependences are safe{{$}}
+
+define void @f(i8* noalias %A, i64 %width) {
+for.body.preheader:
+ %A_ahead = getelementptr inbounds i8, i8* %A, i64 2
+ br label %for.body
+
+for.body:
+ %i = phi i64 [ %i.1, %for.body ], [ 0, %for.body.preheader ]
+ %load_ptr = phi i8* [ %load_ptr.1, %for.body ], [ %A_ahead, %for.body.preheader ]
+ %store_ptr = phi i8* [ %store_ptr.1, %for.body ], [ %A, %for.body.preheader ]
+
+ %loadA = load i8, i8* %load_ptr, align 1
+
+ %mul = mul i8 %loadA, 10
+
+ store i8 %mul, i8* %store_ptr, align 1
+
+ %load_ptr.1 = getelementptr inbounds i8, i8* %load_ptr, i64 1
+ %store_ptr.1 = getelementptr inbounds i8, i8* %store_ptr, i64 1
+ %i.1 = add nuw i64 %i, 1
+
+ %exitcond = icmp eq i64 %i.1, %width
+ br i1 %exitcond, label %for.end, label %for.body
+
+for.end:
+ ret void
+}
diff --git a/test/Analysis/LoopAccessAnalysis/underlying-objects-2.ll b/test/Analysis/LoopAccessAnalysis/underlying-objects-2.ll
new file mode 100644
index 000000000000..d0bed68188db
--- /dev/null
+++ b/test/Analysis/LoopAccessAnalysis/underlying-objects-2.ll
@@ -0,0 +1,90 @@
+; RUN: opt -basicaa -loop-accesses -analyze < %s | 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: Interesting 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
+}
diff --git a/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll b/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll
new file mode 100644
index 000000000000..ce8b86ba2c51
--- /dev/null
+++ b/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll
@@ -0,0 +1,58 @@
+; RUN: opt -loop-accesses -analyze < %s | FileCheck %s
+
+; Analyze this loop:
+; for (i = 0; i < n; i++)
+; A[i + 1] = A[i] * B[i] * C[i];
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.10.0"
+
+; CHECK: Report: unsafe dependent memory operations in loop
+; CHECK-NEXT: Interesting Dependences:
+; CHECK-NEXT: Backward:
+; CHECK-NEXT: %loadA = load i16, i16* %arrayidxA, align 2 ->
+; CHECK-NEXT: store i16 %mul1, i16* %arrayidxA_plus_2, align 2
+; CHECK: Run-time memory checks:
+; CHECK-NEXT: 0:
+; CHECK-NEXT: %arrayidxA_plus_2 = getelementptr inbounds i16, i16* %a, i64 %add
+; CHECK-NEXT: %arrayidxB = getelementptr inbounds i16, i16* %b, i64 %storemerge3
+; CHECK-NEXT: 1:
+; CHECK-NEXT: %arrayidxA_plus_2 = getelementptr inbounds i16, i16* %a, i64 %add
+; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %storemerge3
+
+@B = common global i16* null, align 8
+@A = common global i16* null, align 8
+@C = common global i16* null, align 8
+
+define void @f() {
+entry:
+ %a = load i16*, i16** @A, align 8
+ %b = load i16*, i16** @B, align 8
+ %c = load i16*, i16** @C, align 8
+ br label %for.body
+
+for.body: ; preds = %for.body, %entry
+ %storemerge3 = phi i64 [ 0, %entry ], [ %add, %for.body ]
+
+ %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %storemerge3
+ %loadA = load i16, i16* %arrayidxA, align 2
+
+ %arrayidxB = getelementptr inbounds i16, i16* %b, i64 %storemerge3
+ %loadB = load i16, i16* %arrayidxB, align 2
+
+ %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %storemerge3
+ %loadC = load i16, i16* %arrayidxC, align 2
+
+ %mul = mul i16 %loadB, %loadA
+ %mul1 = mul i16 %mul, %loadC
+
+ %add = add nuw nsw i64 %storemerge3, 1
+ %arrayidxA_plus_2 = getelementptr inbounds i16, i16* %a, i64 %add
+ store i16 %mul1, i16* %arrayidxA_plus_2, align 2
+
+ %exitcond = icmp eq i64 %add, 20
+ br i1 %exitcond, label %for.end, label %for.body
+
+for.end: ; preds = %for.body
+ ret void
+}