summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/RemoveUnusedBrs.cpp36
-rw-r--r--test/passes/O3_inlining.txt8
-rw-r--r--test/passes/converge_O3_metrics.bin.txt32
-rw-r--r--test/passes/inlining-optimizing_optimize-level=3.txt14
-rw-r--r--test/passes/remove-unused-brs_enable-multivalue.txt90
-rw-r--r--test/passes/remove-unused-brs_enable-multivalue.wast67
-rw-r--r--test/wasm2js/i64-add-sub.2asm.js.opt4
-rw-r--r--test/wasm2js/i64-ctz.2asm.js.opt26
-rw-r--r--test/wasm2js/unary-ops.2asm.js.opt26
9 files changed, 225 insertions, 78 deletions
diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp
index 0a3374c4d..6e9c9c5df 100644
--- a/src/passes/RemoveUnusedBrs.cpp
+++ b/src/passes/RemoveUnusedBrs.cpp
@@ -930,6 +930,17 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
!iff->ifFalse->type.isSingle()) {
return nullptr;
}
+ if (iff->condition->type == Type::unreachable) {
+ // An if with an unreachable condition may nonetheless have a type
+ // that is not unreachable,
+ //
+ // (if (result i32) (unreachable) ..)
+ //
+ // Turning such an if into a select would change the type of the
+ // expression, which would require updating types further up. Avoid
+ // that, leaving dead code elimination to that dedicated pass.
+ return nullptr;
+ }
// This is always helpful for code size, but can be a tradeoff with
// performance as we run both code paths. So when shrinking we always
// try to do this, but otherwise must consider more carefully.
@@ -937,20 +948,23 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
passOptions, iff->ifTrue, iff->ifFalse)) {
return nullptr;
}
- // Check if side effects allow this.
+ // Check if side effects allow this: we need to execute the two arms
+ // unconditionally, and also to make the condition run last.
FeatureSet features = getModule()->features;
+ EffectAnalyzer ifTrue(passOptions, features, iff->ifTrue);
+ if (ifTrue.hasSideEffects()) {
+ return nullptr;
+ }
+ EffectAnalyzer ifFalse(passOptions, features, iff->ifFalse);
+ if (ifFalse.hasSideEffects()) {
+ return nullptr;
+ }
EffectAnalyzer condition(passOptions, features, iff->condition);
- if (!condition.hasSideEffects()) {
- EffectAnalyzer ifTrue(passOptions, features, iff->ifTrue);
- if (!ifTrue.hasSideEffects()) {
- EffectAnalyzer ifFalse(passOptions, features, iff->ifFalse);
- if (!ifFalse.hasSideEffects()) {
- return Builder(*getModule())
- .makeSelect(iff->condition, iff->ifTrue, iff->ifFalse);
- }
- }
+ if (condition.invalidates(ifTrue) || condition.invalidates(ifFalse)) {
+ return nullptr;
}
- return nullptr;
+ return Builder(*getModule())
+ .makeSelect(iff->condition, iff->ifTrue, iff->ifFalse);
}
void visitLocalSet(LocalSet* curr) {
diff --git a/test/passes/O3_inlining.txt b/test/passes/O3_inlining.txt
index 79efb08a3..9c8f9eb4e 100644
--- a/test/passes/O3_inlining.txt
+++ b/test/passes/O3_inlining.txt
@@ -13,12 +13,8 @@
)
(if
(i32.eqz
- (if (result i32)
- (i32.load16_u
- (i32.const 3)
- )
- (i32.const 1)
- (i32.const 0)
+ (i32.load16_u
+ (i32.const 3)
)
)
(unreachable)
diff --git a/test/passes/converge_O3_metrics.bin.txt b/test/passes/converge_O3_metrics.bin.txt
index 0341fd6a4..fe69552fc 100644
--- a/test/passes/converge_O3_metrics.bin.txt
+++ b/test/passes/converge_O3_metrics.bin.txt
@@ -6,18 +6,18 @@ total
[imports] : 3
[memory-data] : 28
[table-data] : 429
- [total] : 132
+ [total] : 129
[vars] : 4
binary : 12
block : 8
break : 3
call : 3
call_indirect : 4
- const : 47
+ const : 45
drop : 3
global.get : 1
global.set : 1
- if : 3
+ if : 2
load : 16
local.get : 18
local.set : 7
@@ -71,13 +71,9 @@ total
(i32.const 2)
)
(drop
- (if (result i32)
- (call $import$0
- (i32.const 146)
- (local.get $0)
- )
- (i32.const -1)
- (i32.const 0)
+ (call $import$0
+ (i32.const 146)
+ (local.get $0)
)
)
(i32.const 1)
@@ -251,18 +247,18 @@ total
[imports] : 3
[memory-data] : 28
[table-data] : 429
- [total] : 132
+ [total] : 129
[vars] : 4
binary : 12
block : 8
break : 3
call : 3
call_indirect : 4
- const : 47
+ const : 45
drop : 3
global.get : 1
global.set : 1
- if : 3
+ if : 2
load : 16
local.get : 18
local.set : 7
@@ -316,13 +312,9 @@ total
(i32.const 2)
)
(drop
- (if (result i32)
- (call $import$0
- (i32.const 146)
- (local.get $0)
- )
- (i32.const -1)
- (i32.const 0)
+ (call $import$0
+ (i32.const 146)
+ (local.get $0)
)
)
(i32.const 1)
diff --git a/test/passes/inlining-optimizing_optimize-level=3.txt b/test/passes/inlining-optimizing_optimize-level=3.txt
index a127ec001..c49fead59 100644
--- a/test/passes/inlining-optimizing_optimize-level=3.txt
+++ b/test/passes/inlining-optimizing_optimize-level=3.txt
@@ -3997,13 +3997,7 @@
)
)
)
- (if (result f64)
- (i32.eq
- (i32.load8_s
- (local.get $9)
- )
- (i32.const 45)
- )
+ (select
(f64.neg
(f64.add
(local.get $14)
@@ -4022,6 +4016,12 @@
)
(local.get $14)
)
+ (i32.eq
+ (i32.load8_s
+ (local.get $9)
+ )
+ (i32.const 45)
+ )
)
)
)
diff --git a/test/passes/remove-unused-brs_enable-multivalue.txt b/test/passes/remove-unused-brs_enable-multivalue.txt
index 7d5b0e7fd..de4109665 100644
--- a/test/passes/remove-unused-brs_enable-multivalue.txt
+++ b/test/passes/remove-unused-brs_enable-multivalue.txt
@@ -1,6 +1,6 @@
(module
- (type $none_=>_none (func))
(type $i32_=>_none (func (param i32)))
+ (type $none_=>_none (func))
(type $none_=>_i32 (func (result i32)))
(type $i32_i32_=>_i32 (func (param i32 i32) (result i32)))
(type $i32_=>_i32 (func (param i32) (result i32)))
@@ -2285,6 +2285,83 @@
)
)
)
+ (func $selectify-even-with-condition-side-effects (param $0 i32)
+ (drop
+ (select
+ (i32.const 1)
+ (i32.const 0)
+ (i32.rem_s
+ (local.get $0)
+ (i32.const 2)
+ )
+ )
+ )
+ )
+ (func $no-selectify-when-arm-side-effects (param $0 i32)
+ (drop
+ (if (result i32)
+ (i32.rem_s
+ (local.get $0)
+ (i32.const 2)
+ )
+ (local.tee $0
+ (i32.const 1)
+ )
+ (i32.const 0)
+ )
+ )
+ (drop
+ (if (result i32)
+ (i32.rem_s
+ (local.get $0)
+ (i32.const 2)
+ )
+ (i32.const 0)
+ (local.tee $0
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ (func $no-selectify-when-effects-invalidate (param $0 i32)
+ (local $1 i32)
+ (drop
+ (if (result i32)
+ (i32.rem_s
+ (local.tee $0
+ (i32.const 3)
+ )
+ (i32.const 2)
+ )
+ (local.get $0)
+ (i32.const 0)
+ )
+ )
+ (drop
+ (if (result i32)
+ (i32.rem_s
+ (local.tee $0
+ (i32.const 3)
+ )
+ (i32.const 2)
+ )
+ (i32.const 0)
+ (local.get $0)
+ )
+ )
+ (drop
+ (select
+ (i32.const 0)
+ (local.get $1)
+ (i32.rem_s
+ (local.tee $0
+ (i32.const 3)
+ )
+ (i32.const 2)
+ )
+ )
+ )
+ )
(func $if-one-side (result i32)
(local $x i32)
(local.set $x
@@ -2525,4 +2602,15 @@
)
)
)
+ (func $no-selectify-if-condition-unreachable (result i32)
+ (select
+ (if (result i32)
+ (unreachable)
+ (i32.const 3)
+ (i32.const 4)
+ )
+ (i32.const 1)
+ (i32.const 2)
+ )
+ )
)
diff --git a/test/passes/remove-unused-brs_enable-multivalue.wast b/test/passes/remove-unused-brs_enable-multivalue.wast
index ceefefa40..6b5b4b1a7 100644
--- a/test/passes/remove-unused-brs_enable-multivalue.wast
+++ b/test/passes/remove-unused-brs_enable-multivalue.wast
@@ -1890,6 +1890,62 @@
)
)
)
+ (func $selectify-even-with-condition-side-effects (param $0 i32)
+ (drop (if (result i32)
+ (i32.rem_s
+ (local.get $0)
+ (i32.const 2)
+ )
+ (i32.const 1)
+ (i32.const 0)
+ ))
+ )
+ (func $no-selectify-when-arm-side-effects (param $0 i32)
+ (drop (if (result i32)
+ (i32.rem_s
+ (local.get $0)
+ (i32.const 2)
+ )
+ (local.tee $0 (i32.const 1))
+ (i32.const 0)
+ ))
+ (drop (if (result i32)
+ (i32.rem_s
+ (local.get $0)
+ (i32.const 2)
+ )
+ (i32.const 0)
+ (local.tee $0 (i32.const 1))
+ ))
+ )
+ (func $no-selectify-when-effects-invalidate (param $0 i32)
+ (local $1 i32)
+ (drop (if (result i32)
+ (i32.rem_s
+ (local.tee $0 (i32.const 3))
+ (i32.const 2)
+ )
+ (local.get $0)
+ (i32.const 0)
+ ))
+ (drop (if (result i32)
+ (i32.rem_s
+ (local.tee $0 (i32.const 3))
+ (i32.const 2)
+ )
+ (i32.const 0)
+ (local.get $0)
+ ))
+ ;; but different locals do not invalidate
+ (drop (if (result i32)
+ (i32.rem_s
+ (local.tee $0 (i32.const 3))
+ (i32.const 2)
+ )
+ (i32.const 0)
+ (local.get $1)
+ ))
+ )
(func $if-one-side (result i32)
(local $x i32)
(local.set $x
@@ -2128,4 +2184,15 @@
)
)
)
+ (func $no-selectify-if-condition-unreachable (result i32)
+ (select
+ (if (result i32)
+ (unreachable)
+ (i32.const 3)
+ (i32.const 4)
+ )
+ (i32.const 1)
+ (i32.const 2)
+ )
+ )
)
diff --git a/test/wasm2js/i64-add-sub.2asm.js.opt b/test/wasm2js/i64-add-sub.2asm.js.opt
index 6d00c9321..d44e7657d 100644
--- a/test/wasm2js/i64-add-sub.2asm.js.opt
+++ b/test/wasm2js/i64-add-sub.2asm.js.opt
@@ -21,9 +21,7 @@ function asmFunc(global, env) {
$5 = $5 | 0;
$1_1 = $1_1 + $3 | 0;
$0 = $0 + $2 | 0;
- if ($2 >>> 0 > $0 >>> 0) {
- $1_1 = $1_1 + 1 | 0
- }
+ $1_1 = $2 >>> 0 > $0 >>> 0 ? $1_1 + 1 | 0 : $1_1;
return ($0 | 0) == ($4 | 0) & ($1_1 | 0) == ($5 | 0);
}
diff --git a/test/wasm2js/i64-ctz.2asm.js.opt b/test/wasm2js/i64-ctz.2asm.js.opt
index 4cb4f79ff..9edec2848 100644
--- a/test/wasm2js/i64-ctz.2asm.js.opt
+++ b/test/wasm2js/i64-ctz.2asm.js.opt
@@ -30,14 +30,12 @@ function asmFunc(global, env) {
function __wasm_ctz_i64($0, $1) {
var $2 = 0, $3 = 0;
if ($0 | $1) {
- $3 = $1 + -1 | 0;
- $2 = $0 + -1 | 0;
- if (($2 | 0) != -1) {
- $3 = $3 + 1 | 0
- }
- $2 = Math_clz32($0 ^ $2) + 32 | 0;
- $0 = Math_clz32($1 ^ $3);
- $0 = ($0 | 0) == 32 ? $2 : $0;
+ $2 = $1 + -1 | 0;
+ $3 = $0 + -1 | 0;
+ $2 = ($3 | 0) != -1 ? $2 + 1 | 0 : $2;
+ $3 = Math_clz32($0 ^ $3) + 32 | 0;
+ $0 = Math_clz32($1 ^ $2);
+ $0 = ($0 | 0) == 32 ? $3 : $0;
$1 = 63 - $0 | 0;
i64toi32_i32$HIGH_BITS = 0 - ($0 >>> 0 > 63) | 0;
return $1;
@@ -49,17 +47,15 @@ function asmFunc(global, env) {
function __wasm_popcnt_i64($0, $1) {
var $2 = 0, $3 = 0, $4 = 0, $5 = 0;
while (1) {
- $5 = $3;
- $2 = $4;
+ $5 = $4;
+ $2 = $3;
if ($0 | $1) {
$2 = $0;
$0 = $2 - 1 & $2;
$1 = $1 - ($2 >>> 0 < 1) & $1;
- $2 = $3 + 1 | 0;
- if ($2 >>> 0 < 1) {
- $4 = $4 + 1 | 0
- }
- $3 = $2;
+ $2 = $4 + 1 | 0;
+ $3 = $2 >>> 0 < 1 ? $3 + 1 | 0 : $3;
+ $4 = $2;
continue;
}
break;
diff --git a/test/wasm2js/unary-ops.2asm.js.opt b/test/wasm2js/unary-ops.2asm.js.opt
index 9bda50800..d42ea3e97 100644
--- a/test/wasm2js/unary-ops.2asm.js.opt
+++ b/test/wasm2js/unary-ops.2asm.js.opt
@@ -71,14 +71,12 @@ function asmFunc(global, env) {
function __wasm_ctz_i64($0, $1_1) {
var $2 = 0, $3 = 0;
if ($0 | $1_1) {
- $3 = $1_1 + -1 | 0;
- $2 = $0 + -1 | 0;
- if (($2 | 0) != -1) {
- $3 = $3 + 1 | 0
- }
- $2 = Math_clz32($0 ^ $2) + 32 | 0;
- $0 = Math_clz32($1_1 ^ $3);
- $0 = ($0 | 0) == 32 ? $2 : $0;
+ $2 = $1_1 + -1 | 0;
+ $3 = $0 + -1 | 0;
+ $2 = ($3 | 0) != -1 ? $2 + 1 | 0 : $2;
+ $3 = Math_clz32($0 ^ $3) + 32 | 0;
+ $0 = Math_clz32($1_1 ^ $2);
+ $0 = ($0 | 0) == 32 ? $3 : $0;
$1_1 = 63 - $0 | 0;
i64toi32_i32$HIGH_BITS = 0 - ($0 >>> 0 > 63) | 0;
return $1_1;
@@ -104,17 +102,15 @@ function asmFunc(global, env) {
function __wasm_popcnt_i64($0, $1_1) {
var $2 = 0, $3 = 0, $4 = 0, $5 = 0;
while (1) {
- $5 = $3;
- $2 = $4;
+ $5 = $4;
+ $2 = $3;
if ($0 | $1_1) {
$2 = $0;
$0 = $2 - 1 & $2;
$1_1 = $1_1 - ($2 >>> 0 < 1) & $1_1;
- $2 = $3 + 1 | 0;
- if ($2 >>> 0 < 1) {
- $4 = $4 + 1 | 0
- }
- $3 = $2;
+ $2 = $4 + 1 | 0;
+ $3 = $2 >>> 0 < 1 ? $3 + 1 | 0 : $3;
+ $4 = $2;
continue;
}
break;