aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2009-08-26 14:53:06 +0000
committerDan Gohman <gohman@apple.com>2009-08-26 14:53:06 +0000
commit2385e0e22ca482f2896dfa975a08db2f54926c09 (patch)
tree263a06bef4db6a85627348a6003f7193600a67b2 /test
parente2cb91203917152ea462073628f1597c3d54aa37 (diff)
Create a ScalarEvolution-based AliasAnalysis implementation.
This is a simple AliasAnalysis implementation which works by making ScalarEvolution queries. ScalarEvolution has a more complete understanding of arithmetic than BasicAA's collection of ad-hoc checks, so it handles some cases that BasicAA misses, for example p[i] and p[i+1] within the same iteration of a loop. This is currently experimental. It may be that the main use for this pass will be to help find cases where BasicAA can be profitably extended, or to help in the development of the overall AliasAnalysis infrastructure, however it's also possible that it could grow up to become a directly useful pass. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@80098 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test')
-rw-r--r--test/Analysis/ScalarEvolution/scev-aa.ll194
1 files changed, 194 insertions, 0 deletions
diff --git a/test/Analysis/ScalarEvolution/scev-aa.ll b/test/Analysis/ScalarEvolution/scev-aa.ll
new file mode 100644
index 0000000000..2208b3db4d
--- /dev/null
+++ b/test/Analysis/ScalarEvolution/scev-aa.ll
@@ -0,0 +1,194 @@
+; RUN: llvm-as < %s | opt -scev-aa -aa-eval -print-all-alias-modref-info \
+; RUN: |& FileCheck %s
+
+; At the time of this writing, all of these CHECK lines are cases that
+; plain -basicaa misses.
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64"
+
+; p[i] and p[i+1] don't alias.
+
+; CHECK: Function: loop: 3 pointers, 0 call sites
+; CHECK: NoAlias: double* %pi, double* %pi.next
+
+define void @loop(double* nocapture %p, i64 %n) nounwind {
+entry:
+ %j = icmp sgt i64 %n, 0
+ br i1 %j, label %bb, label %return
+
+bb:
+ %i = phi i64 [ 0, %entry ], [ %i.next, %bb ]
+ %pi = getelementptr double* %p, i64 %i
+ %i.next = add i64 %i, 1
+ %pi.next = getelementptr double* %p, i64 %i.next
+ %x = load double* %pi
+ %y = load double* %pi.next
+ %z = fmul double %x, %y
+ store double %z, double* %pi
+ %exitcond = icmp eq i64 %i.next, %n
+ br i1 %exitcond, label %return, label %bb
+
+return:
+ ret void
+}
+
+; Slightly more involved: p[j][i], p[j][i+1], and p[j+1][i] don't alias.
+
+; CHECK: Function: nestedloop: 4 pointers, 0 call sites
+; CHECK: NoAlias: double* %pi.j, double* %pi.next.j
+; CHECK: NoAlias: double* %pi.j, double* %pi.j.next
+; CHECK: NoAlias: double* %pi.j.next, double* %pi.next.j
+
+define void @nestedloop(double* nocapture %p, i64 %m) nounwind {
+entry:
+ %k = icmp sgt i64 %m, 0
+ br i1 %k, label %guard, label %return
+
+guard:
+ %l = icmp sgt i64 91, 0
+ br i1 %l, label %outer.loop, label %return
+
+outer.loop:
+ %j = phi i64 [ 0, %guard ], [ %j.next, %outer.latch ]
+ br label %bb
+
+bb:
+ %i = phi i64 [ 0, %outer.loop ], [ %i.next, %bb ]
+ %i.next = add i64 %i, 1
+
+ %e = add i64 %i, %j
+ %pi.j = getelementptr double* %p, i64 %e
+ %f = add i64 %i.next, %j
+ %pi.next.j = getelementptr double* %p, i64 %f
+ %x = load double* %pi.j
+ %y = load double* %pi.next.j
+ %z = fmul double %x, %y
+ store double %z, double* %pi.j
+
+ %o = add i64 %j, 91
+ %g = add i64 %i, %o
+ %pi.j.next = getelementptr double* %p, i64 %g
+ %a = load double* %pi.j.next
+ %b = fmul double %x, %a
+ store double %b, double* %pi.j.next
+
+ %exitcond = icmp eq i64 %i.next, 91
+ br i1 %exitcond, label %outer.latch, label %bb
+
+outer.latch:
+ %j.next = add i64 %j, 91
+ %h = icmp eq i64 %j.next, %m
+ br i1 %h, label %return, label %outer.loop
+
+return:
+ ret void
+}
+
+; Even more involved: same as nestedloop, but with a variable extent.
+; When n is 1, p[j+1][i] does alias p[j][i+1], and there's no way to
+; prove whether n will be greater than 1, so that relation will always
+; by MayAlias. The loop is guarded by a n > 0 test though, so
+; p[j+1][i] and p[j][i] can theoretically be determined to be NoAlias,
+; however the analysis currently doesn't do that.
+; TODO: Make the analysis smarter and turn that MayAlias into a NoAlias.
+
+; CHECK: Function: nestedloop_more: 4 pointers, 0 call sites
+; CHECK: NoAlias: double* %pi.j, double* %pi.next.j
+; CHECK: MayAlias: double* %pi.j, double* %pi.j.next
+
+define void @nestedloop_more(double* nocapture %p, i64 %n, i64 %m) nounwind {
+entry:
+ %k = icmp sgt i64 %m, 0
+ br i1 %k, label %guard, label %return
+
+guard:
+ %l = icmp sgt i64 %n, 0
+ br i1 %l, label %outer.loop, label %return
+
+outer.loop:
+ %j = phi i64 [ 0, %guard ], [ %j.next, %outer.latch ]
+ br label %bb
+
+bb:
+ %i = phi i64 [ 0, %outer.loop ], [ %i.next, %bb ]
+ %i.next = add i64 %i, 1
+
+ %e = add i64 %i, %j
+ %pi.j = getelementptr double* %p, i64 %e
+ %f = add i64 %i.next, %j
+ %pi.next.j = getelementptr double* %p, i64 %f
+ %x = load double* %pi.j
+ %y = load double* %pi.next.j
+ %z = fmul double %x, %y
+ store double %z, double* %pi.j
+
+ %o = add i64 %j, %n
+ %g = add i64 %i, %o
+ %pi.j.next = getelementptr double* %p, i64 %g
+ %a = load double* %pi.j.next
+ %b = fmul double %x, %a
+ store double %b, double* %pi.j.next
+
+ %exitcond = icmp eq i64 %i.next, %n
+ br i1 %exitcond, label %outer.latch, label %bb
+
+outer.latch:
+ %j.next = add i64 %j, %n
+ %h = icmp eq i64 %j.next, %m
+ br i1 %h, label %return, label %outer.loop
+
+return:
+ ret void
+}
+
+; ScalarEvolution expands field offsets into constants, which allows it to
+; do aggressive analysis. Contrast this with BasicAA, which works by
+; recognizing GEP idioms.
+
+%struct.A = type { %struct.B, i32, i32 }
+%struct.B = type { double }
+
+; CHECK: Function: foo: 7 pointers, 0 call sites
+; CHECK: NoAlias: %struct.B* %B, i32* %Z
+; CHECK: NoAlias: %struct.B* %B, %struct.B* %C
+; CHECK: MustAlias: %struct.B* %C, i32* %Z
+; CHECK: NoAlias: %struct.B* %B, i32* %X
+; CHECK: MustAlias: i32* %X, i32* %Z
+; CHECK: MustAlias: %struct.B* %C, i32* %Y
+; CHECK: MustAlias: i32* %X, i32* %Y
+
+define void @foo() {
+entry:
+ %A = alloca %struct.A
+ %B = getelementptr %struct.A* %A, i32 0, i32 0
+ %Q = bitcast %struct.B* %B to %struct.A*
+ %Z = getelementptr %struct.A* %Q, i32 0, i32 1
+ %C = getelementptr %struct.B* %B, i32 1
+ %X = bitcast %struct.B* %C to i32*
+ %Y = getelementptr %struct.A* %A, i32 0, i32 1
+ ret void
+}
+
+; CHECK: Function: bar: 7 pointers, 0 call sites
+; CHECK: NoAlias: %struct.B* %N, i32* %P
+; CHECK: NoAlias: %struct.B* %N, %struct.B* %R
+; CHECK: MustAlias: %struct.B* %R, i32* %P
+; CHECK: NoAlias: %struct.B* %N, i32* %W
+; CHECK: MustAlias: i32* %P, i32* %W
+; CHECK: MustAlias: %struct.B* %R, i32* %V
+; CHECK: MustAlias: i32* %V, i32* %W
+
+define void @bar() {
+ %M = alloca %struct.A
+ %N = getelementptr %struct.A* %M, i32 0, i32 0
+ %O = bitcast %struct.B* %N to %struct.A*
+ %P = getelementptr %struct.A* %O, i32 0, i32 1
+ %R = getelementptr %struct.B* %N, i32 1
+ %W = bitcast %struct.B* %R to i32*
+ %V = getelementptr %struct.A* %M, i32 0, i32 1
+ ret void
+}
+
+; CHECK: 13 no alias responses
+; CHECK: 26 may alias responses
+; CHECK: 18 must alias responses