diff options
-rw-r--r-- | src/literal.h | 12 | ||||
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 33 | ||||
-rw-r--r-- | test/passes/optimize-instructions_all-features.txt | 44 | ||||
-rw-r--r-- | test/passes/optimize-instructions_all-features.wast | 55 |
4 files changed, 144 insertions, 0 deletions
diff --git a/src/literal.h b/src/literal.h index d94d1a6d0..625b3eb43 100644 --- a/src/literal.h +++ b/src/literal.h @@ -114,6 +114,18 @@ public: WASM_UNREACHABLE("unexpected type"); } } + bool isNegative() const { + switch (type.getBasic()) { + case Type::i32: + case Type::f32: + return i32 < 0; + case Type::i64: + case Type::f64: + return i64 < 0; + default: + WASM_UNREACHABLE("unexpected type"); + } + } bool isSignedMin() const { switch (type.getBasic()) { case Type::i32: diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 57ef42913..20cdeee19 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1734,6 +1734,39 @@ private: return curr->left; } { + // C1 - (x + C2) ==> (C1 - C2) - x + Const *c1, *c2; + Expression* x; + if (matches(curr, + binary(Sub, ival(&c1), binary(Add, any(&x), ival(&c2))))) { + left->value = c1->value.sub(c2->value); + curr->right = x; + return curr; + } + // C1 - (x - C2) ==> (C1 + C2) - x + if (matches(curr, + binary(Sub, ival(&c1), binary(Sub, any(&x), ival(&c2))))) { + left->value = c1->value.add(c2->value); + curr->right = x; + return curr; + } + // C1 - (C2 - x) ==> x + (C1 - C2) + if (matches(curr, + binary(Sub, ival(&c1), binary(Sub, ival(&c2), any(&x))))) { + left->value = c1->value.sub(c2->value); + if (left->value.isNegative()) { + // -C1 - (C2 - x) ==> x - (C1 - C2) + left->value = left->value.neg(); + curr->op = Abstract::getBinary(type, Sub); + } else { + curr->op = Abstract::getBinary(type, Add); + } + curr->right = x; + std::swap(curr->left, curr->right); + return curr; + } + } + { // fval(C) / -x ==> -C / x Expression* right; if (matches(curr, binary(DivS, fval(), unary(Neg, any(&right))))) { diff --git a/test/passes/optimize-instructions_all-features.txt b/test/passes/optimize-instructions_all-features.txt index 96346ed22..522bd6fe8 100644 --- a/test/passes/optimize-instructions_all-features.txt +++ b/test/passes/optimize-instructions_all-features.txt @@ -4391,6 +4391,50 @@ ) ) ) + (func $lhs-is-const (param $x i32) (param $y i64) + (drop + (i32.sub + (i32.const 1) + (local.get $x) + ) + ) + (drop + (i64.sub + (i64.const 1) + (local.get $y) + ) + ) + (drop + (i32.sub + (i32.const -2) + (local.get $x) + ) + ) + (drop + (i64.sub + (i64.const -2) + (local.get $y) + ) + ) + (drop + (i32.sub + (local.get $x) + (i32.const 1) + ) + ) + (drop + (i64.sub + (local.get $y) + (i64.const 1) + ) + ) + (drop + (i32.sub + (local.get $x) + (i32.const -2147483648) + ) + ) + ) (func $pre-combine-or (param $x i32) (param $y i32) (drop (i32.ge_s diff --git a/test/passes/optimize-instructions_all-features.wast b/test/passes/optimize-instructions_all-features.wast index cdb3c56f2..9b172e4bd 100644 --- a/test/passes/optimize-instructions_all-features.wast +++ b/test/passes/optimize-instructions_all-features.wast @@ -4842,6 +4842,61 @@ (local.get $x) )) ) + (func $lhs-is-const (param $x i32) (param $y i64) + ;; 0 - (x - 1) + (drop (i32.sub + (i32.const 0) + (i32.sub + (local.get $x) + (i32.const 1) + ) + )) + (drop (i64.sub + (i64.const 0) + (i64.sub + (local.get $y) + (i64.const 1) + ) + )) + ;; -1 - (x + 1) + (drop (i32.sub + (i32.const -1) + (i32.add + (local.get $x) + (i32.const 1) + ) + )) + (drop (i64.sub + (i64.const -1) + (i64.add + (local.get $y) + (i64.const 1) + ) + )) + ;; 1 - (2 - x) + (drop (i32.sub + (i32.const 1) + (i32.sub + (i32.const 2) + (local.get $x) + ) + )) + (drop (i64.sub + (i64.const 1) + (i64.sub + (i64.const 2) + (local.get $y) + ) + )) + ;; 0 - (0x80000000 - x) + (drop (i32.sub + (i32.const 0) + (i32.sub + (i32.const 0x80000000) + (local.get $x) + ) + )) + ) (func $pre-combine-or (param $x i32) (param $y i32) (drop (i32.or (i32.gt_s |