summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/SimplifyLocals.cpp19
-rw-r--r--test/passes/simplify-locals.txt69
-rw-r--r--test/passes/simplify-locals.wast24
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)
+ )
)