diff options
-rw-r--r-- | src/passes/RemoveUnusedBrs.cpp | 36 | ||||
-rw-r--r-- | test/passes/O3_inlining.txt | 8 | ||||
-rw-r--r-- | test/passes/converge_O3_metrics.bin.txt | 32 | ||||
-rw-r--r-- | test/passes/inlining-optimizing_optimize-level=3.txt | 14 | ||||
-rw-r--r-- | test/passes/remove-unused-brs_enable-multivalue.txt | 90 | ||||
-rw-r--r-- | test/passes/remove-unused-brs_enable-multivalue.wast | 67 | ||||
-rw-r--r-- | test/wasm2js/i64-add-sub.2asm.js.opt | 4 | ||||
-rw-r--r-- | test/wasm2js/i64-ctz.2asm.js.opt | 26 | ||||
-rw-r--r-- | test/wasm2js/unary-ops.2asm.js.opt | 26 |
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; |