diff options
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 21 | ||||
-rw-r--r-- | test/passes/optimize-instructions_all-features.txt | 51 | ||||
-rw-r--r-- | test/passes/optimize-instructions_all-features.wast | 47 |
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) |