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.