summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/OptimizeInstructions.cpp21
-rw-r--r--test/passes/optimize-instructions_all-features.txt51
-rw-r--r--test/passes/optimize-instructions_all-features.wast47
3 files changed, 119 insertions, 0 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index b4a5b9217..676e753ce 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -1299,6 +1299,27 @@ private:
}
}
}
+ if (type.isFloat()) {
+ auto value = right->value.getFloat();
+ if (value == 0.0) {
+ if (binary->op == Abstract::getBinary(type, Abstract::Sub)) {
+ if (std::signbit(value)) {
+ // x - (-0.0) ==> x + 0.0
+ binary->op = Abstract::getBinary(type, Abstract::Add);
+ right->value = right->value.neg();
+ return binary;
+ } else {
+ // x - 0.0 ==> x
+ return binary->left;
+ }
+ } else if (binary->op == Abstract::getBinary(type, Abstract::Add)) {
+ if (std::signbit(value)) {
+ // x + (-0.0) ==> x
+ return binary->left;
+ }
+ }
+ }
+ }
if (type.isInteger() || type.isFloat()) {
// note that this is correct even on floats with a NaN on the left,
// as a NaN would skip the computation and just return the NaN,
diff --git a/test/passes/optimize-instructions_all-features.txt b/test/passes/optimize-instructions_all-features.txt
index 31c1afbfc..33e137b9d 100644
--- a/test/passes/optimize-instructions_all-features.txt
+++ b/test/passes/optimize-instructions_all-features.txt
@@ -14,6 +14,7 @@
(type $i32_i32_i32_=>_none (func (param i32 i32 i32)))
(type $i32_i32_f64_f64_=>_none (func (param i32 i32 f64 f64)))
(type $i32_i64_f64_i32_=>_none (func (param i32 i64 f64 i32)))
+ (type $f32_f64_=>_none (func (param f32 f64)))
(type $none_=>_f64 (func (result f64)))
(memory $0 0)
(export "load-off-2" (func $load-off-2))
@@ -3541,6 +3542,56 @@
(i32.const 2)
)
)
+ (func $const-float-zero (param $fx f32) (param $fy f64)
+ (drop
+ (local.get $fx)
+ )
+ (drop
+ (local.get $fy)
+ )
+ (drop
+ (local.get $fx)
+ )
+ (drop
+ (local.get $fy)
+ )
+ (drop
+ (f32.add
+ (local.get $fx)
+ (f32.const 0)
+ )
+ )
+ (drop
+ (f64.add
+ (local.get $fy)
+ (f64.const 0)
+ )
+ )
+ (drop
+ (f32.sub
+ (f32.const 0)
+ (local.get $fx)
+ )
+ )
+ (drop
+ (f64.sub
+ (f64.const 0)
+ (local.get $fy)
+ )
+ )
+ (drop
+ (f32.add
+ (local.get $fx)
+ (f32.const 0)
+ )
+ )
+ (drop
+ (f64.add
+ (local.get $fy)
+ (f64.const 0)
+ )
+ )
+ )
(func $rhs-is-neg-one (param $x i32) (param $y i64) (param $fx f32) (param $fy f64)
(drop
(i32.sub
diff --git a/test/passes/optimize-instructions_all-features.wast b/test/passes/optimize-instructions_all-features.wast
index c2fa16e35..c67270a4f 100644
--- a/test/passes/optimize-instructions_all-features.wast
+++ b/test/passes/optimize-instructions_all-features.wast
@@ -4047,6 +4047,53 @@
(i32.const 2)
)
)
+ (func $const-float-zero (param $fx f32) (param $fy f64)
+ ;; x - 0.0 ==> x
+ (drop (f32.sub
+ (local.get $fx)
+ (f32.const 0)
+ ))
+ (drop (f64.sub
+ (local.get $fy)
+ (f64.const 0)
+ ))
+ ;; x + (-0.0) ==> x
+ (drop (f32.add
+ (local.get $fx)
+ (f32.const -0)
+ ))
+ (drop (f64.add
+ (local.get $fy)
+ (f64.const -0)
+ ))
+ ;; x - (-0.0) ==> x + 0.0
+ (drop (f32.sub
+ (local.get $fx)
+ (f32.const -0) ;; skip
+ ))
+ (drop (f64.sub
+ (local.get $fy)
+ (f64.const -0) ;; skip
+ ))
+ ;; 0.0 - x ==> 0.0 - x
+ (drop (f32.sub
+ (f32.const 0)
+ (local.get $fx) ;; skip
+ ))
+ (drop (f64.sub
+ (f64.const 0)
+ (local.get $fy) ;; skip
+ ))
+ ;; x + 0.0 ==> x + 0.0
+ (drop (f32.add
+ (local.get $fx) ;; skip
+ (f32.const 0)
+ ))
+ (drop (f64.add
+ (local.get $fy) ;; skip
+ (f64.const 0)
+ ))
+ )
(func $rhs-is-neg-one (param $x i32) (param $y i64) (param $fx f32) (param $fy f64)
(drop (i32.sub
(local.get $x)