[SimplifyCFG] Simplify identical predecessors - #173022
Conversation
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
🪟 Windows x64 Test Results
✅ The build succeeded and all tests passed. |
🐧 Linux x64 Test Results
✅ The build succeeded and all tests passed. |
54d7a50 to
be1c964
Compare
|
This probably subsumes simplifyDuplicateSwitchArms? |
Yes, it is indeed a generalization of |
be1c964 to
4e0b53a
Compare
4e0b53a to
ade6af0
Compare
ade6af0 to
185e648
Compare
b17f5b5 to
02da180
Compare
02da180 to
ca6c8da
Compare
| // Merge identical predecessors of this block | ||
| if (simplifyDuplicatePredecessors(BB, DTU)) | ||
| return true; |
There was a problem hiding this comment.
Should we treat identical predecessor merging as part of sink-common-insts, and perform it after sinkCommonCodeFromPredecessors?
This avoids interfering with earlier optimizations that rely on special basic block structures (e.g., unconditioned branch folding, speculativelyExecuteBB and jump-threading).
There was a problem hiding this comment.
Yeah, we probably do not want to do this transform too early. Not sure whether having the same phase ordering as sink-common-insts is right, but it's probably a reasonable starting point...
4647b4a to
95312c5
Compare
| return false; | ||
|
|
||
| // The BB must have at least one predecessor. | ||
| if (!BB->hasNPredecessorsOrMore(1)) |
There was a problem hiding this comment.
| if (!BB->hasNPredecessorsOrMore(1)) | |
| if (pred_empty(BB)) |
| return false; | ||
|
|
||
| // TODO: relax this condition to merge equal blocks with >1 instructions? | ||
| if (BB->size() != 1) |
There was a problem hiding this comment.
It is calculated in linear time:
There was a problem hiding this comment.
This code is directly inherited from the original code.
Here, we can replace it with a O(1) judgment &BB->front() != &BB->back().
|
Seems the comptime issue has been resolved. |
|
|
||
| // Avoid blocks that are "address-taken" (blockaddress) or have unusual | ||
| // uses. | ||
| if (BB->hasAddressTaken() || BB->isLandingPad()) |
There was a problem hiding this comment.
It looks like these conditions don't have test coverage?
Also, are you sure you want to exclude landingpads specifically, rather than EH pads in general?
There was a problem hiding this comment.
Yes. We should use isEHPad().
I have added a new test to cover BB->hasAddressTaken() .
BB->isEHPad() is hard to cover as there are no TWO identical EHPad BBs with only ONE unconditioned branch.
I added this guard just for future usage.
| return false; | ||
|
|
||
| // TODO: relax this condition to merge equal blocks with >1 instructions? | ||
| if (/* I.e., O(n) calc: size() != 1 */ &BB->front() != &BB->back()) |
There was a problem hiding this comment.
Move this comment out of the condition.
| Succ->phis(), [BB, &PhiPredIVs = *EBW->PhiPredIVs](PHINode &Phi) { | ||
| return PhiPredIVs[&Phi][BB]; |
There was a problem hiding this comment.
| Succ->phis(), [BB, &PhiPredIVs = *EBW->PhiPredIVs](PHINode &Phi) { | |
| return PhiPredIVs[&Phi][BB]; | |
| Succ->phis(), [&](PHINode &Phi) { | |
| return EBW->PhiPredIVs[&Phi][BB]; |
The explicit captures here look more confusing than helpful.
| BasicBlock *KeepBB = (*It)->BB; | ||
| BasicBlock *DeadBB = EBW.BB; | ||
|
|
||
| // Avoid merging if either is the other's predecessor in weird ways. |
There was a problem hiding this comment.
Is this really what this condition is guarding against? I'd have thought this would occur if the same block occurs multiple times in the candidate list, rather than some kind of relationship between the blocks.
There was a problem hiding this comment.
I am sorry I forgot the context of this comment due to some rebases, but it is now just a useless comment.
| SmallSetVector<BasicBlock *, 16> FilteredArms( | ||
| llvm::from_range, | ||
| make_filter_range(successors(SI), EqualBBWrapper::canBeMerged)); | ||
| return mergeIdenticalBBs(FilteredArms.getArrayRef(), DTU); |
There was a problem hiding this comment.
Can you please explain why we still need the special switch handling next to the predecessor based logic?
There was a problem hiding this comment.
They perform at different stages.
- "switch arm merging": very early
simplifycfg - "identical preds merging": late
simplifycfg<sink-common-inst>aftersimplifycfg, see [SimplifyCFG] Simplify identical predecessors #173022 (comment)
I indeed tried completely replacing "switch arm merging" with "identical pred merging" to consider unification; however, it triggered a regression due to the delay of "switch arm merging" (implemented by "identical pred merging").
The regression chain is too long to clarify here: dtcxzyw/llvm-opt-benchmark#3204 (comment)
Finally, I decided to keep the original logic of "switch arm merging" and append "identical pred merging" as new functionality.
|
Gentle ping😀. |
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/169/builds/20839 Here is the relevant piece of the build log for the reference |
When >1 predecessors of BB are identical, try to merge them into ONE.
Here is a simplified example (
sinkandbb*s share the same predecessorentry, hindering the existing uncond br folding to optimize such a case):Actually,
simplifyDuplicateSwitchArmsdid similar things in a very limited scope (only for switch arms); this patch generalizes its logic to handle any BB with >1 identical predecessors.This PR lands the discussion, i.e., "merge identical predecessor bottom to up", and implements the suggestion of #114262 (comment).