Title: Data Dependence Analysis
1Data Dependence Analysis
- Dependence Graphs
- Preparatory Transformations
2Data Dependence
- DO I 1, N
- DO K 2, N-1
- A ( I , K) B ( I ) C ( I ) K
- B ( I ) B ( I1 ) D ( I )
- D( I-1) A ( I, K-1) K
- END DO
- END DO
?
3Data Dependence Graph
- We may represent all dependence relations in a
loop nest by a dependence graph. - It contains one node for each statement involved
in one or more dependence relations. - It has a directed edge to represent each
dependence relation. The edge connects the two
statements involved. - An edge may be annotated with the corresponding
array, the level, kind of dependence, or other
info.
S1
Nodes correspond to statements Edges correspond
to dependences
d
S2
4Data Dependences
Dependence graphs are widely used to represent
data dependences in a region of a program
(usually a single loop nest), including for human
consumption.
5Data Dependence Graph
- DO I 1, N
- DO J 1, M
- S1 A (I, J) B(I1, J-1)
- S2 B(I, J) A(I, J) K
- S3 C(I, J) C(I,J) B(I, J)
- ENDDO
- ENDDO
- S1(i,j) ?t? S2(i,j) for all i,j in range
- What about the rest??
S1
S2
S3
6Data Dependence Testing
Goal of dependence testing prove independence of
as many pairs of statements in a loop nest as
possible
- The more freedom the compiler has to reorder
statements in a loop nest, the more opportunities
it has to optimize. - Thus a small dependence graph (few nodes and few
edges) is a good sign! - However, reuse is good for cache, so some
dependences are not bad.
7DO Loop Normalization
- Purpose simplify implementation of dependence
testing, other loop transformations - They can assume that loop variable has positive
increment, known lower bound (usually 0 or 1) - Downside May lead to slight increase in
computation - Action Standardizes loop iteration space
- Applied to loops that do not have lower bound and
stride of 1 - Transformation (here) sets lower bound and stride
to 1 - Makes any changes needed to ensure that
computation within loop is identical to that of
original loop
The compiler normalizes other constructs to
simplify IR
8Loop Normalization
NB Compiler has to work to simplify these
expressions!
- DO I 10, 100, 2
- A(I) B(I1) B(I-1)
- END DO
- becomes
- DO I 1, 46
- A(10 (I 1)2) B( 10 (I-1)2 1) B(
10 (I-1)2 -1) - END DO
- I 102
Standardizes format of loops to simplify
dependence testing. Which version would you
prefer to see?
9Scalar Forward Substitution
- Purpose simplify, improve results of dependence
testing - Thus enables other loop optimizations
- More array expressions can be handled by standard
tests - Downside May lead to slight increase in
computation - Approach Removes variables from array subscript
expressions - Applied to array subscript expressions that are
not affine in loop bounds - Transformation replaces variable in subscript
expression with affine expression in loop bounds - Only possible if variable is defined as affine
expression in loop bounds
10Scalar Forward Substitution
- DO I 1, 100
- K 2 I 1
- A(K) B(K) B(K-1)
- D(K) A(K-2) A(K-1)
- END DO
- becomes
- DO I 1, 100
- A(2I1) B(2I1) B(2I1 -1) ! some
expressions - D(2I1) A(2I1 -2) A(2I1 -1) ! can
be simplified - END DO
Why might the programmer write the first version?
11Induction Variable Substitution
- Purpose improve results of dependence testing
- Thus enables other optimizations
- More array expressions can be handled by standard
tests - Downside May lead to slight increase in
computation - Action Removes variables from array subscript
expressions - Applied to array subscript expressions that
contain induction variables - Transformation replaces induction variable in
subscript expression with affine expression in
loop bounds - Induction variables are defined in terms of loop
variable this way.
12What is an Induction Variable?
- A variable v in loop L is a basic (simple)
induction variable iff - all assignments to v in L have form v v c,
where c is a constant - A variable v in loop L is a general induction
variable iff - v is a basic induction variable or
- there is one assignment to v in L with the form v
c v1 k, where c, k are both constants and
v1 is a basic induction variable - Induction variables are common in older
application codes
13Induction Variable Substitution
- Replace uses of induction variables by
expressions involving the DO variables only. - Let v be a basic induction variable defined by
precisely one statement v v c. - Let v0 be the value of v in iteration 1 before
this is executed. - Then, at the same place in iteration 2 its value
is v0 c in iteration 3 it is v0 2 c, etc. - We may replace occurrences of v by the expression
v0 I c, where I is the loops DO variable.
14Example
- K
- DO I 1, 100
- K K 2
- A(K) B(K) B(K-1)
- END DO
- becomes
- K0
- DO I 1, 100
- A(K0 (-2) I) B(K0 2I) B(K0 2I
-1) - END DO
- K
Subscript expressions can be simplified. Note
that expression simplification must be repeatedly
performed by compiler.
15Wrap-Around Variable Substitution
- Purpose same as for induction variable
substitution - This is one way to handle occurrences of
induction variables that are used before they are
defined - Peels off first iteration from a loop
- Transformation removes first assignment from loop
- also modifies loop bounds and removes statement
that defines induction variable - Loop peeling is a much more general technique.
16Wrap-Around Variable Substitution
- K
- DO I 1, 100
- A(K) B(K) B(K-1)
- K K 2
- END DO
- becomes
- K0 K
- A(K0) B(K0) B(K0-1)
- DO I 2, 100
- A(K0 2 (-2) I) B(K0 2 2I) B(K0
2 2I -1) - END DO
- K
A useful approach whenever first or last
iteration requires special handling
17Scalar Renaming
- Purpose simplify, improve data dependence
testing - This is one way to remove the need to check
whether definitions reach certain uses - Without this check we may erroneously detect
dependences - Transformation renames some scalar variables
- Ensures that only one definition reaches a use
- Static single assignment form systematically
applies this principle throughout a code (only
one definition of a variable)
18Scalar Renaming
- Ensure distinct regions of use for different
definitions. - Given variable v, statements S and S, each of
which defines v, where DU(S) and DU(S) have no
common statements. - Then replace v in S and DU(S) by a
compiler-generated name.
Notice this is inverse of another optimization
that aims to save memory by reusing variable.
Strange but true there are often pairs of
transformations that have the opposite goal. One
of them undoes the other.