This is an archive of the discontinued LLVM Phabricator instance.

[JumpThreading] Set edge probabilities when creating basic blocks
ClosedPublic

Authored by kazu on Oct 24 2020, 3:32 PM.

Details

Summary

This patch teaches the jump threading pass to set edge probabilities
whenever the pass creates new basic blocks.

Without this patch, the compiler sometimes produces non-deterministic
results. The non-determinism comes from the jump threading pass using
stale edge probabilities in BranchProbabilityInfo. Specifically, when
the jump threading pass creates a new basic block, we don't initialize
its outgoing edge probability.

Edge probabilities are maintained in:

DenseMap<Edge, BranchProbability> Probs;

in class BranchProbabilityInfo, where Edge is an ordered pair of
BasicBlock * and a successor index declared as:

using Edge = std::pair<const BasicBlock *, unsigned>;

Probs maps edges to their corresponding probabilities.

Now, we rarely remove entries from this map, so if we happen to
allocate a new basic block at the same address as a previously deleted
basic block with an edge probability assigned, the newly created basic
block appears to have an edge probability, albeit a stale one.

This patch fixes the problem by explicitly setting edge probabilities
whenever the jump threading pass creates new basic blocks.

Diff Detail

Event Timeline

kazu created this revision.Oct 24 2020, 3:32 PM
Herald added a project: Restricted Project. · View Herald TranscriptOct 24 2020, 3:32 PM
kazu requested review of this revision.Oct 24 2020, 3:32 PM

I've debugged this two weeks ago:)

Now, we rarely remove entries from this map, so if we happen to ...

Thanks for narrowing it down to the issue! LGTM

Do you know whether we have missed some BranchProbabilityInfo::eraseBlock calls? Why is BasicBlockCallbackVH::deleted() not effective when some BasicBlock's are removed?

wmi added a comment.Oct 26 2020, 4:00 PM

Do you know whether we have missed some BranchProbabilityInfo::eraseBlock calls? Why is BasicBlockCallbackVH::deleted() not effective when some BasicBlock's are removed?

Same question here. There shouldn't be stale value in Prob if the value handler is functioning correctly.

This revision was not accepted when it landed; it landed in state Needs Review.Oct 27 2020, 4:07 PM
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
kazu added a comment.Oct 27 2020, 4:11 PM
In D90106#2355030, @wmi wrote:

Do you know whether we have missed some BranchProbabilityInfo::eraseBlock calls? Why is BasicBlockCallbackVH::deleted() not effective when some BasicBlock's are removed?

Same question here. There shouldn't be stale value in Prob if the value handler is functioning correctly.

Please see the description of the follow-up patch I just posted: https://reviews.llvm.org/D90272

Probably would'ev been worth waiting to check that the two reviewers with the question found the answer addressed their concerns (& getting a clear approval) before committing. (bit awkward to commit things that haven't been formally approved - though I realize @MaskRay's comment may be close enough to be construed as approval)

Probably would'ev been worth waiting to check that the two reviewers with the question found the answer addressed their concerns (& getting a clear approval) before committing. (bit awkward to commit things that haven't been formally approved - though I realize @MaskRay's comment may be close enough to be construed as approval)

Thanks @dblaikie!

llvm/lib/Transforms/Scalar/JumpThreading.cpp
2517

With D90272, do we still need this chunk?

getEdgeProbability by default knows the probability is 1.

2734

With D90272, do we still need this chunk?

getEdgeProbability by default knows the probability is 1.

llvm/test/Transforms/JumpThreading/thread-prob-2.ll
1

debug-only tests require REQUIRES: asserts

The 3 new tests are useful but I wonder -debug-only=branch-prob is the best way testing them. Such tests should also be used prudently as debug only codes tends to be very specific internal details.

I would have required the description of this patch to be fixed if I saw D90272 earlier.

anna added subscribers: yrouban, anna.EditedNov 3 2020, 10:34 AM

Hi @kazu, just wanted to point out - We have seen multiple assertion failures in benchmarks downstream with this patch (or a related one built on this patch). Trying to revert this downstream shows there are dependent patches. Is this assertion seen and already fixed in trunk?

Assertion failure is BranchProbabilityInfo.cpp:1163: void llvm::BranchProbabilityInfo::setEdgeProbability(const llvm::BasicBlock*, const llvm::SmallVectorImpl&): Assertion TotalNumerator <= BranchProbability::getDenominator() + Probs.size()'

@yrouban narrowed it down to:
"Debugging showed that the assertion detects incorrect set of probabilities (summ != 1.0) when they are copied from PredBB to NewBB in JumpThreadingPass::ThreadThroughTwoBasicBlocks(). The probabilities are corrupted in PredBB when it gets cloned instructions from its successor in JumpThreadingPass::DuplicateCondBranchOnPHIIntoPred(). So the bug is in this method which does not fix the probabilities. "
He is working on a fix for this with upstream testcase.

kazu added a comment.Nov 3 2020, 2:07 PM

Hi @kazu, just wanted to point out - We have seen multiple assertion failures in benchmarks downstream with this patch (or a related one built on this patch). Trying to revert this downstream shows there are dependent patches. Is this assertion seen and already fixed in trunk?

Assertion failure is BranchProbabilityInfo.cpp:1163: void llvm::BranchProbabilityInfo::setEdgeProbability(const llvm::BasicBlock*, const llvm::SmallVectorImpl&): Assertion TotalNumerator <= BranchProbability::getDenominator() + Probs.size()'

@yrouban narrowed it down to:
"Debugging showed that the assertion detects incorrect set of probabilities (summ != 1.0) when they are copied from PredBB to NewBB in JumpThreadingPass::ThreadThroughTwoBasicBlocks(). The probabilities are corrupted in PredBB when it gets cloned instructions from its successor in JumpThreadingPass::DuplicateCondBranchOnPHIIntoPred(). So the bug is in this method which does not fix the probabilities. "
He is working on a fix for this with upstream testcase.

Those follow-up patches do not touch the code to call setEdgeProbability from JumpThreadingPass::ThreadThroughTwoBasicBlocks, so I'm pretty sure that the issue isn't fixed on the trunk yet. Thank you for tracking down the bug. I'd appreciate if you put me as a reviewer on your patch.