[llvm] r194527 - delinearization of arrays
Sebastian Pop
spop at codeaurora.org
Wed Nov 13 11:55:34 PST 2013
Hi,
Hal Finkel wrote:
> ----- Original Message -----
> >
> > On Tue, Nov 12, 2013 at 2:47 PM, Sebastian Pop < spop at codeaurora.org
> > > wrote:
> >
> >
> > delinearization of arrays
> > This seems like a really underwhelming commit log... ;] There is
> > quite a lot going on here, and it would be helpful to give an
> > overview for those who haven't followed the entire review of this
> > work.
> >
The core of the patch adds one function to the SCEV tools: delinearize. That
allows the delinearization of a SCEV representing a memory access function.
For example: when analyzing the memory access A[i][j][k] in this loop nest
+; void foo(long n, long m, long o, double A[n][m][o]) {
+;
+; for (long i = 0; i < n; i++)
+; for (long j = 0; j < m; j++)
+; for (long k = 0; k < o; k++)
+; A[i][j][k] = 1.0;
+; }
the delinearization input is the following AddRec SCEV:
+; AddRec: {{{%A,+,(8 * %m * %o)}<%for.i>,+,(8 * %o)}<%for.j>,+,8}<%for.k>
>From this SCEV, we are able to say that the base offset of the access is %A
because it appears as an offset that does not divide any of the strides in the
loops:
+; CHECK: Base offset: %A
and then delinearize determines the size of some of the dimensions of the array
as these are the multiples by which the strides are happening:
+; CHECK: ArrayDecl[UnknownSize][%m][%o] with elements of sizeof(double) bytes.
Note that the outermost dimension remains of UnknownSize because there are no
strides that would help identifying the size of the last dimension: when the
array has been statically allocated, one could compute the size of that
dimension by dividing the overall size of the array by the size of the known
dimensions: %m * %o * 8.
Finally delinearize provides the access functions for the array reference that
does correspond to A[i][j][k] of the above C testcase:
+; CHECK: ArrayRef[{0,+,1}<nuw><nsw><%for.i>][{0,+,1}<nuw><nsw><%for.j>][{0,+,1}<nuw><nsw><%for.k>]
The testcases are checking the output of a function pass: DelinearizationPass
that walks through all loads and stores of a function asking for the SCEV of the
memory access with respect to all enclosing loops, calling SCEV->delinearize on
that and printing the results.
The patch also calls SCEV->delinearize within Preston's classical data
dependence analysis. The flag controlling the call to delinearize from the data
dependence analysis "-da-delinearize" is turned off by default for now.
Attached a patch that shows the results of the dependence analysis with
-da-delinearize turned on. There are more MIV tests (Multiple Induction
Variables dependence test) that can be disambiguated as carrying no dependence
(as SCEV->delinearize translates MIV tests into SIV tests (Single IV tests)):
diff --git a/test/Analysis/DependenceAnalysis/Banerjee.ll b/test/Analysis/DependenceAnalysis/Banerjee.ll
index 09e8fd2..65a1f68 100644
--- a/test/Analysis/DependenceAnalysis/Banerjee.ll
+++ b/test/Analysis/DependenceAnalysis/Banerjee.ll
@@ -490,7 +490,7 @@ entry:
br label %for.cond1.preheader
; CHECK: 'Dependence Analysis' for function 'banerjee9':
-; CHECK: da analyze - output [* *]!
+; CHECK: da analyze - none!
; CHECK: da analyze - flow [<= =|<]!
; CHECK: da analyze - confused!
; CHECK: da analyze - none!
diff --git a/test/Analysis/DependenceAnalysis/GCD.ll b/test/Analysis/DependenceAnalysis/GCD.ll
index bb31d11..18942aa 100644
--- a/test/Analysis/DependenceAnalysis/GCD.ll
+++ b/test/Analysis/DependenceAnalysis/GCD.ll
@@ -18,7 +18,7 @@ entry:
; CHECK: da analyze - output [* *]!
; CHECK: da analyze - flow [=> *|<]!
; CHECK: da analyze - confused!
-; CHECK: da analyze - input [* *]!
+; CHECK: da analyze - none!
; CHECK: da analyze - confused!
; CHECK: da analyze - none!
@@ -71,7 +71,7 @@ entry:
; CHECK: da analyze - output [* *]!
; CHECK: da analyze - none!
; CHECK: da analyze - confused!
-; CHECK: da analyze - input [* *]!
+; CHECK: da analyze - none!
; CHECK: da analyze - confused!
; CHECK: da analyze - none!
@@ -125,7 +125,7 @@ entry:
; CHECK: da analyze - output [* *]!
; CHECK: da analyze - none!
; CHECK: da analyze - confused!
-; CHECK: da analyze - input [* *]!
+; CHECK: da analyze - none!
; CHECK: da analyze - confused!
; CHECK: da analyze - none!
@@ -353,10 +353,10 @@ entry:
br i1 %cmp4, label %for.cond1.preheader.preheader, label %for.end12
; CHECK: 'Dependence Analysis' for function 'gcd6'
-; CHECK: da analyze - output [* *]!
+; CHECK: da analyze - flow [0 =>|<]!
; CHECK: da analyze - none!
; CHECK: da analyze - confused!
-; CHECK: da analyze - input [* *]!
+; CHECK: da analyze - none!
; CHECK: da analyze - confused!
; CHECK: da analyze - output [* *]!
I'm not sure why we have this change:
-; CHECK: da analyze - output [* *]!
+; CHECK: da analyze - flow [0 =>|<]!
it looks like an error... although, I have not investigated why this happens.
>
> Yea ;)
>
> Also, please comment on the current state of any known correctness issues. In
> response to one of Arnold's comments about dealing with
> inner-dimension-overflow cases, you had said, "Right. It looks like the data
> dependence analysis needs more code to support the contiguous memory
> semantics...", and I'd like to have a clear understanding on the resolution to
> that.
The data dependence analysis has to bound each array access dimension by the
number of elements that the delinearization has determined: i.e., for a
delinearized access of the form (same C testcase as above)
> +; AddRec: {{{%A,+,(8 * %m * %o)}<%for.i>,+,(8 * %o)}<%for.j>,+,8}<%for.k>
> +; CHECK: Base offset: %A
> +; CHECK: ArrayDecl[UnknownSize][%m][%o] with elements of sizeof(double) bytes.
> +; CHECK: ArrayRef[{0,+,1}<nuw><nsw><%for.i>][{0,+,1}<nuw><nsw><%for.j>][{0,+,1}<nuw><nsw><%for.k>]
We will have to add to the data dependence test these two constraints:
"{0,+,1}<nuw><nsw><%for.k> < %o"
"{0,+,1}<nuw><nsw><%for.j> < %m"
to avoid having memory accesses overflow from one dimension into another.
This is related to the problem of determining the existence of data dependences
in array accesses using a different number of subscripts: in C one can decide to
access an array A[100][100]; as A[0][9999] or *A[9999], etc.
I am currently not sure how to add these constraints in the classical data
dependence test in lib/Analysis/DependenceAnalysis.cpp.
On the other hand, adding these constraints to Polly is a piece of cake: you
just drop the extra constraints in the bag of constraints that Polly uses to
formulate the dependence test, and then ISL does the rest. I will post a patch
that integrates SCEV->delinearize in Polly.
> > (And also, awesome to see all of that work paying off!)
SCEV->delinearize will be beneficial in the context of data dependence tests in
multiple nested loops. LLVM would need a loop nest optimizer, a vectorizer, or a
parallelizer on top of lib/Analysis/DependenceAnalysis.cpp (not sure how long
that would take).
On the other hand, Polly would be the first to see the benefits from
SCEV->delinearize: I hope that Polly will start transforming most of the
test-suite/pollybench.
Sebastian
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
More information about the llvm-commits
mailing list