diff options
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 96 | ||||
-rw-r--r-- | test/passes/O4_disable-bulk-memory.txt | 15 | ||||
-rw-r--r-- | test/passes/inlining-optimizing_optimize-level=3.txt | 7 | ||||
-rw-r--r-- | test/passes/optimize-instructions_all-features.txt | 138 | ||||
-rw-r--r-- | test/passes/optimize-instructions_all-features.wast | 147 |
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 |