diff options
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 48 | ||||
-rw-r--r-- | test/lit/passes/inlining-optimizing_optimize-level=3.wast | 40 | ||||
-rw-r--r-- | test/lit/passes/optimize-instructions.wast | 111 | ||||
-rw-r--r-- | test/passes/O3_low-memory-unused_metrics.txt | 8 | ||||
-rw-r--r-- | test/passes/fannkuch3_manyopts_dwarf.bin.txt | 8 | ||||
-rw-r--r-- | test/wasm2js/i64-ctz.2asm.js.opt | 4 | ||||
-rw-r--r-- | test/wasm2js/stack-modified.2asm.js.opt | 2 | ||||
-rw-r--r-- | test/wasm2js/unary-ops.2asm.js.opt | 4 |
8 files changed, 180 insertions, 45 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index f23c119ec..a52126c5a 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1869,14 +1869,58 @@ private: }; // Prefer a const on the right. if (binary->left->is<Const>() && !binary->right->is<Const>()) { - return swap(); + swap(); } if (auto* c = binary->right->dynCast<Const>()) { - // x - C ==> x + (-C) + // x - C ==> x + (-C) // Prefer use addition if there is a constant on the right. if (binary->op == Abstract::getBinary(c->type, Abstract::Sub)) { c->value = c->value.neg(); binary->op = Abstract::getBinary(c->type, Abstract::Add); + return; + } + // Prefer to compare to 0 instead of to -1 or 1. + // (signed)x > -1 ==> x >= 0 + if (binary->op == Abstract::getBinary(c->type, Abstract::GtS) && + c->value.getInteger() == -1LL) { + binary->op = Abstract::getBinary(c->type, Abstract::GeS); + c->value = Literal::makeZero(c->type); + return; + } + // (signed)x <= -1 ==> x < 0 + if (binary->op == Abstract::getBinary(c->type, Abstract::LeS) && + c->value.getInteger() == -1LL) { + binary->op = Abstract::getBinary(c->type, Abstract::LtS); + c->value = Literal::makeZero(c->type); + return; + } + // (signed)x < 1 ==> x <= 0 + if (binary->op == Abstract::getBinary(c->type, Abstract::LtS) && + c->value.getInteger() == 1LL) { + binary->op = Abstract::getBinary(c->type, Abstract::LeS); + c->value = Literal::makeZero(c->type); + return; + } + // (signed)x >= 1 ==> x > 0 + if (binary->op == Abstract::getBinary(c->type, Abstract::GeS) && + c->value.getInteger() == 1LL) { + binary->op = Abstract::getBinary(c->type, Abstract::GtS); + c->value = Literal::makeZero(c->type); + return; + } + // (unsigned)x < 1 ==> x == 0 + if (binary->op == Abstract::getBinary(c->type, Abstract::LtU) && + c->value.getInteger() == 1LL) { + binary->op = Abstract::getBinary(c->type, Abstract::Eq); + c->value = Literal::makeZero(c->type); + return; + } + // (unsigned)x >= 1 ==> x != 0 + if (binary->op == Abstract::getBinary(c->type, Abstract::GeU) && + c->value.getInteger() == 1LL) { + binary->op = Abstract::getBinary(c->type, Abstract::Ne); + c->value = Literal::makeZero(c->type); + return; } return; } diff --git a/test/lit/passes/inlining-optimizing_optimize-level=3.wast b/test/lit/passes/inlining-optimizing_optimize-level=3.wast index 1ae11b22a..3a5e89e67 100644 --- a/test/lit/passes/inlining-optimizing_optimize-level=3.wast +++ b/test/lit/passes/inlining-optimizing_optimize-level=3.wast @@ -434,11 +434,11 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_s + ;; CHECK-NEXT: (i32.le_s ;; CHECK-NEXT: (i32.load8_s offset=74 ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.store ;; CHECK-NEXT: (local.get $0) @@ -1326,11 +1326,11 @@ ;; CHECK-NEXT: (local.set $0 ;; CHECK-NEXT: (block $do-once (result i32) ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.le_s + ;; CHECK-NEXT: (i32.lt_s ;; CHECK-NEXT: (i32.load offset=76 ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br $do-once ;; CHECK-NEXT: (call $___fflush_unlocked @@ -2709,11 +2709,11 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $2 ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.gt_s + ;; CHECK-NEXT: (i32.ge_s ;; CHECK-NEXT: (i32.load8_s offset=75 ;; CHECK-NEXT: (local.get $2) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block $label$break$L10 (result i32) ;; CHECK-NEXT: (local.set $3 @@ -4232,9 +4232,9 @@ ;; CHECK-NEXT: (loop $label$continue$L1 ;; CHECK-NEXT: (block $label$break$L1 ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.gt_s + ;; CHECK-NEXT: (i32.ge_s ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: (i32.const -1) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $18 ;; CHECK-NEXT: (if (result i32) @@ -5089,9 +5089,9 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $16 - ;; CHECK-NEXT: (i32.gt_s + ;; CHECK-NEXT: (i32.ge_s ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: (i32.const -1) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block $__rjto$2 @@ -6103,9 +6103,9 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (i32.lt_s + ;; CHECK-NEXT: (i32.le_s ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $20 @@ -7975,9 +7975,9 @@ ;; CHECK-NEXT: (i32.const 48) ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.gt_s + ;; CHECK-NEXT: (i32.ge_s ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const -1) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block (result i32) ;; CHECK-NEXT: (local.set $16 @@ -8048,9 +8048,9 @@ ;; CHECK-NEXT: (br_if $do-once115 ;; CHECK-NEXT: (i32.and ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (i32.lt_s + ;; CHECK-NEXT: (i32.le_s ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -8138,14 +8138,14 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $20) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.gt_s + ;; CHECK-NEXT: (i32.ge_s ;; CHECK-NEXT: (local.tee $7 ;; CHECK-NEXT: (i32.sub ;; CHECK-NEXT: (local.get $7) ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -8871,9 +8871,9 @@ ;; CHECK-NEXT: (i32.const -65537) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.gt_s + ;; CHECK-NEXT: (i32.ge_s ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const -1) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) diff --git a/test/lit/passes/optimize-instructions.wast b/test/lit/passes/optimize-instructions.wast index 76074dadf..638811586 100644 --- a/test/lit/passes/optimize-instructions.wast +++ b/test/lit/passes/optimize-instructions.wast @@ -1549,11 +1549,102 @@ ) )) ) - ;; CHECK: (func $canonicalize-cmp-const (param $x i32) (param $fx f64) + ;; CHECK: (func $canonicalize-cmp-near-zero (param $x i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.ge_s + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.lt_s ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.ge_s + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.lt_s + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.le_s + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.gt_s + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.ne + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $canonicalize-cmp-near-zero (param $x i32) + ;; i32(x) > -1 ==> x >= 0 + (drop (i32.gt_s + (local.get $x) + (i32.const -1) + )) + ;; i32(x) <= -1 ==> x < 0 + (drop (i32.le_s + (local.get $x) + (i32.const -1) + )) + ;; -1 < i32(x) ==> x >= 0 + (drop (i32.lt_s + (i32.const -1) + (local.get $x) + )) + ;; -1 >= i32(x) ==> x < 0 + (drop (i32.ge_s + (i32.const -1) + (local.get $x) + )) + ;; i32(x) < 1 ==> x <= 0 + (drop (i32.lt_s + (local.get $x) + (i32.const 1) + )) + ;; (signed)x >= 1 ==> x > 0 + (drop (i32.ge_s + (local.get $x) + (i32.const 1) + )) + ;; u32(x) < 1 ==> x == 0 + (drop (i32.lt_u + (local.get $x) + (i32.const 1) + )) + ;; u32(x) >= 1 ==> x != 0 + (drop (i32.ge_u + (local.get $x) + (i32.const 1) + )) + ) + ;; CHECK: (func $canonicalize-cmp-const (param $x i32) (param $fx f64) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.le_s + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop @@ -9596,15 +9687,15 @@ ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.gt_s + ;; CHECK-NEXT: (i32.ge_s ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -1) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.gt_s + ;; CHECK-NEXT: (i64.ge_s ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const -1) + ;; CHECK-NEXT: (i64.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop @@ -9619,15 +9710,15 @@ ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.le_s + ;; CHECK-NEXT: (i32.lt_s ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -1) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.le_s + ;; CHECK-NEXT: (i64.lt_s ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const -1) + ;; CHECK-NEXT: (i64.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop diff --git a/test/passes/O3_low-memory-unused_metrics.txt b/test/passes/O3_low-memory-unused_metrics.txt index 3de2d66fe..617b03a6d 100644 --- a/test/passes/O3_low-memory-unused_metrics.txt +++ b/test/passes/O3_low-memory-unused_metrics.txt @@ -2688,13 +2688,13 @@ total (i32.const 1) ) (br_if $label$1 - (i32.lt_s + (i32.le_s (local.tee $4 (i32.load offset=24 (local.get $2) ) ) - (i32.const 1) + (i32.const 0) ) ) (local.set $1 @@ -3106,13 +3106,13 @@ total ) ) (if - (i32.ge_s + (i32.gt_s (local.tee $0 (i32.load offset=24 (local.get $2) ) ) - (i32.const 1) + (i32.const 0) ) (i32.store offset=24 (local.get $2) diff --git a/test/passes/fannkuch3_manyopts_dwarf.bin.txt b/test/passes/fannkuch3_manyopts_dwarf.bin.txt index b2dca3117..00fed4beb 100644 --- a/test/passes/fannkuch3_manyopts_dwarf.bin.txt +++ b/test/passes/fannkuch3_manyopts_dwarf.bin.txt @@ -5711,11 +5711,11 @@ file_names[ 4]: ;; code offset: 0x30a (if ;; code offset: 0x309 - (i32.ge_s + (i32.gt_s ;; code offset: 0x305 (local.get $2) ;; code offset: 0x307 - (i32.const 1) + (i32.const 0) ) (block ;; code offset: 0x30c @@ -6578,11 +6578,11 @@ file_names[ 4]: ;; code offset: 0x5a8 (if ;; code offset: 0x5a7 - (i32.ge_s + (i32.gt_s ;; code offset: 0x5a3 (local.get $2) ;; code offset: 0x5a5 - (i32.const 1) + (i32.const 0) ) (block ;; code offset: 0x5aa diff --git a/test/wasm2js/i64-ctz.2asm.js.opt b/test/wasm2js/i64-ctz.2asm.js.opt index fc2e030b9..d1659d374 100644 --- a/test/wasm2js/i64-ctz.2asm.js.opt +++ b/test/wasm2js/i64-ctz.2asm.js.opt @@ -25,9 +25,9 @@ function asmFunc(env) { if ($0 | $2) { $1 = $0; $0 = $0 - 1 & $0; - $2 = $2 - ($1 >>> 0 < 1) & $2; + $2 = $2 - !$1 & $2; $3 = $3 + 1 | 0; - $4 = $3 >>> 0 < 1 ? $4 + 1 | 0 : $4; + $4 = $3 ? $4 : $4 + 1 | 0; continue; } break; diff --git a/test/wasm2js/stack-modified.2asm.js.opt b/test/wasm2js/stack-modified.2asm.js.opt index f08671743..63d2e4829 100644 --- a/test/wasm2js/stack-modified.2asm.js.opt +++ b/test/wasm2js/stack-modified.2asm.js.opt @@ -35,7 +35,7 @@ function asmFunc(env) { $8 = i64toi32_i32$HIGH_BITS; $1 = $0; $0 = $1 - 1 | 0; - $4 = $4 - ($1 >>> 0 < 1) | 0; + $4 = $4 - !$1 | 0; continue; } break; diff --git a/test/wasm2js/unary-ops.2asm.js.opt b/test/wasm2js/unary-ops.2asm.js.opt index ecf227753..86eee0e0a 100644 --- a/test/wasm2js/unary-ops.2asm.js.opt +++ b/test/wasm2js/unary-ops.2asm.js.opt @@ -54,9 +54,9 @@ function asmFunc(env) { if ($5 | $4) { $0 = $5; $5 = $0 - 1 & $0; - $4 = $4 - ($0 >>> 0 < 1) & $4; + $4 = $4 - !$0 & $4; $6_1 = $6_1 + 1 | 0; - $7_1 = $6_1 >>> 0 < 1 ? $7_1 + 1 | 0 : $7_1; + $7_1 = $6_1 ? $7_1 : $7_1 + 1 | 0; continue; } break; |