Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport D74999: [WebAssembly] Fix a non-determinism problem in FixIrreducibleControlFlow #68

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,17 @@ namespace {
using BlockVector = SmallVector<MachineBasicBlock *, 4>;
using BlockSet = SmallPtrSet<MachineBasicBlock *, 4>;

static BlockVector getSortedEntries(const BlockSet &Entries) {
BlockVector SortedEntries(Entries.begin(), Entries.end());
llvm::sort(SortedEntries,
[](const MachineBasicBlock *A, const MachineBasicBlock *B) {
auto ANum = A->getNumber();
auto BNum = B->getNumber();
return ANum < BNum;
});
return SortedEntries;
}

// Calculates reachability in a region. Ignores branches to blocks outside of
// the region, and ignores branches to the region entry (for the case where
// the region is the inner part of a loop).
Expand Down Expand Up @@ -241,20 +252,25 @@ class WebAssemblyFixIrreducibleControlFlow final : public MachineFunctionPass {
bool WebAssemblyFixIrreducibleControlFlow::processRegion(
MachineBasicBlock *Entry, BlockSet &Blocks, MachineFunction &MF) {
bool Changed = false;

// Remove irreducibility before processing child loops, which may take
// multiple iterations.
while (true) {
ReachabilityGraph Graph(Entry, Blocks);

bool FoundIrreducibility = false;

for (auto *LoopEntry : Graph.getLoopEntries()) {
for (auto *LoopEntry : getSortedEntries(Graph.getLoopEntries())) {
// Find mutual entries - all entries which can reach this one, and
// are reached by it (that always includes LoopEntry itself). All mutual
// entries must be in the same loop, so if we have more than one, then we
// have irreducible control flow.
//
// (Note that we need to sort the entries here, as otherwise the order can
// matter: being mutual is a symmetric relationship, and each set of
// mutuals will be handled properly no matter which we see first. However,
// there can be multiple disjoint sets of mutuals, and which we process
// first changes the output.)
//
// Note that irreducibility may involve inner loops, e.g. imagine A
// starts one loop, and it has B inside it which starts an inner loop.
// If we add a branch from all the way on the outside to B, then in a
Expand Down Expand Up @@ -325,13 +341,7 @@ void WebAssemblyFixIrreducibleControlFlow::makeSingleEntryLoop(
assert(Entries.size() >= 2);

// Sort the entries to ensure a deterministic build.
BlockVector SortedEntries(Entries.begin(), Entries.end());
llvm::sort(SortedEntries,
[&](const MachineBasicBlock *A, const MachineBasicBlock *B) {
auto ANum = A->getNumber();
auto BNum = B->getNumber();
return ANum < BNum;
});
BlockVector SortedEntries = getSortedEntries(Entries);

#ifndef NDEBUG
for (auto Block : SortedEntries)
Expand Down