diff options
-rw-r--r-- | src/passes/DeadCodeElimination.cpp | 48 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 7 | ||||
-rw-r--r-- | test/passes/dce.txt | 116 | ||||
-rw-r--r-- | test/passes/dce.wast | 67 | ||||
-rw-r--r-- | test/passes/dce_vacuum.txt | 7 | ||||
-rw-r--r-- | test/unit.fromasm | 18 | ||||
-rw-r--r-- | test/unit.fromasm.clamp | 18 | ||||
-rw-r--r-- | test/unit.fromasm.imprecise | 18 |
8 files changed, 219 insertions, 80 deletions
diff --git a/src/passes/DeadCodeElimination.cpp b/src/passes/DeadCodeElimination.cpp index 41012fccb..33a52a09a 100644 --- a/src/passes/DeadCodeElimination.cpp +++ b/src/passes/DeadCodeElimination.cpp @@ -51,12 +51,20 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>> std::set<Name> reachableBreaks; void addBreak(Name name) { - assert(reachable); - reachableBreaks.insert(name); + // we normally have already reduced unreachable code into (unreachable) + // nodes, so we would not get to this function at all anyhow, the breaking + // instruction itself would be removed. However, an exception are things + // like (block i32 (call $x) (unreachable)) , which has type i32 + // despite not being exited. + // TODO: optimize such cases + if (reachable) { + reachableBreaks.insert(name); + } } - bool isDead(Expression* curr) { - return curr && curr->is<Unreachable>(); + // if a child is unreachable, we can replace ourselves with it + bool isDead(Expression* child) { + return child && child->type == unreachable; } // things that stop control flow @@ -67,6 +75,19 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>> replaceCurrent(curr->value); return; } + if (isDead(curr->condition)) { + if (curr->value) { + auto* block = getModule()->allocator.alloc<Block>(); + block->list.resize(2); + block->list[0] = drop(curr->value); + block->list[1] = curr->condition; + block->finalize(); + replaceCurrent(block); + } else { + replaceCurrent(curr->condition); + } + return; + } addBreak(curr->name); if (!curr->condition) { reachable = false; @@ -78,6 +99,19 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>> replaceCurrent(curr->value); return; } + if (isDead(curr->condition)) { + if (curr->value) { + auto* block = getModule()->allocator.alloc<Block>(); + block->list.resize(2); + block->list[0] = drop(curr->value); + block->list[1] = curr->condition; + block->finalize(); + replaceCurrent(block); + } else { + replaceCurrent(curr->condition); + } + return; + } for (auto target : curr->targets) { addBreak(target); } @@ -137,7 +171,7 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>> reachable = reachable || reachableBreaks.count(curr->name); reachableBreaks.erase(curr->name); } - if (curr->list.size() == 1 && isDead(curr->list[0])) { + if (curr->list.size() == 1 && isDead(curr->list[0]) && !BreakSeeker::has(curr->list[0], curr->name)) { replaceCurrent(curr->list[0]); } } @@ -146,7 +180,7 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>> if (curr->name.is()) { reachableBreaks.erase(curr->name); } - if (isDead(curr->body)) { + if (isDead(curr->body) && !BreakSeeker::has(curr->body, curr->name)) { replaceCurrent(curr->body); return; } @@ -360,7 +394,7 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>> } void visitHost(Host* curr) { - // TODO + handleCall(curr); } void visitFunction(Function* curr) { diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index a983fc943..36eff681f 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -409,7 +409,12 @@ void Host::finalize() { break; } case GrowMemory: { - type = i32; + // if the single operand is not reachable, so are we + if (operands[0]->type == unreachable) { + type = unreachable; + } else { + type = i32; + } break; } default: abort(); diff --git a/test/passes/dce.txt b/test/passes/dce.txt index 80ba622a4..22189fb66 100644 --- a/test/passes/dce.txt +++ b/test/passes/dce.txt @@ -21,9 +21,7 @@ ) (if (i32.const 0) - (block $out3 - (return) - ) + (return) ) (block $out4 (br_table $out4 $out4 $out4 $out4 @@ -40,12 +38,10 @@ ) (if (i32.const 0) - (block $block4 - (if - (i32.const 0) - (unreachable) - (unreachable) - ) + (if + (i32.const 0) + (unreachable) + (unreachable) ) ) (if @@ -76,15 +72,13 @@ ) (if (i32.const 0) - (block $block11 - (block $out18 - (block $in19 - (br_if $in19 - (i32.const 1) - ) + (block $out18 + (block $in19 + (br_if $in19 + (i32.const 1) ) - (unreachable) ) + (unreachable) ) ) (block $out20 @@ -105,15 +99,13 @@ ) (if (i32.const 0) - (block $block13 - (block $out25 - (block $in26 - (br_table $in26 $in26 - (i32.const 1) - ) + (block $out25 + (block $in26 + (br_table $in26 $in26 + (i32.const 1) ) - (unreachable) ) + (unreachable) ) ) (if @@ -133,7 +125,7 @@ (unreachable) ) (block $out29 - (loop $in30 + (block (br_if $out29 (i32.const 1) ) @@ -142,13 +134,11 @@ ) (if (i32.const 0) - (block $block20 - (loop $in32 - (br_if $in32 - (i32.const 1) - ) - (unreachable) + (loop $in32 + (br_if $in32 + (i32.const 1) ) + (unreachable) ) ) (if @@ -300,13 +290,8 @@ ) ) (func $typed-block-none-then-unreachable (type $2) (result i32) - (block $top-typed i32 - (block $switch$0 - (return - (i32.const 0) - ) - ) - (unreachable) + (return + (i32.const 0) ) ) (func $typed-block-remove-br-changes-type (type $3) (param $$$0 i32) (result i32) @@ -337,4 +322,61 @@ (i32.const 0) ) ) + (func $unreachable-br (type $2) (result i32) + (block $out i32 + (br $out + (i32.const 0) + ) + ) + ) + (func $unreachable-br-loop (type $2) (result i32) + (loop $out + (br $out) + ) + ) + (func $unreachable-block-ends-switch (type $2) (result i32) + (block $label$0 i32 + (block $label$3 + (nop) + (unreachable) + ) + (unreachable) + ) + ) + (func $unreachable-block-ends-br_if (type $1) (result i32) + (block $label$0 i32 + (block $label$2 + (nop) + (unreachable) + ) + (unreachable) + ) + ) + (func $unreachable-brs-3 (type $2) (result i32) + (block $label$0 i32 + (br $label$0 + (i32.const 18) + ) + ) + ) + (func $unreachable-brs-4 (type $3) (param $var$0 i32) (result i32) + (i32.add + (i32.const 1) + (block $label$0 i32 + (br $label$0 + (block $label$1 i32 + (drop + (block + (drop + (i32.const 4104) + ) + (unreachable) + ) + ) + (unreachable) + ) + ) + ) + ) + ) ) diff --git a/test/passes/dce.wast b/test/passes/dce.wast index 0bed1e8ff..865f373cf 100644 --- a/test/passes/dce.wast +++ b/test/passes/dce.wast @@ -442,4 +442,71 @@ (nop) (i32.const 0) ) + (func $unreachable-br (result i32) + (block $out i32 + (br $out + (br $out (i32.const 0)) + ) + ) + ) + (func $unreachable-br-loop (result i32) + (loop $out + (br $out) + ) + ) + (func $unreachable-block-ends-switch (result i32) + (block $label$0 i32 + (block $label$3 + (nop) + (br_table $label$3 + (unreachable) + ) + (unreachable) + ) + (i32.const 19) + ) + ) + (func $unreachable-block-ends-br_if (type $1) (result i32) + (block $label$0 i32 + (block $label$2 + (nop) + (br_if $label$2 + (unreachable) + ) + (unreachable) + ) + (i32.const 19) + ) + ) + (func $unreachable-brs-3 (result i32) + (block $label$0 i32 + (br $label$0 + (grow_memory + (br $label$0 + (i32.const 18) + ) + ) + ) + (i32.const 21) + ) + ) + (func $unreachable-brs-4 (param $var$0 i32) (result i32) + (i32.add + (i32.const 1) + (block $label$0 i32 + (br $label$0 + (block $label$1 i32 ;; this block is declared i32, but we can see it is unreachable + (drop + (br_if $label$0 + (i32.const 4104) + (unreachable) + ) + ) + (i32.const 4) + ) + ) + (i32.const 16) + ) + ) + ) ) diff --git a/test/passes/dce_vacuum.txt b/test/passes/dce_vacuum.txt index 157339e9b..4fb982524 100644 --- a/test/passes/dce_vacuum.txt +++ b/test/passes/dce_vacuum.txt @@ -2,11 +2,8 @@ (type $0 (func (result i32))) (memory $0 0) (func $__Z12serveroptionPc (type $0) (result i32) - (block $switch$0 - (return - (i32.const 0) - ) + (return + (i32.const 0) ) - (unreachable) ) ) diff --git a/test/unit.fromasm b/test/unit.fromasm index 45dc81937..580057f82 100644 --- a/test/unit.fromasm +++ b/test/unit.fromasm @@ -197,16 +197,14 @@ (i32.const 51) ) ) - (block $label$break$Lout - (block $switch-case9 - (block $switch-case6 - (block $switch-case5 - (block $switch-case4 - (br_table $switch-case9 $label$break$Lout $label$break$Lout $switch-case6 $label$break$Lout $label$break$Lout $label$break$Lout $label$break$Lout $switch-case5 $label$break$Lout $switch-case4 $label$break$Lout - (i32.sub - (get_local $0) - (i32.const 2) - ) + (block $switch-case9 + (block $switch-case6 + (block $switch-case5 + (block $switch-case4 + (br_table $switch-case9 $switch-case9 $switch-case9 $switch-case6 $switch-case9 $switch-case9 $switch-case9 $switch-case9 $switch-case5 $switch-case9 $switch-case4 $switch-case9 + (i32.sub + (get_local $0) + (i32.const 2) ) ) ) diff --git a/test/unit.fromasm.clamp b/test/unit.fromasm.clamp index 469c4932b..7bfcdd531 100644 --- a/test/unit.fromasm.clamp +++ b/test/unit.fromasm.clamp @@ -221,16 +221,14 @@ (i32.const 51) ) ) - (block $label$break$Lout - (block $switch-case9 - (block $switch-case6 - (block $switch-case5 - (block $switch-case4 - (br_table $switch-case9 $label$break$Lout $label$break$Lout $switch-case6 $label$break$Lout $label$break$Lout $label$break$Lout $label$break$Lout $switch-case5 $label$break$Lout $switch-case4 $label$break$Lout - (i32.sub - (get_local $0) - (i32.const 2) - ) + (block $switch-case9 + (block $switch-case6 + (block $switch-case5 + (block $switch-case4 + (br_table $switch-case9 $switch-case9 $switch-case9 $switch-case6 $switch-case9 $switch-case9 $switch-case9 $switch-case9 $switch-case5 $switch-case9 $switch-case4 $switch-case9 + (i32.sub + (get_local $0) + (i32.const 2) ) ) ) diff --git a/test/unit.fromasm.imprecise b/test/unit.fromasm.imprecise index 3254980d9..f78f530c1 100644 --- a/test/unit.fromasm.imprecise +++ b/test/unit.fromasm.imprecise @@ -178,16 +178,14 @@ (i32.const 51) ) ) - (block $label$break$Lout - (block $switch-case9 - (block $switch-case6 - (block $switch-case5 - (block $switch-case4 - (br_table $switch-case9 $label$break$Lout $label$break$Lout $switch-case6 $label$break$Lout $label$break$Lout $label$break$Lout $label$break$Lout $switch-case5 $label$break$Lout $switch-case4 $label$break$Lout - (i32.sub - (get_local $0) - (i32.const 2) - ) + (block $switch-case9 + (block $switch-case6 + (block $switch-case5 + (block $switch-case4 + (br_table $switch-case9 $switch-case9 $switch-case9 $switch-case6 $switch-case9 $switch-case9 $switch-case9 $switch-case9 $switch-case5 $switch-case9 $switch-case4 $switch-case9 + (i32.sub + (get_local $0) + (i32.const 2) ) ) ) |