summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ast_utils.h1
-rw-r--r--src/passes/RemoveUnusedBrs.cpp7
-rw-r--r--src/passes/pass.cpp2
-rw-r--r--test/emcc_O2_hello_world.fromasm16
-rw-r--r--test/emcc_O2_hello_world.fromasm.imprecise16
-rw-r--r--test/emcc_hello_world.fromasm54
-rw-r--r--test/emcc_hello_world.fromasm.imprecise54
-rw-r--r--test/memorygrowth.fromasm16
-rw-r--r--test/memorygrowth.fromasm.imprecise16
-rw-r--r--test/passes/remove-unused-brs.txt41
-rw-r--r--test/passes/remove-unused-brs.wast39
-rw-r--r--test/unit.asm.js12
-rw-r--r--test/unit.fromasm11
-rw-r--r--test/unit.fromasm.imprecise11
-rw-r--r--test/unit.fromasm.imprecise.no-opts24
-rw-r--r--test/unit.fromasm.no-opts24
16 files changed, 247 insertions, 97 deletions
diff --git a/src/ast_utils.h b/src/ast_utils.h
index 0c2c318e2..8952114bc 100644
--- a/src/ast_utils.h
+++ b/src/ast_utils.h
@@ -105,7 +105,6 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer, Visitor<EffectAnalyzer
|| (accessesMemory() && (other.writesMemory || other.calls))) {
return true;
}
- assert(localsWritten.size() + localsRead.size() <= 1); // the code below is fast on that case, of one element vs many
for (auto local : localsWritten) {
if (other.localsWritten.count(local) || other.localsRead.count(local)) {
return true;
diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp
index ffdba0768..3f909c32e 100644
--- a/src/passes/RemoveUnusedBrs.cpp
+++ b/src/passes/RemoveUnusedBrs.cpp
@@ -128,6 +128,13 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs, Visitor<R
// if without an else. try to reduce if (condition) br => br_if (condition)
Break* br = curr->ifTrue->dynCast<Break>();
if (br && !br->condition) { // TODO: if there is a condition, join them
+ // if the br has a value, then if => br_if means we always execute the value, and also the order is value,condition vs condition,value
+ if (br->value) {
+ EffectAnalyzer value(br->value);
+ if (value.hasSideEffects()) return;
+ EffectAnalyzer condition(curr->condition);
+ if (condition.invalidates(value)) return;
+ }
br->condition = curr->condition;
replaceCurrent(br);
anotherCycle = true;
diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp
index e43b712e5..babb4635b 100644
--- a/src/passes/pass.cpp
+++ b/src/passes/pass.cpp
@@ -65,6 +65,7 @@ void PassRunner::addDefaultOptimizationPasses() {
add("optimize-instructions");
add("simplify-locals");
add("vacuum"); // previous pass creates garbage
+ add("remove-unused-brs"); // simplify-locals opens opportunities for phi optimizations
add("coalesce-locals");
add("vacuum"); // previous pass creates garbage
add("reorder-locals");
@@ -81,6 +82,7 @@ void PassRunner::addDefaultFunctionOptimizationPasses() {
add("optimize-instructions");
add("simplify-locals");
add("vacuum"); // previous pass creates garbage
+ add("remove-unused-brs"); // simplify-locals opens opportunities for phi optimizations
add("coalesce-locals");
add("vacuum"); // previous pass creates garbage
add("reorder-locals");
diff --git a/test/emcc_O2_hello_world.fromasm b/test/emcc_O2_hello_world.fromasm
index ad3f945f3..acbeb2a0b 100644
--- a/test/emcc_O2_hello_world.fromasm
+++ b/test/emcc_O2_hello_world.fromasm
@@ -4682,14 +4682,12 @@
)
)
(block
- (if
+ (br_if $do-once$67
+ (i32.const 31)
(i32.gt_u
(get_local $0)
(i32.const 16777215)
)
- (br $do-once$67
- (i32.const 31)
- )
)
(i32.or
(i32.and
@@ -8190,11 +8188,7 @@
)
)
(set_local $16
- (if
- (i32.eq
- (get_local $18)
- (i32.const 2)
- )
+ (select
(i32.const 0)
(i32.sub
(get_local $2)
@@ -8202,6 +8196,10 @@
(get_local $17)
)
)
+ (i32.eq
+ (get_local $18)
+ (i32.const 2)
+ )
)
)
)
diff --git a/test/emcc_O2_hello_world.fromasm.imprecise b/test/emcc_O2_hello_world.fromasm.imprecise
index ad3f945f3..acbeb2a0b 100644
--- a/test/emcc_O2_hello_world.fromasm.imprecise
+++ b/test/emcc_O2_hello_world.fromasm.imprecise
@@ -4682,14 +4682,12 @@
)
)
(block
- (if
+ (br_if $do-once$67
+ (i32.const 31)
(i32.gt_u
(get_local $0)
(i32.const 16777215)
)
- (br $do-once$67
- (i32.const 31)
- )
)
(i32.or
(i32.and
@@ -8190,11 +8188,7 @@
)
)
(set_local $16
- (if
- (i32.eq
- (get_local $18)
- (i32.const 2)
- )
+ (select
(i32.const 0)
(i32.sub
(get_local $2)
@@ -8202,6 +8196,10 @@
(get_local $17)
)
)
+ (i32.eq
+ (get_local $18)
+ (i32.const 2)
+ )
)
)
)
diff --git a/test/emcc_hello_world.fromasm b/test/emcc_hello_world.fromasm
index c7b334e7d..02e6d6002 100644
--- a/test/emcc_hello_world.fromasm
+++ b/test/emcc_hello_world.fromasm
@@ -1415,11 +1415,7 @@
)
)
(set_local $14
- (if
- (i32.eq
- (get_local $16)
- (i32.const 2)
- )
+ (select
(i32.const 0)
(i32.sub
(get_local $2)
@@ -1427,6 +1423,10 @@
(get_local $15)
)
)
+ (i32.eq
+ (get_local $16)
+ (i32.const 2)
+ )
)
)
)
@@ -5422,19 +5422,7 @@
)
(br $while-in$61)
)
- (if
- (i32.eq
- (i32.shr_s
- (i32.shl
- (i32.load8_s
- (get_local $11)
- )
- (i32.const 24)
- )
- (i32.const 24)
- )
- (i32.const 45)
- )
+ (select
(f64.neg
(f64.add
(get_local $29)
@@ -5453,6 +5441,18 @@
)
(get_local $29)
)
+ (i32.eq
+ (i32.shr_s
+ (i32.shl
+ (i32.load8_s
+ (get_local $11)
+ )
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ (i32.const 45)
+ )
)
)
)
@@ -5611,7 +5611,8 @@
(i32.const 1)
)
(block
- (if
+ (br_if $do-once$64
+ (get_local $1)
(i32.and
(get_local $13)
(i32.and
@@ -5622,9 +5623,6 @@
)
)
)
- (br $do-once$64
- (get_local $1)
- )
)
(i32.store8
(get_local $1)
@@ -5999,14 +5997,12 @@
)
(br $while-in$73)
)
- (if
+ (br_if $do-once$70
+ (get_local $8)
(i32.eq
(get_local $5)
(i32.const 0)
)
- (br $do-once$70
- (get_local $8)
- )
)
(i32.store
(set_local $6
@@ -14941,14 +14937,12 @@
)
(i32.const 0)
(block
- (if
+ (br_if $do-once$69
+ (i32.const 31)
(i32.gt_u
(get_local $4)
(i32.const 16777215)
)
- (br $do-once$69
- (i32.const 31)
- )
)
(set_local $1
(i32.shl
diff --git a/test/emcc_hello_world.fromasm.imprecise b/test/emcc_hello_world.fromasm.imprecise
index 29492cd2c..b7e3d5f59 100644
--- a/test/emcc_hello_world.fromasm.imprecise
+++ b/test/emcc_hello_world.fromasm.imprecise
@@ -1413,11 +1413,7 @@
)
)
(set_local $14
- (if
- (i32.eq
- (get_local $16)
- (i32.const 2)
- )
+ (select
(i32.const 0)
(i32.sub
(get_local $2)
@@ -1425,6 +1421,10 @@
(get_local $15)
)
)
+ (i32.eq
+ (get_local $16)
+ (i32.const 2)
+ )
)
)
)
@@ -5420,19 +5420,7 @@
)
(br $while-in$61)
)
- (if
- (i32.eq
- (i32.shr_s
- (i32.shl
- (i32.load8_s
- (get_local $11)
- )
- (i32.const 24)
- )
- (i32.const 24)
- )
- (i32.const 45)
- )
+ (select
(f64.neg
(f64.add
(get_local $29)
@@ -5451,6 +5439,18 @@
)
(get_local $29)
)
+ (i32.eq
+ (i32.shr_s
+ (i32.shl
+ (i32.load8_s
+ (get_local $11)
+ )
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ (i32.const 45)
+ )
)
)
)
@@ -5609,7 +5609,8 @@
(i32.const 1)
)
(block
- (if
+ (br_if $do-once$64
+ (get_local $1)
(i32.and
(get_local $13)
(i32.and
@@ -5620,9 +5621,6 @@
)
)
)
- (br $do-once$64
- (get_local $1)
- )
)
(i32.store8
(get_local $1)
@@ -5997,14 +5995,12 @@
)
(br $while-in$73)
)
- (if
+ (br_if $do-once$70
+ (get_local $8)
(i32.eq
(get_local $5)
(i32.const 0)
)
- (br $do-once$70
- (get_local $8)
- )
)
(i32.store
(set_local $6
@@ -14939,14 +14935,12 @@
)
(i32.const 0)
(block
- (if
+ (br_if $do-once$69
+ (i32.const 31)
(i32.gt_u
(get_local $4)
(i32.const 16777215)
)
- (br $do-once$69
- (i32.const 31)
- )
)
(set_local $1
(i32.shl
diff --git a/test/memorygrowth.fromasm b/test/memorygrowth.fromasm
index 07909b855..3d3f9468b 100644
--- a/test/memorygrowth.fromasm
+++ b/test/memorygrowth.fromasm
@@ -4750,14 +4750,12 @@
)
)
(block
- (if
+ (br_if $do-once$67
+ (i32.const 31)
(i32.gt_u
(get_local $0)
(i32.const 16777215)
)
- (br $do-once$67
- (i32.const 31)
- )
)
(i32.or
(i32.and
@@ -8245,11 +8243,7 @@
)
)
(set_local $16
- (if
- (i32.eq
- (get_local $18)
- (i32.const 2)
- )
+ (select
(i32.const 0)
(i32.sub
(get_local $2)
@@ -8257,6 +8251,10 @@
(get_local $17)
)
)
+ (i32.eq
+ (get_local $18)
+ (i32.const 2)
+ )
)
)
)
diff --git a/test/memorygrowth.fromasm.imprecise b/test/memorygrowth.fromasm.imprecise
index 07909b855..3d3f9468b 100644
--- a/test/memorygrowth.fromasm.imprecise
+++ b/test/memorygrowth.fromasm.imprecise
@@ -4750,14 +4750,12 @@
)
)
(block
- (if
+ (br_if $do-once$67
+ (i32.const 31)
(i32.gt_u
(get_local $0)
(i32.const 16777215)
)
- (br $do-once$67
- (i32.const 31)
- )
)
(i32.or
(i32.and
@@ -8245,11 +8243,7 @@
)
)
(set_local $16
- (if
- (i32.eq
- (get_local $18)
- (i32.const 2)
- )
+ (select
(i32.const 0)
(i32.sub
(get_local $2)
@@ -8257,6 +8251,10 @@
(get_local $17)
)
)
+ (i32.eq
+ (get_local $18)
+ (i32.const 2)
+ )
)
)
)
diff --git a/test/passes/remove-unused-brs.txt b/test/passes/remove-unused-brs.txt
index a8e7f29be..c3ac71057 100644
--- a/test/passes/remove-unused-brs.txt
+++ b/test/passes/remove-unused-brs.txt
@@ -281,4 +281,45 @@
)
)
)
+ (func $side-effects-and-order (result i32)
+ (local $x i32)
+ (block $do-once$0
+ (br_if $do-once$0
+ (i32.const 0)
+ (call $b13)
+ )
+ (i32.const 1)
+ )
+ (block $do-once$0
+ (if
+ (call $b13)
+ (br $do-once$0
+ (call $b14)
+ )
+ )
+ (i32.const 1)
+ )
+ (block $do-once$0
+ (if
+ (i32.const 0)
+ (br $do-once$0
+ (call $b14)
+ )
+ )
+ (i32.const 1)
+ )
+ (block $do-once$0
+ (if
+ (set_local $x
+ (i32.const 1)
+ )
+ (br $do-once$0
+ (set_local $x
+ (i32.const 2)
+ )
+ )
+ )
+ (i32.const 1)
+ )
+ )
)
diff --git a/test/passes/remove-unused-brs.wast b/test/passes/remove-unused-brs.wast
index 8b9d42bc1..b7dc1cc25 100644
--- a/test/passes/remove-unused-brs.wast
+++ b/test/passes/remove-unused-brs.wast
@@ -297,5 +297,44 @@
)
)
)
+ (func $side-effects-and-order (result i32)
+ (local $x i32)
+ (block $do-once$0
+ (if
+ (call $b13)
+ (br $do-once$0
+ (i32.const 0)
+ )
+ )
+ (i32.const 1)
+ )
+ (block $do-once$0
+ (if
+ (call $b13)
+ (br $do-once$0
+ (call $b14)
+ )
+ )
+ (i32.const 1)
+ )
+ (block $do-once$0
+ (if
+ (i32.const 0)
+ (br $do-once$0
+ (call $b14)
+ )
+ )
+ (i32.const 1)
+ )
+ (block $do-once$0
+ (if
+ (set_local $x (i32.const 1))
+ (br $do-once$0
+ (set_local $x (i32.const 2))
+ )
+ )
+ (i32.const 1)
+ )
+ )
)
diff --git a/test/unit.asm.js b/test/unit.asm.js
index 2f307e085..b0e4e7594 100644
--- a/test/unit.asm.js
+++ b/test/unit.asm.js
@@ -247,6 +247,18 @@ function asm(global, env, buffer) {
}
}
+ function phi() {
+ var x = 0;
+ do {
+ if (lb(1) | 0) {
+ x = 0;
+ break;
+ }
+ x = 1;
+ } while (0);
+ return x | 0;
+ }
+
function z() {
}
function w() {
diff --git a/test/unit.fromasm b/test/unit.fromasm
index 3fb76981d..38d8c2c67 100644
--- a/test/unit.fromasm
+++ b/test/unit.fromasm
@@ -453,4 +453,15 @@
)
)
)
+ (func $phi (result i32)
+ (block $do-once$0
+ (br_if $do-once$0
+ (i32.const 0)
+ (call $lb
+ (i32.const 1)
+ )
+ )
+ (i32.const 1)
+ )
+ )
)
diff --git a/test/unit.fromasm.imprecise b/test/unit.fromasm.imprecise
index a4716941d..b493c66d0 100644
--- a/test/unit.fromasm.imprecise
+++ b/test/unit.fromasm.imprecise
@@ -445,4 +445,15 @@
)
)
)
+ (func $phi (result i32)
+ (block $do-once$0
+ (br_if $do-once$0
+ (i32.const 0)
+ (call $lb
+ (i32.const 1)
+ )
+ )
+ (i32.const 1)
+ )
+ )
)
diff --git a/test/unit.fromasm.imprecise.no-opts b/test/unit.fromasm.imprecise.no-opts
index c3da01359..9f49824f3 100644
--- a/test/unit.fromasm.imprecise.no-opts
+++ b/test/unit.fromasm.imprecise.no-opts
@@ -721,6 +721,30 @@
)
)
)
+ (func $phi (result i32)
+ (local $x i32)
+ (block $do-once$0
+ (block
+ (if
+ (call $lb
+ (i32.const 1)
+ )
+ (block
+ (set_local $x
+ (i32.const 0)
+ )
+ (br $do-once$0)
+ )
+ )
+ (set_local $x
+ (i32.const 1)
+ )
+ )
+ )
+ (return
+ (get_local $x)
+ )
+ )
(func $z
(nop)
)
diff --git a/test/unit.fromasm.no-opts b/test/unit.fromasm.no-opts
index 92d2d2add..ccf89c5b6 100644
--- a/test/unit.fromasm.no-opts
+++ b/test/unit.fromasm.no-opts
@@ -725,6 +725,30 @@
)
)
)
+ (func $phi (result i32)
+ (local $x i32)
+ (block $do-once$0
+ (block
+ (if
+ (call $lb
+ (i32.const 1)
+ )
+ (block
+ (set_local $x
+ (i32.const 0)
+ )
+ (br $do-once$0)
+ )
+ )
+ (set_local $x
+ (i32.const 1)
+ )
+ )
+ )
+ (return
+ (get_local $x)
+ )
+ )
(func $z
(nop)
)