In order to preserve LoopSimplify, SplitCriticalEdge will generate a new exit block,
which may become a new dominance frontier for dead blocks. After that, we need to
add this block to DF list, and update the undef incoming value for phi correctly.
Details
- Reviewers
- fhahn - asbirlea - jdoerfert - efriedma - gkistanova 
Diff Detail
Event Timeline
| llvm/lib/Transforms/Scalar/GVN.cpp | ||
|---|---|---|
| 2822 | Could you please explain in more details the mechanics here?  | |
| 2834 | s/NewBolcks/NewBlocks | |
| llvm/lib/Transforms/Scalar/GVN.cpp | ||
|---|---|---|
| 2822 | I have updated the code, and some comments to descibe the details for it.     //     - - - - - - - -
    //    |    ... ...    |
    //    |[D1]           |   =>  A simplified loop<L>
    //    | |  \          |
    //    | |   [D2] [B1] |
    //     -|- - |- - |- -
    //      |    |    |
    //      \    |    /
    //       \   |   /
    //        [ DF1 ]        => exit block for loop<L>
    //
    // Consider the above scenario, there're two dead blocks [D1] + [D2], and
// a live block[B1]([D1][D2][B1] in one loop). [DF1] will a common dominance
    // frontier block for [D1] and [D2], so Candidates will contain two elements
    // [D1, D2]. [D1] has two succs: [D2] and [DF1], for [D1],first llvm::any_of
    // will return true, so splitCriticalEdges will be called.
    //
    //     - - - - - - - -
    //    |    ... ...    |
    //    |[D1]           |   =>  A simplified loop<L>
    //    | |  \          |
    //    | |   [D2] [B1] |
    //     -|- - |- - |- -
    //      |    |    |
    //      |    \    /
    //     [D3]   [DF2]      => New Exit block[DF2] for loop<L>
    //       \      |
    //        [ DF1 ]
    //
    // After splitCriticalEdges, a new crit_edge block[D3] will be created, and
    // it is added into dead blocks. Also, a new loop exit block[DF2] is created
    // to preserve LoopSimplify. After that, llvm::any_of will return false for
    // [D2], and we need to add [DF2] as a new dominance frontier block for [D2]
    // since it has a pred edge to non-dead block[B1], and then, we need to
    // update the undef incoming value for phi in [DF2].About the purpose of the intersection of non-dead succs and preds, we should consider another case like below: // - - - - - - - - // | ... ... | // | ... ... | => A simplified loop<L> // | [ D1 ] [B1] | // -|- |- |- -|- - // | | | | // | | | | // \ | | | // \ | / / // [ DF1 ] => exit block for loop<L> // // After split edeges, // - - - - - - - - // | ... ... | // | ... ... | => A simplified loop<L> // | [ D1 ] [B1]| // -|- |- |- -|-- // | | | | // | | \ / // [D2][D3][DF2] => New Exit block[DF2] for loop<L> // \ | / // [ DF1 ] // // switch-case: [ D1 ] will have multi edges to [ DF1 ], after split, [D2][D3] are new created, // both will be dead blocks, so we need to use the intersection of non-dead succs and preds to get [DF2] | |
| llvm/lib/Transforms/Scalar/GVN.cpp | ||
|---|---|---|
| 2834 | changed. | |
| llvm/lib/Transforms/Scalar/GVN.cpp | ||
|---|---|---|
| 2761–2762 | It doesn't look like this condition is needed here anymore, since splitting critical edges is done below. So just checking isCriticalEdge should be enough to make it a candidate. Simplify this to iterate over B's predecessors directly; the vector is not needed when predecessors don't change. | |
| 2822 | Thank you for adding the example in code, that's very helpful! I may be missing some details in the last example, but it seems like the non-dead predecessors for B (the IDF block) should cover the new blocks? ([D2]and [D3] should be in DeadBlocks following the split). | |
| llvm/test/Transforms/GVN/pr47462.ll | ||
| 2 | Can you add a RUN line using the new pass manager? (-passes=...) | |
| llvm/lib/Transforms/Scalar/GVN.cpp | ||
|---|---|---|
| 2822 | yeah, the non-dead predecessors for B should cover the new blocks, there're some mistakes for the diagram after split edeges, the right one should be: // After split edeges, // - - - - - - - - // | ... ... | // | ... ... | => A simplified loop<L> // | [ D1 ] [B1]| // -|- |- |- -|-- // | | | | // | \ | / // [D2] [DF2] => New Exit block[DF2] for loop<L> // \ | // [ DF1 ] [D2] and [DF2] are both new created blocks after split edeges,[D2] will be a dead block while [DF2] will be a new IDF block | |
for (BasicBlock *P : predecessors(B)) {
delete Preds.