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.