diff options
author | Alon Zakai <alonzakai@gmail.com> | 2018-11-26 19:02:29 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-26 19:02:29 -0800 |
commit | 12c18c73558be7d2922c063b7646429998f9e4d6 (patch) | |
tree | 1b448a0d4ed26c8e5eefa9888e5b8942ac05c70f /src/cfg/Relooper.cpp | |
parent | 3eea53509fb6275c3fd39060129396a98ef13ab5 (diff) | |
download | binaryen-12c18c73558be7d2922c063b7646429998f9e4d6.tar.gz binaryen-12c18c73558be7d2922c063b7646429998f9e4d6.tar.bz2 binaryen-12c18c73558be7d2922c063b7646429998f9e4d6.zip |
Relooper: Merge consecutive blocks (#1770)
That is, A -> B where no other branches go to B. In that case we are guaranteed to not increase code size.
Diffstat (limited to 'src/cfg/Relooper.cpp')
-rw-r--r-- | src/cfg/Relooper.cpp | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/src/cfg/Relooper.cpp b/src/cfg/Relooper.cpp index 74fe8e7b5..17bccc451 100644 --- a/src/cfg/Relooper.cpp +++ b/src/cfg/Relooper.cpp @@ -493,6 +493,7 @@ struct Optimizer : public RelooperRecursor { More = SkipEmptyBlocks() || More; More = MergeEquivalentBranches() || More; More = UnSwitch() || More; + More = MergeConsecutiveBlocks() || More; // TODO: Merge identical blocks. This would avoid taking into account their // position / how they are reached, which means that the merging // may add overhead, so we do it carefully: @@ -648,6 +649,45 @@ struct Optimizer : public RelooperRecursor { return Worked; } + // Merge consecutive blocks, that is, A -> B where no other branches go to B. + // In that case we are guaranteed to not increase code size. + bool MergeConsecutiveBlocks() { + bool Worked = false; + // First, count predecessors. + std::map<Block*, size_t> NumPredecessors; + for (auto* CurrBlock : Parent->Blocks) { + for (auto& iter : CurrBlock->BranchesOut) { + auto* NextBlock = iter.first; + NumPredecessors[NextBlock]++; + } + } + for (auto* CurrBlock : Parent->Blocks) { + if (CurrBlock->BranchesOut.size() == 1) { + auto iter = CurrBlock->BranchesOut.begin(); + auto* NextBlock = iter->first; + auto* NextBranch = iter->second; + assert(NumPredecessors[NextBlock] > 0); + if (NextBlock != CurrBlock && NumPredecessors[NextBlock] == 1) { + // Good to merge! + wasm::Builder Builder(*Parent->Module); + // Merge in code on the branch as well, if any. + if (NextBranch->Code) { + CurrBlock->Code = Builder.makeSequence(CurrBlock->Code, NextBranch->Code); + } + CurrBlock->Code = Builder.makeSequence(CurrBlock->Code, NextBlock->Code); + // Use the next block's branching behavior + CurrBlock->BranchesOut.swap(NextBlock->BranchesOut); + NextBlock->BranchesOut.clear(); + CurrBlock->SwitchCondition = NextBlock->SwitchCondition; + // The next block now has no predecessors. + NumPredecessors[NextBlock] = 0; + Worked = true; + } + } + } + return Worked; + } + // Removes unneeded switches - if only one branch is left, the default, then // no switch is needed. bool UnSwitch() { |