diff options
author | Alon Zakai <azakai@google.com> | 2019-04-30 10:48:51 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-30 10:48:51 -0700 |
commit | fa4e1e5d9bf94c43b9b0b2295476e6b72daa81ff (patch) | |
tree | c5db7750291509cc9442ec368600cc160839d7b1 /src | |
parent | 28e01f3e832498237d78a64aafc1ee2a26f92bb4 (diff) | |
download | binaryen-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.h | 25 |
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); |