summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/OptimizeInstructions.cpp96
-rw-r--r--test/passes/O4_disable-bulk-memory.txt15
-rw-r--r--test/passes/inlining-optimizing_optimize-level=3.txt7
-rw-r--r--test/passes/optimize-instructions_all-features.txt138
-rw-r--r--test/passes/optimize-instructions_all-features.wast147
5 files changed, 375 insertions, 28 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index ecd30d711..24b7ee845 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -1592,12 +1592,30 @@ private:
curr->type = Type::i32;
return Builder(*getModule()).makeUnary(ExtendUInt32, curr);
}
- // (unsigned)x > -1 ==> 0
+ // (unsigned)x < 0 ==> i32(0)
+ if (matches(curr, binary(LtU, pure(&left), ival(0)))) {
+ right->value = Literal::makeZero(Type::i32);
+ right->type = Type::i32;
+ return right;
+ }
+ // (unsigned)x <= -1 ==> i32(1)
+ if (matches(curr, binary(LeU, pure(&left), ival(-1)))) {
+ right->value = Literal::makeOne(Type::i32);
+ right->type = Type::i32;
+ return right;
+ }
+ // (unsigned)x > -1 ==> i32(0)
if (matches(curr, binary(GtU, pure(&left), ival(-1)))) {
right->value = Literal::makeZero(Type::i32);
right->type = Type::i32;
return right;
}
+ // (unsigned)x >= 0 ==> i32(1)
+ if (matches(curr, binary(GeU, pure(&left), ival(0)))) {
+ right->value = Literal::makeOne(Type::i32);
+ right->type = Type::i32;
+ return right;
+ }
// (unsigned)x < -1 ==> x != -1
// Friendlier to JS emitting as we don't need to write an unsigned -1 value
// which is large.
@@ -1605,6 +1623,76 @@ private:
curr->op = Abstract::getBinary(type, Ne);
return curr;
}
+ // (unsigned)x <= 0 ==> x == 0
+ if (matches(curr, binary(LeU, any(), ival(0)))) {
+ curr->op = Abstract::getBinary(type, Eq);
+ return curr;
+ }
+ // (unsigned)x > 0 ==> x != 0
+ if (matches(curr, binary(GtU, any(), ival(0)))) {
+ curr->op = Abstract::getBinary(type, Ne);
+ return curr;
+ }
+ // (unsigned)x >= -1 ==> x == -1
+ if (matches(curr, binary(GeU, any(), ival(-1)))) {
+ curr->op = Abstract::getBinary(type, Eq);
+ return curr;
+ }
+ {
+ Const* c;
+ // (signed)x < (i32|i64).min_s ==> i32(0)
+ if (matches(curr, binary(LtS, pure(&left), ival(&c))) &&
+ c->value.isSignedMin()) {
+ right->value = Literal::makeZero(Type::i32);
+ right->type = Type::i32;
+ return right;
+ }
+ // (signed)x <= (i32|i64).max_s ==> i32(1)
+ if (matches(curr, binary(LeS, pure(&left), ival(&c))) &&
+ c->value.isSignedMax()) {
+ right->value = Literal::makeOne(Type::i32);
+ right->type = Type::i32;
+ return right;
+ }
+ // (signed)x > (i32|i64).max_s ==> i32(0)
+ if (matches(curr, binary(GtS, pure(&left), ival(&c))) &&
+ c->value.isSignedMax()) {
+ right->value = Literal::makeZero(Type::i32);
+ right->type = Type::i32;
+ return right;
+ }
+ // (signed)x >= (i32|i64).min_s ==> i32(1)
+ if (matches(curr, binary(GeS, pure(&left), ival(&c))) &&
+ c->value.isSignedMin()) {
+ right->value = Literal::makeOne(Type::i32);
+ right->type = Type::i32;
+ return right;
+ }
+ // (signed)x < (i32|i64).max_s ==> x != (i32|i64).max_s
+ if (matches(curr, binary(LtS, any(), ival(&c))) &&
+ c->value.isSignedMax()) {
+ curr->op = Abstract::getBinary(type, Ne);
+ return curr;
+ }
+ // (signed)x <= (i32|i64).min_s ==> x == (i32|i64).min_s
+ if (matches(curr, binary(LeS, any(), ival(&c))) &&
+ c->value.isSignedMin()) {
+ curr->op = Abstract::getBinary(type, Eq);
+ return curr;
+ }
+ // (signed)x > (i32|i64).min_s ==> x != (i32|i64).min_s
+ if (matches(curr, binary(GtS, any(), ival(&c))) &&
+ c->value.isSignedMin()) {
+ curr->op = Abstract::getBinary(type, Ne);
+ return curr;
+ }
+ // (signed)x >= (i32|i64).max_s ==> x == (i32|i64).max_s
+ if (matches(curr, binary(GeS, any(), ival(&c))) &&
+ c->value.isSignedMax()) {
+ curr->op = Abstract::getBinary(type, Eq);
+ return curr;
+ }
+ }
// x * -1 ==> 0 - x
if (matches(curr, binary(Mul, any(&left), ival(-1)))) {
right->value = Literal::makeZero(type);
@@ -1613,12 +1701,6 @@ private:
curr->right = left;
return curr;
}
- // (unsigned)x <= -1 ==> 1
- if (matches(curr, binary(LeU, pure(&left), ival(-1)))) {
- right->value = Literal::makeOne(Type::i32);
- right->type = Type::i32;
- return right;
- }
{
// ~(1 << x) aka (1 << x) ^ -1 ==> rotl(-2, x)
Expression* x;
diff --git a/test/passes/O4_disable-bulk-memory.txt b/test/passes/O4_disable-bulk-memory.txt
index 9a64a0834..b7a3dba06 100644
--- a/test/passes/O4_disable-bulk-memory.txt
+++ b/test/passes/O4_disable-bulk-memory.txt
@@ -196,18 +196,15 @@
(f64.store offset=24
(local.tee $1
(if (result i32)
- (i32.gt_u
- (i32.shr_u
- (i32.load
- (local.tee $1
- (i32.load
- (local.get $0)
- )
+ (i32.shr_u
+ (i32.load
+ (local.tee $1
+ (i32.load
+ (local.get $0)
)
)
- (i32.const 2)
)
- (i32.const 0)
+ (i32.const 2)
)
(i32.load offset=8
(local.get $1)
diff --git a/test/passes/inlining-optimizing_optimize-level=3.txt b/test/passes/inlining-optimizing_optimize-level=3.txt
index 42420c3c9..d9a621099 100644
--- a/test/passes/inlining-optimizing_optimize-level=3.txt
+++ b/test/passes/inlining-optimizing_optimize-level=3.txt
@@ -3645,7 +3645,7 @@
(i32.const 0)
(local.get $7)
)
- (i32.gt_u
+ (i32.ne
(local.get $5)
(i32.const 0)
)
@@ -7349,10 +7349,7 @@
(func $_fmt_u (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
(local $3 i32)
(if
- (i32.gt_u
- (local.get $1)
- (i32.const 0)
- )
+ (local.get $1)
(loop $while-in
(i32.store8
(local.tee $2
diff --git a/test/passes/optimize-instructions_all-features.txt b/test/passes/optimize-instructions_all-features.txt
index b80330ad6..4a58c210f 100644
--- a/test/passes/optimize-instructions_all-features.txt
+++ b/test/passes/optimize-instructions_all-features.txt
@@ -3441,13 +3441,7 @@
)
)
(drop
- (i64.le_s
- (i64.sub
- (local.get $x64)
- (i64.const 288230376151711744)
- )
- (i64.const 9223372036854775807)
- )
+ (i32.const 1)
)
)
(func $negatives-are-sometimes-better (param $x i32) (param $y i64) (param $z f32)
@@ -4264,6 +4258,30 @@
)
)
(drop
+ (i32.eq
+ (local.get $x)
+ (i32.const -1)
+ )
+ )
+ (drop
+ (i64.eq
+ (local.get $y)
+ (i64.const -1)
+ )
+ )
+ (drop
+ (i32.ne
+ (local.get $x)
+ (i32.const -1)
+ )
+ )
+ (drop
+ (i64.ne
+ (local.get $y)
+ (i64.const -1)
+ )
+ )
+ (drop
(i32.sub
(i32.const 0)
(local.get $x)
@@ -4362,6 +4380,112 @@
)
)
(drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 0)
+ )
+ (drop
+ (i32.const 0)
+ )
+ (drop
+ (i32.ne
+ (local.get $x)
+ (i32.const 0)
+ )
+ )
+ (drop
+ (i64.ne
+ (local.get $y)
+ (i64.const 0)
+ )
+ )
+ (drop
+ (i32.eqz
+ (local.get $x)
+ )
+ )
+ (drop
+ (i64.eqz
+ (local.get $y)
+ )
+ )
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 0)
+ )
+ (drop
+ (i32.const 0)
+ )
+ (drop
+ (i32.const 0)
+ )
+ (drop
+ (i32.const 0)
+ )
+ (drop
+ (i32.ne
+ (local.get $x)
+ (i32.const 2147483647)
+ )
+ )
+ (drop
+ (i64.ne
+ (local.get $y)
+ (i64.const 9223372036854775807)
+ )
+ )
+ (drop
+ (i32.ne
+ (local.get $x)
+ (i32.const -2147483648)
+ )
+ )
+ (drop
+ (i64.ne
+ (local.get $y)
+ (i64.const -9223372036854775808)
+ )
+ )
+ (drop
+ (i32.eq
+ (local.get $x)
+ (i32.const -2147483648)
+ )
+ )
+ (drop
+ (i64.eq
+ (local.get $y)
+ (i64.const -9223372036854775808)
+ )
+ )
+ (drop
+ (i32.eq
+ (local.get $x)
+ (i32.const 2147483647)
+ )
+ )
+ (drop
+ (i64.eq
+ (local.get $y)
+ (i64.const 9223372036854775807)
+ )
+ )
+ (drop
(f32.sub
(f32.const -0)
(local.get $fx)
diff --git a/test/passes/optimize-instructions_all-features.wast b/test/passes/optimize-instructions_all-features.wast
index cf35668d5..b28536519 100644
--- a/test/passes/optimize-instructions_all-features.wast
+++ b/test/passes/optimize-instructions_all-features.wast
@@ -4670,6 +4670,7 @@
(local.get $y)
(i64.const -1)
))
+ ;; (unsigned)x > -1 ==> 0
(drop (i32.gt_u
(local.get $x)
(i32.const -1)
@@ -4709,6 +4710,24 @@
(local.get $y)
(i64.const -1)
))
+ ;; (unsigned)x >= -1 ==> x == -1
+ (drop (i32.ge_u
+ (local.get $x)
+ (i32.const -1)
+ ))
+ (drop (i64.ge_u
+ (local.get $y)
+ (i64.const -1)
+ ))
+ ;; (unsigned)x < -1 ==> x != -1
+ (drop (i32.lt_u
+ (local.get $x)
+ (i32.const -1)
+ ))
+ (drop (i64.lt_u
+ (local.get $y)
+ (i64.const -1)
+ ))
;; x * -1
(drop (i32.mul
(local.get $x)
@@ -4786,6 +4805,134 @@
(i64.const -9223372036854775808)
))
+ ;; (unsigned)x >= 0 => i32(1)
+ (drop (i32.ge_u
+ (local.get $x)
+ (i32.const 0)
+ ))
+ (drop (i64.ge_u
+ (local.get $y)
+ (i64.const 0)
+ ))
+
+ ;; (unsigned)x < 0 => i32(0)
+ (drop (i32.lt_u
+ (local.get $x)
+ (i32.const 0)
+ ))
+ (drop (i64.lt_u
+ (local.get $y)
+ (i64.const 0)
+ ))
+
+ ;; (unsigned)x > 0 => x != 0
+ (drop (i32.gt_u
+ (local.get $x)
+ (i32.const 0)
+ ))
+ (drop (i64.gt_u
+ (local.get $y)
+ (i64.const 0)
+ ))
+
+ ;; (unsigned)x <= 0 => x == 0
+ (drop (i32.le_u
+ (local.get $x)
+ (i32.const 0)
+ ))
+ (drop (i64.le_u
+ (local.get $y)
+ (i64.const 0)
+ ))
+
+ ;; i32(x) <= 0x7fffffff => i32(1)
+ (drop (i32.le_s
+ (local.get $x)
+ (i32.const 0x7fffffff)
+ ))
+ ;; i64(x) <= 0x7fffffffffffffff => i32(1)
+ (drop (i64.le_s
+ (local.get $y)
+ (i64.const 0x7fffffffffffffff)
+ ))
+
+ ;; i32(x) >= 0x80000000 => i32(1)
+ (drop (i32.ge_s
+ (local.get $x)
+ (i32.const 0x80000000)
+ ))
+ ;; i64(x) >= 0x8000000000000000 => i32(1)
+ (drop (i64.ge_s
+ (local.get $y)
+ (i64.const 0x8000000000000000)
+ ))
+
+ ;; i32(x) < 0x80000000 => 0
+ (drop (i32.lt_s
+ (local.get $x)
+ (i32.const 0x80000000)
+ ))
+ ;; i64(x) < 0x8000000000000000 => 0
+ (drop (i64.lt_s
+ (local.get $y)
+ (i64.const 0x8000000000000000)
+ ))
+
+ ;; i32(x) > 0x7fffffff => 0
+ (drop (i32.gt_s
+ (local.get $x)
+ (i32.const 0x7fffffff)
+ ))
+ ;; i64(x) > 0x7fffffffffffffff => 0
+ (drop (i64.gt_s
+ (local.get $y)
+ (i64.const 0x7fffffffffffffff)
+ ))
+
+ ;; i32(x) < 0x7fffffff => x != 0x7fffffff
+ (drop (i32.lt_s
+ (local.get $x)
+ (i32.const 0x7fffffff)
+ ))
+ ;; i64(x) < 0x7fffffffffffffff => x != 0x7fffffffffffffff
+ (drop (i64.lt_s
+ (local.get $y)
+ (i64.const 0x7fffffffffffffff)
+ ))
+
+ ;; i32(x) > 0x80000000 => x != 0x80000000
+ (drop (i32.gt_s
+ (local.get $x)
+ (i32.const 0x80000000)
+ ))
+ ;; i64(x) > 0x8000000000000000 => x != 0x8000000000000000
+ (drop (i64.gt_s
+ (local.get $y)
+ (i64.const 0x8000000000000000)
+ ))
+
+ ;; i32(x) <= 0x80000000 => x == 0x80000000
+ (drop (i32.le_s
+ (local.get $x)
+ (i32.const 0x80000000)
+ ))
+ ;; i64(x) <= 0x8000000000000000 => x == 0x8000000000000000
+ (drop (i64.le_s
+ (local.get $y)
+ (i64.const 0x8000000000000000)
+ ))
+
+ ;; i32(x) >= 0x7fffffff => x == 0x7fffffff
+ (drop (i32.ge_s
+ (local.get $x)
+ (i32.const 0x7fffffff)
+ ))
+ ;; i64(x) >= 0x7fffffffffffffff => x == 0x7fffffffffffffff
+ (drop (i64.ge_s
+ (local.get $y)
+ (i64.const 0x7fffffffffffffff)
+ ))
+
;; -x * 1 => x * -1
(drop (f32.mul
(f32.neg