summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2016-09-07 15:37:07 -0700
committerAlon Zakai <alonzakai@gmail.com>2016-09-07 18:42:48 -0700
commitb518e564be25cc2705ab3993b71f0170feabac7e (patch)
treed5e00037377b1903867d5e2665c792e19e5eb689 /src
parent443d7a8e39c4ccfaeab6066160aae17e1fee8cc8 (diff)
downloadbinaryen-b518e564be25cc2705ab3993b71f0170feabac7e.tar.gz
binaryen-b518e564be25cc2705ab3993b71f0170feabac7e.tar.bz2
binaryen-b518e564be25cc2705ab3993b71f0170feabac7e.zip
properly handle blocks with return values in vacuum - we cannot remove their final value directly, we can only do that if it is dropped, from the drop
Diffstat (limited to 'src')
-rw-r--r--src/passes/Vacuum.cpp25
1 files changed, 22 insertions, 3 deletions
diff --git a/src/passes/Vacuum.cpp b/src/passes/Vacuum.cpp
index 53b9eb397..592f5a063 100644
--- a/src/passes/Vacuum.cpp
+++ b/src/passes/Vacuum.cpp
@@ -137,13 +137,12 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum, Visitor<Vacuum>>
void visitBlock(Block *curr) {
// compress out nops and other dead code
- bool resultUsed = ExpressionAnalyzer::isResultUsed(expressionStack, getFunction());
int skip = 0;
auto& list = curr->list;
size_t size = list.size();
bool needResize = false;
for (size_t z = 0; z < size; z++) {
- auto* optimized = optimize(list[z], z == size - 1 && resultUsed);
+ auto* optimized = optimize(list[z], z == size - 1 && isConcreteWasmType(curr->type));
if (!optimized) {
skip++;
needResize = true;
@@ -170,7 +169,7 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum, Visitor<Vacuum>>
if (!curr->name.is()) {
if (list.size() == 1) {
// just one element. replace the block, either with it or with a nop if it's not needed
- if (resultUsed || EffectAnalyzer(list[0]).hasSideEffects()) {
+ if (isConcreteWasmType(curr->type) || EffectAnalyzer(list[0]).hasSideEffects()) {
replaceCurrent(list[0]);
} else {
ExpressionManipulator::nop(curr);
@@ -218,6 +217,26 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum, Visitor<Vacuum>>
replaceCurrent(set);
return;
}
+ // if we are dropping a block's return value, we might be able to remove it entirely
+ if (auto* block = curr->value->dynCast<Block>()) {
+ auto* last = block->list.back();
+ if (isConcreteWasmType(last->type)) {
+ assert(block->type == last->type);
+ block->list.back() = last = optimize(last, false);
+ if (!last) {
+ block->list.pop_back();
+ // we don't need the drop anymore, let's see what we have left in the block
+ if (block->list.size() > 1) {
+ replaceCurrent(block);
+ } else if (block->list.size() == 1) {
+ replaceCurrent(block->list[0]);
+ } else {
+ ExpressionManipulator::nop(curr);
+ }
+ return;
+ }
+ }
+ }
// sink a drop into an arm of an if-else if the other arm ends in an unreachable, as it if is a branch, this can make that branch optimizable and more vaccuming possible
auto* iff = curr->value->dynCast<If>();
if (iff && iff->ifFalse && isConcreteWasmType(iff->type)) {