[PATCH] D50433: A New Divergence Analysis for LLVM

Simon Moll via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 24 10:28:52 PDT 2018


simoll added a comment.

In https://reviews.llvm.org/D50433#1212500, @alex-t wrote:

> >> For given branch all the blocks where PHI nodes must be inserted belongs to the branch parent block dominance frontier.
> > 
> > The problem with DF is that it implicitly assumes that there exists a definition at the function entry (see http://www.cs.utexas.edu/~pingali/CS380C/2010/papers/ssaCytron.pdf, comment below last equation of page 17).
> >  So, we would get imprecise results.
>
> I'm not sure that I understand you correct...
>  I still do not get an idea what do you mean by "imprecise results". The assumption in the paper you have referred looks reasonable.
>  Let's say we have 2 disjoint paths from Entry to block X and you have a use of some value V in X.
>
>         Entry
>        /   \
>       A     E
>     /  \     \
>   B     C     F  [v0 = 1]
>     \  /      |
>      D       /
>       \ _   /
>           X   v1 = PHI (1, F, undef, Entry)
>  
>  
>         Entry__
>        /       \
>     A [v1 = 2]  E
>    /  \         |
>   B     C       F  [v0 = 1]
>    \  /      __/
>     D       /
>       \ _  /
>         X v2 = PHI (1, F, 2, A)
>   
>
> Irrelevant of the definition in Entry, divergent branch in Entry makes the PHI in X divergent.
>
> Each of this 2 paths should contain a definition for V. It does not matter in entry block or in one of it's successors.
>  You either have a normal PHI or a PHI with undef incoming value. How to handle undef depends of your decision.
>  You may conservatively consider any undef as divergent. This make your PHI divergent by data-dependency.


The SDA detects re-convergence points of disjoint divergent paths from a branch.
There aren't any real PHI nodes involved.
The PHI nodes are rather a vehicle to demonstrate the reduction to SSA construction.
The incoming values in the reduction are always uniform (x0 = <SomeConstant>).

Let's pretend we actually generated the assignments and we were really construction SSA form.

     Entry
     /   \
    B     C
   /  \    \
  D    E-->F
   \  /   /
    G--->H

B contains a divergent branch. So, we emit the assigments "x = 0" in D and "x = 1" in E.
SSA construction will generate PHI nodes in F, G and H.
However, there aren't two disjoint path from B to F.
The root cause of the "spurious" phi node in F is the implicit definition "undef" at Entry.
In short, vanilla SSA construction gives imprecise result.

> 
> 
>> Control-dependence/PDT does not give you correct results (see my earlier example in https://reviews.llvm.org/D50433#1205934).
> 
> Oh.. :)   Please forget of the set differences that I mentioned. It was mentioned mistakenly.
>  You was concerned about using non-filtered PDFs since they could produce over-conservative results.
>  You probably meant not PDF but iterated PDF  (PDF+)

Yep, my bad. The notation should be:
DF(X)  := the set of all blocks B that X does not dominate but that have a predecessor that X dominates.
PDF(X) := set set of all blocks B that X does not post-dominate but that have a successor that X post-dominates (aka control dependence).
PDF+   := the transitive closure of the post-dominance frontier.
DF+    := the transitive closure of the dominance frontier.

> I meant just PDF - without closure over all predecessors.
> 
>        Entry
>      /       \
>     A_____    E
>    /       \   \
>   B[v1 = 2] C  F  [v0 = 1]
>    \  _____/ _/
>     D       /
>       \ _  /
>         X v2 = PHI (1, F, 2, A)
>    
> 
> PDF(B) = {A}  DF+(B) = {A, Entry}
>  PDF(F) = DF+(F) = {Entry}
> 
> For PHI in X we have 2 source blocks - B and F so we only have to examine branches in A and Entry
>  If the second definition of V was in C instead of F we'd only look at the branch in A.
> 
> For your example with switch:
> 
> +----A----+
> 
> |  |  |
> |
> 
> C0  C1    D
>  \   |    [..]
> 
>   \  |
>     J
> 
> PDF(C0) = {A}
>  PDF(C1) = {A}
> 
> Let's say in J we have v2 = PHI(v0, A. v1, C0)  we should examine A terminator because PDF(C0) = {A}, PDF(A) = {}

Sorry, i am struggeling to follow.
Do you take the union of the PDF(P) for each immediate predecessor P of X? (where X is a potential join point).
That gives you invalid results.

        A
      /   \
     B     C
   /  \   /  \
  D     E     F
   \  /   \  /
     G     H
     \    /
        I

PDF(G) = {E, B}
PDF(H) = {E, C}

PDF(G) join PDF(H) =  {E, B, C}   (where join is set union).
Yet, there are two disjoint paths from A to I. But A is in none of these sets.


Repository:
  rL LLVM

https://reviews.llvm.org/D50433





More information about the llvm-commits mailing list