summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/CodePushing.cpp9
-rw-r--r--test/passes/code-pushing.txt60
-rw-r--r--test/passes/code-pushing.wast36
3 files changed, 96 insertions, 9 deletions
diff --git a/src/passes/CodePushing.cpp b/src/passes/CodePushing.cpp
index 397a20bab..f4beff1a8 100644
--- a/src/passes/CodePushing.cpp
+++ b/src/passes/CodePushing.cpp
@@ -115,7 +115,14 @@ private:
auto* set = curr->dynCast<SetLocal>();
if (!set) return nullptr;
auto index = set->index;
- return analyzer.isSFA(index) && numGetsSoFar[index] == analyzer.getNumGets(index) ? set : nullptr;
+ // to be pushable, this must be SFA and the right # of gets,
+ // but also have no side effects, as it may not execute if pushed.
+ if (analyzer.isSFA(index) &&
+ numGetsSoFar[index] == analyzer.getNumGets(index) &&
+ !EffectAnalyzer(set->value).hasSideEffects()) {
+ return set;
+ }
+ return nullptr;
}
// Push past conditional control flow.
diff --git a/test/passes/code-pushing.txt b/test/passes/code-pushing.txt
index b8c496210..f09d0dfb5 100644
--- a/test/passes/code-pushing.txt
+++ b/test/passes/code-pushing.txt
@@ -342,15 +342,15 @@
(local $x i32)
(local $y i32)
(block $out
- (br_if $out
- (i32.const 2)
- )
(set_local $x
(call $push-dropped)
)
(set_local $y
(call $push-dropped)
)
+ (br_if $out
+ (i32.const 2)
+ )
(drop
(get_local $x)
)
@@ -388,13 +388,13 @@
(local $y i32)
(block $out
(set_local $x
- (call $push-dropped)
+ (i32.const 1)
)
(br_if $out
(i32.const 2)
)
(set_local $y
- (call $push-dropped)
+ (i32.const 3)
)
(drop
(get_local $x)
@@ -407,4 +407,54 @@
(get_local $x)
)
)
+ (func $unpushed-ignorable-side-effect (type $0)
+ (local $x i32)
+ (local $y i32)
+ (block $out
+ (set_local $x
+ (call $push-dropped)
+ )
+ (br_if $out
+ (i32.const 2)
+ )
+ (set_local $y
+ (i32.const 3)
+ )
+ (drop
+ (get_local $x)
+ )
+ (drop
+ (get_local $y)
+ )
+ )
+ )
+ (func $unpushed-side-effect-into-drop (type $0)
+ (local $x i32)
+ (block $out
+ (set_local $x
+ (call $push-dropped)
+ )
+ (br_if $out
+ (i32.const 1)
+ )
+ (drop
+ (get_local $x)
+ )
+ )
+ )
+ (func $unpushed-side-effect-into-if (type $0)
+ (local $x i32)
+ (block $out
+ (set_local $x
+ (call $push-dropped)
+ )
+ (br_if $out
+ (i32.const 1)
+ )
+ (if
+ (get_local $x)
+ (nop)
+ )
+ )
+ )
)
diff --git a/test/passes/code-pushing.wast b/test/passes/code-pushing.wast
index ca973e182..e1cb30f4a 100644
--- a/test/passes/code-pushing.wast
+++ b/test/passes/code-pushing.wast
@@ -179,7 +179,7 @@
(drop (get_local $x))
)
)
- (func $values-might-interfere ;; but don't, as we keep the order
+ (func $values-might-interfere ;; they don't, as we keep the order - but here their side effects prevent pushing
(local $x i32)
(local $y i32)
(block $out
@@ -206,13 +206,43 @@
(local $x i32)
(local $y i32)
(block $out
- (set_local $x (call $push-dropped))
- (set_local $y (call $push-dropped))
+ (set_local $x (i32.const 1))
+ (set_local $y (i32.const 3))
(br_if $out (i32.const 2))
(drop (get_local $x))
(drop (get_local $y))
)
(drop (get_local $x)) ;; $x can't be pushed, but y doesn't care
)
+ (func $unpushed-ignorable-side-effect
+ (local $x i32)
+ (local $y i32)
+ (block $out
+ (set_local $x (call $push-dropped)) ;; $x can't be pushed, but y doesn't care
+ (set_local $y (i32.const 3))
+ (br_if $out (i32.const 2))
+ (drop (get_local $x))
+ (drop (get_local $y))
+ )
+ )
+ (func $unpushed-side-effect-into-drop
+ (local $x i32)
+ (block $out
+ (set_local $x (call $push-dropped))
+ (br_if $out (i32.const 1))
+ (drop (get_local $x))
+ )
+ )
+ (func $unpushed-side-effect-into-if
+ (local $x i32)
+ (block $out
+ (set_local $x (call $push-dropped))
+ (br_if $out (i32.const 1))
+ (if
+ (get_local $x)
+ (nop)
+ )
+ )
+ )
)