This is an archive of the discontinued LLVM Phabricator instance.

SplitIndirectBrCriticalEdges: Fix Branch Probability update
ClosedPublic

Authored by yrouban on Apr 24 2020, 5:05 AM.

Details

Summary

Splitting critical edges for indirect branches the SplitIndirectBrCriticalEdges() function may break branch probabilities if target basic block happens to have unset a probability for any of its successors. That is because in such cases the getEdgeProbability(Target) function returns probability 1/NumOfSuccessors and it is called after Target was split (thus Target has a single successor). As the result the correspondent successor of the split block gets probability 100% but 1/NumOfSuccessors is expected (or better be left unset).

Diff Detail

Event Timeline

yrouban created this revision.Apr 24 2020, 5:05 AM

Why considering the cases where "target basic block happens to have unset a probability for any of its successors" specifically?

Does the new test TEST(BasicBlockUtils, SplitIndirectBrCriticalEdge) fail before the change in BreakCriticalEdges.cpp (where the target block doesn't seem to have an unset successor)?

In D78806#2002145, @yamauchi wrote:

Does the new test TEST(BasicBlockUtils, SplitIndirectBrCriticalEdge) fail ..

Yes. It fails with 100% on both edges.

Functionally the change looks ok.
I think we should improve current API of BP (not in this change though) because it's easy to break invariant that sum of all probabilities is 1.
We better disallow cases when only part of edges have probability set and others unset. 1/NumSuccesors will likely be incorrect value in most cases with uneven distribution.

hjyamauchi added inline comments.Apr 30 2020, 5:57 PM
llvm/unittests/Transforms/Utils/BasicBlockUtilsTest.cpp
146

Can you clang-format this code (as the lint check)?

169

Relying on the block name ".split" (that SplitIndirectBrCriticalEdges internally uses) may be a bit fragile. How about finding the block that's the predecessor of bb2/bb3?

yrouban marked 2 inline comments as done.May 1 2020, 9:41 AM
yrouban added inline comments.
llvm/unittests/Transforms/Utils/BasicBlockUtilsTest.cpp
146

ok. but this will look different from the other test cases

yrouban updated this revision to Diff 261477.May 1 2020, 9:43 AM

addressed the comments about the test

What happens in the newly added test seems that none of the successor probabilities are ever set (BranchProbabilityInfo::Probs is empty throughout). The thing is that BPI does not internally store the edge probabilities unless they are non-default, unevenly-split ones (1/NumOfSuccessors) and relies on the real-time state of the blocks/CFG for default cases, which is likely different from what the author of SplitIndirectBrCriticalEdges expected. In contrast, BFI stores the block frequencies at the time it was calculated, which stays there after the blocks/CFG are modified. When the block "bb1" gets split, the number of its successors goes from two (50% each) to one (100%). Then, this 100% probability incorrectly gets copied to each of the two successors of the new block.

This revision is now accepted and ready to land.May 1 2020, 3:09 PM
This revision was automatically updated to reflect the committed changes.