This is an archive of the discontinued LLVM Phabricator instance.

[BranchProbabilityInfo] Fix eraseBlock
ClosedPublic

Authored by kazu on Oct 27 2020, 3:44 PM.

Details

Summary

This patch ensures that BranchProbabilityInfo::eraseBlock(BB) deletes
all entries in Probs associated with with BB.

Without this patch, stale entries for BB may remain in Probs after
eraseBlock(BB), leading to a situation where a newly created basic
block has an edge probability associated with it even before the pass
responsible for creating the basic block adds any edge probability to
it.

Consider the current implementation of eraseBlock(BB):

for (const_succ_iterator I = succ_begin(BB), E = succ_end(BB); I != E; ++I) {
  auto MapI = Probs.find(std::make_pair(BB, I.getSuccessorIndex()));
  if (MapI != Probs.end())
    Probs.erase(MapI);
}

Notice that it uses succ_begin(BB) and succ_end(BB), which are based
on BB->getTerminator(). This means that if the terminator changes
between calls to setEdgeProbability and eraseBlock, then we may not
examine all pairs associated with BB.

This is exactly what happens in MaybeMergeBasicBlockIntoOnlyPred,
which merges basic blocks A into B if A is the sole predecessor of B,
and B is the sole successor of A. It replaces the terminator of A
with UnreachableInst before (indirectly) calling eraseBlock(A).

The patch fixes the problem by keeping track of all edge probablities
entered with setEdgeProbability in a map from BasicBlock* to a
successor index.

Diff Detail

Event Timeline

kazu created this revision.Oct 27 2020, 3:44 PM
Herald added a project: Restricted Project. · View Herald TranscriptOct 27 2020, 3:44 PM
kazu requested review of this revision.Oct 27 2020, 3:44 PM
wmi accepted this revision.Oct 27 2020, 4:12 PM

LGTM.

llvm/lib/Analysis/BranchProbabilityInfo.cpp
1141–1144

If Src doesn't exist in MaxSuccIdx, MaxSuccIdx[Src] will return 0. Can it be simplified to one statement?
MaxSuccIdx[Src] = std::max(MaxSuccIdx[Src], IndexInSuccessors);

This revision is now accepted and ready to land.Oct 27 2020, 4:12 PM
This revision was landed with ongoing or failed builds.Oct 27 2020, 4:14 PM
This revision was automatically updated to reflect the committed changes.

Thanks for figuring out the root cause!

It replaces the terminator of A with UnreachableInst before (indirectly) calling eraseBlock(A).

Question: Why is it UnreachableInst?

llvm/lib/Analysis/BranchProbabilityInfo.cpp
1141

This can be simply: int &SuccIdx = MaxSuccIdx[Src]; SuccIdx = std::max(SuccIdx, IndexInSuccessors);

Alternatively,

try_emplace + std::max

1182–1187

Add a comment that we cannot simply use successors?