summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/OptimizeInstructions.cpp37
-rw-r--r--test/passes/O4_disable-bulk-memory.txt18
-rw-r--r--test/passes/optimize-instructions_all-features.txt52
-rw-r--r--test/passes/optimize-instructions_all-features.wast52
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