summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2019-04-30 10:48:51 -0700
committerGitHub <noreply@github.com>2019-04-30 10:48:51 -0700
commitfa4e1e5d9bf94c43b9b0b2295476e6b72daa81ff (patch)
treec5db7750291509cc9442ec368600cc160839d7b1 /src
parent28e01f3e832498237d78a64aafc1ee2a26f92bb4 (diff)
downloadbinaryen-fa4e1e5d9bf94c43b9b0b2295476e6b72daa81ff.tar.gz
binaryen-fa4e1e5d9bf94c43b9b0b2295476e6b72daa81ff.tar.bz2
binaryen-fa4e1e5d9bf94c43b9b0b2295476e6b72daa81ff.zip
wasm2js: optimize switches (#2067)
Don't emit unneeded breaks in switch cases, instead do case X: case Y: .. case W: break .. for each group. Also, the group with the default doesn't need any cases but the default itself.
Diffstat (limited to 'src')
-rw-r--r--src/wasm2js.h25
1 files changed, 22 insertions, 3 deletions
diff --git a/src/wasm2js.h b/src/wasm2js.h
index 515b9335a..c05c16f2b 100644
--- a/src/wasm2js.h
+++ b/src/wasm2js.h
@@ -830,11 +830,30 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m,
Ref theSwitch =
ValueBuilder::makeSwitch(makeAsmCoercion(condition, ASM_INT));
ret[1]->push_back(theSwitch);
+ // First, group the switch targets.
+ std::map<Name, std::vector<Index>> targetIndexes;
for (size_t i = 0; i < curr->targets.size(); i++) {
- ValueBuilder::appendCaseToSwitch(theSwitch, ValueBuilder::makeNum(i));
- ValueBuilder::appendCodeToSwitch(
- theSwitch, blockify(makeBreakOrContinue(curr->targets[i])), false);
+ targetIndexes[curr->targets[i]].push_back(i);
}
+ // Emit group by group.
+ for (auto& pair : targetIndexes) {
+ auto target = pair.first;
+ auto& indexes = pair.second;
+ if (target != curr->default_) {
+ for (auto i : indexes) {
+ ValueBuilder::appendCaseToSwitch(theSwitch,
+ ValueBuilder::makeNum(i));
+ }
+ ValueBuilder::appendCodeToSwitch(
+ theSwitch, blockify(makeBreakOrContinue(target)), false);
+ } else {
+ // For the group going to the same place as the default, we can just
+ // emit the default itself, which we do at the end.
+ }
+ }
+ // TODO: if the group the default is in is not the largest, we can turn
+ // the largest into
+ // the default by using a local and a check on the range
ValueBuilder::appendDefaultToSwitch(theSwitch);
ValueBuilder::appendCodeToSwitch(
theSwitch, blockify(makeBreakOrContinue(curr->default_)), false);