diff options
-rw-r--r-- | src/passes/SimplifyLocals.cpp | 19 | ||||
-rw-r--r-- | test/passes/simplify-locals.txt | 69 | ||||
-rw-r--r-- | test/passes/simplify-locals.wast | 24 |
3 files changed, 89 insertions, 23 deletions
diff --git a/src/passes/SimplifyLocals.cpp b/src/passes/SimplifyLocals.cpp index efc73aa29..e032acc77 100644 --- a/src/passes/SimplifyLocals.cpp +++ b/src/passes/SimplifyLocals.cpp @@ -102,8 +102,8 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals, // block returns std::map<Name, std::vector<BlockBreak>> blockBreaks; - // blocks that are the targets of a switch; we need to know this - // since we can't produce a block return value for them. + // blocks that we can't produce a block return value for them. + // (switch target, or some other reason) std::set<Name> unoptimizableBlocks; // A stack of sinkables from the current traversal state. When @@ -328,9 +328,18 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals, for (size_t j = 0; j < breaks.size(); j++) { // move break set_local's value to the break auto* breakSetLocalPointer = breaks[j].sinkables.at(sharedIndex).item; - assert(!breaks[j].br->value); - breaks[j].br->value = (*breakSetLocalPointer)->cast<SetLocal>()->value; - ExpressionManipulator::nop(*breakSetLocalPointer); + auto* br = breaks[j].br; + assert(!br->value); + // if the break is conditional, then we must set the value here - if the break is not taken, we must still have the new value in the local + auto* set = (*breakSetLocalPointer)->cast<SetLocal>(); + if (br->condition) { + br->value = set; + set->setTee(true); + *breakSetLocalPointer = getModule()->allocator.alloc<Nop>(); + } else { + br->value = set->value; + ExpressionManipulator::nop(set); + } } // finally, create a set_local on the block itself auto* newSetLocal = Builder(*getModule()).makeSetLocal(sharedIndex, block); diff --git a/test/passes/simplify-locals.txt b/test/passes/simplify-locals.txt index 72bd7aa12..4b7cd2bb3 100644 --- a/test/passes/simplify-locals.txt +++ b/test/passes/simplify-locals.txt @@ -7,11 +7,13 @@ (type $4 (func (param i32))) (type $5 (func (param i32) (result i32))) (type $6 (func (param i32 i32 i32 i32 i32 i32))) - (type $7 (func (param i32 i32))) + (type $FUNCSIG$iii (func (param i32 i32) (result i32))) + (type $8 (func (param i32 i32))) (import "env" "waka" (func $waka)) (import "env" "waka_int" (func $waka_int (result i32))) (import "env" "i64sub" (func $_i64Subtract (param i32 i32 i32 i32) (result i32))) (import "env" "moddi" (func $___udivmoddi4 (param i32 i32 i32 i32 i32) (result i32))) + (import "env" "lp" (func $lp (param i32 i32) (result i32))) (func $b0-yes (type $4) (param $i1 i32) (local $x i32) (local $y i32) @@ -576,14 +578,18 @@ (block $out (nop) (br_if $out - (block $waka - (nop) - (br_if $waka - (i32.const 12) - (i32.const 1) + (tee_local $x + (block $waka + (nop) + (br_if $waka + (tee_local $x + (i32.const 12) + ) + (i32.const 1) + ) + (nop) + (i32.const 34) ) - (nop) - (i32.const 34) ) (i32.const 1) ) @@ -607,15 +613,17 @@ (nop) ) (br_if $out - (if - (i32.const 1) - (block $block3 - (nop) - (i32.const 14) - ) - (block $block5 - (nop) - (i32.const 25) + (tee_local $x + (if + (i32.const 1) + (block $block3 + (nop) + (i32.const 14) + ) + (block $block5 + (nop) + (i32.const 25) + ) ) ) (i32.const 1) @@ -674,7 +682,7 @@ (get_local $i1) ) ) - (func $no-out-of-label (type $7) (param $x i32) (param $y i32) + (func $no-out-of-label (type $8) (param $x i32) (param $y i32) (loop $moar (set_local $x (block $block0 @@ -702,4 +710,29 @@ (get_local $y) ) ) + (func $freetype-cd (type $5) (param $a i32) (result i32) + (local $e i32) + (loop $while-in$1 + (set_local $a + (block $while-out$0 + (set_local $e + (get_local $a) + ) + (nop) + (br_if $while-out$0 + (tee_local $a + (i32.const 4) + ) + (get_local $e) + ) + (nop) + (i32.add + (get_local $a) + (i32.const 0) + ) + ) + ) + ) + (get_local $a) + ) ) diff --git a/test/passes/simplify-locals.wast b/test/passes/simplify-locals.wast index 2b5b84a5f..b703613d8 100644 --- a/test/passes/simplify-locals.wast +++ b/test/passes/simplify-locals.wast @@ -11,6 +11,7 @@ (import $waka_int "env" "waka_int" (result i32)) (import $_i64Subtract "env" "i64sub" (param i32 i32 i32 i32) (result i32)) (import $___udivmoddi4 "env" "moddi" (param i32 i32 i32 i32 i32) (result i32)) + (import $lp "env" "lp" (param i32 i32) (result i32)) (func $b0-yes (type $4) (param $i1 i32) (local $x i32) (local $y i32) @@ -751,4 +752,27 @@ ) (drop (get_local $y)) ) + (func $freetype-cd (param $a i32) (result i32) + (local $e i32) + (loop $while-in$1 + (block $while-out$0 + (set_local $e + (get_local $a) + ) + (set_local $a ;; this set must happen, so that if the br_if does not break, we have the right $a later down - once we use a block return value, the $a set's outside the block + (i32.const 4) + ) + (br_if $while-out$0 + (get_local $e) + ) + (set_local $a + (i32.add + (get_local $a) + (i32.const 0) + ) + ) + ) + ) + (get_local $a) + ) ) |