summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/OptimizeInstructions.cpp48
-rw-r--r--test/lit/passes/inlining-optimizing_optimize-level=3.wast40
-rw-r--r--test/lit/passes/optimize-instructions.wast111
-rw-r--r--test/passes/O3_low-memory-unused_metrics.txt8
-rw-r--r--test/passes/fannkuch3_manyopts_dwarf.bin.txt8
-rw-r--r--test/wasm2js/i64-ctz.2asm.js.opt4
-rw-r--r--test/wasm2js/stack-modified.2asm.js.opt2
-rw-r--r--test/wasm2js/unary-ops.2asm.js.opt4
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;