diff options
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 37 | ||||
-rw-r--r-- | test/passes/O4_disable-bulk-memory.txt | 18 | ||||
-rw-r--r-- | test/passes/optimize-instructions_all-features.txt | 52 | ||||
-rw-r--r-- | test/passes/optimize-instructions_all-features.wast | 52 |
4 files changed, 128 insertions, 31 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 89315ab60..c7219dd3c 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1684,6 +1684,14 @@ private: return curr->left; } } + // -x * fval(C) ==> x * -C + // -x / fval(C) ==> x / -C + if (matches(curr, binary(Mul, unary(Neg, any(&left)), fval())) || + matches(curr, binary(DivS, unary(Neg, any(&left)), fval()))) { + right->value = right->value.neg(); + curr->left = left; + return curr; + } // x * -1.0 ==> -x if (fastMath && matches(curr, binary(Mul, any(), fval(-1.0)))) { return builder.makeUnary(Abstract::getUnary(type, Neg), left); @@ -1702,18 +1710,23 @@ private: // is a constant. since we canonicalize constants to the right for symmetrical // operations, we only need to handle asymmetrical ones here // TODO: templatize on type? - Expression* optimizeWithConstantOnLeft(Binary* binary) { - auto type = binary->left->type; - auto* left = binary->left->cast<Const>(); - if (type.isInteger()) { - // operations on zero - if (left->value == Literal::makeFromInt32(0, type)) { - if ((binary->op == Abstract::getBinary(type, Abstract::Shl) || - binary->op == Abstract::getBinary(type, Abstract::ShrU) || - binary->op == Abstract::getBinary(type, Abstract::ShrS)) && - !effects(binary->right).hasSideEffects()) { - return binary->left; - } + Expression* optimizeWithConstantOnLeft(Binary* curr) { + using namespace Match; + using namespace Abstract; + + auto* left = curr->left->cast<Const>(); + // 0 <<>> y ==> 0 + if (Abstract::hasAnyShift(curr->op) && left->value.isZero() && + !effects(curr->right).hasSideEffects()) { + return curr->left; + } + { + // fval(C) / -x ==> -C / x + Expression* right; + if (matches(curr, binary(DivS, fval(), unary(Neg, any(&right))))) { + left->value = left->value.neg(); + curr->right = right; + return curr; } } return nullptr; diff --git a/test/passes/O4_disable-bulk-memory.txt b/test/passes/O4_disable-bulk-memory.txt index 730c2ac0f..19d07a81e 100644 --- a/test/passes/O4_disable-bulk-memory.txt +++ b/test/passes/O4_disable-bulk-memory.txt @@ -216,28 +216,22 @@ ) ) (f64.div - (f64.neg - (local.get $4) - ) - (f64.const 39.47841760435743) + (local.get $4) + (f64.const -39.47841760435743) ) ) (f64.store offset=32 (local.get $1) (f64.div - (f64.neg - (local.get $5) - ) - (f64.const 39.47841760435743) + (local.get $5) + (f64.const -39.47841760435743) ) ) (f64.store offset=40 (local.get $1) (f64.div - (f64.neg - (local.get $6) - ) - (f64.const 39.47841760435743) + (local.get $6) + (f64.const -39.47841760435743) ) ) (i32.store diff --git a/test/passes/optimize-instructions_all-features.txt b/test/passes/optimize-instructions_all-features.txt index 15a38f267..3e792cd9a 100644 --- a/test/passes/optimize-instructions_all-features.txt +++ b/test/passes/optimize-instructions_all-features.txt @@ -7,10 +7,10 @@ (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $i32_=>_none (func (param i32))) (type $i32_i32_i64_i64_=>_none (func (param i32 i32 i64 i64))) + (type $i32_i64_f32_f64_=>_none (func (param i32 i64 f32 f64))) (type $none_=>_i64 (func (result i64))) (type $i64_=>_i64 (func (param i64) (result i64))) (type $i32_i64_f32_=>_none (func (param i32 i64 f32))) - (type $i32_i64_f32_f64_=>_none (func (param i32 i64 f32 f64))) (type $none_=>_anyref (func (result anyref))) (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) (type $i32_i32_i32_f64_=>_none (func (param i32 i32 i32 f64))) @@ -4248,7 +4248,7 @@ ) ) ) - (func $rhs-is-const (param $x i32) (param $y i64) + (func $rhs-is-const (param $x i32) (param $y i64) (param $fx f32) (param $fy f64) (drop (i32.eq (local.get $x) @@ -4307,6 +4307,48 @@ (i64.const 63) ) ) + (drop + (f32.mul + (local.get $fx) + (f32.const -1) + ) + ) + (drop + (f64.mul + (local.get $fy) + (f64.const 2.1) + ) + ) + (drop + (f64.mul + (local.get $fy) + (f64.const -2) + ) + ) + (drop + (f32.div + (local.get $fx) + (f32.const -inf) + ) + ) + (drop + (f64.div + (local.get $fy) + (f64.const 0) + ) + ) + (drop + (f64.div + (local.get $fy) + (f64.const -nan:0x8000000000000) + ) + ) + (drop + (f64.div + (f64.const -5) + (local.get $fy) + ) + ) ) (func $pre-combine-or (param $x i32) (param $y i32) (drop @@ -4619,10 +4661,8 @@ ) (drop (f64.mul - (f64.neg - (local.get $0) - ) - (f64.const 2) + (local.get $0) + (f64.const -2) ) ) ) diff --git a/test/passes/optimize-instructions_all-features.wast b/test/passes/optimize-instructions_all-features.wast index c9f071727..cdd203fa4 100644 --- a/test/passes/optimize-instructions_all-features.wast +++ b/test/passes/optimize-instructions_all-features.wast @@ -4688,7 +4688,7 @@ (i64.const -1) )) ) - (func $rhs-is-const (param $x i32) (param $y i64) + (func $rhs-is-const (param $x i32) (param $y i64) (param $fx f32) (param $fy f64) ;; signed divs ;; i32(x) / -2147483648 -> x == -2147483648 (drop (i32.div_s @@ -4737,6 +4737,56 @@ (local.get $y) (i64.const -9223372036854775808) )) + + ;; -x * 1 => x * -1 + (drop (f32.mul + (f32.neg + (local.get $fx) + ) + (f32.const 1) + )) + ;; -x * -2.1 => x * 2.1 + (drop (f64.mul + (f64.neg + (local.get $fy) + ) + (f64.const -2.1) + )) + ;; 2 * -x => x * -2 + (drop (f64.mul + (f64.const 2) + (f64.neg + (local.get $fy) + ) + )) + ;; -x / inf => x / -inf + (drop (f32.div + (f32.neg + (local.get $fx) + ) + (f32.const inf) + )) + ;; -x / -0.0 => x / 0.0 + (drop (f64.div + (f64.neg + (local.get $fy) + ) + (f64.const -0.0) + )) + ;; -x / nan => x / -nan + (drop (f64.div + (f64.neg + (local.get $fy) + ) + (f64.const nan) + )) + ;; 5.0 / -x => -5 / x + (drop (f64.div + (f64.const 5) + (f64.neg + (local.get $fy) + ) + )) ) (func $pre-combine-or (param $x i32) (param $y i32) (drop (i32.or |