diff options
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 15 | ||||
-rw-r--r-- | test/passes/optimize-instructions_all-features.txt | 32 | ||||
-rw-r--r-- | test/passes/optimize-instructions_all-features.wast | 39 |
3 files changed, 84 insertions, 2 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index d019a983f..57ef42913 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -764,7 +764,7 @@ struct OptimizeInstructions } // abs(0 - x) ==> abs(x), // only for fast math - if (getPassOptions().fastMath && + if (fastMath && binary->op == Abstract::getBinary(binary->type, Abstract::Sub)) { if (auto* c = binary->left->dynCast<Const>()) { if (c->value.isZero()) { @@ -1716,12 +1716,23 @@ private: using namespace Match; using namespace Abstract; + auto type = curr->left->type; auto* left = curr->left->cast<Const>(); - // 0 <<>> y ==> 0 + // 0 <<>> x ==> 0 if (Abstract::hasAnyShift(curr->op) && left->value.isZero() && !effects(curr->right).hasSideEffects()) { return curr->left; } + // (signed)-1 >> x ==> -1 + // rotl(-1, x) ==> -1 + // rotr(-1, x) ==> -1 + if ((curr->op == Abstract::getBinary(type, ShrS) || + curr->op == Abstract::getBinary(type, RotL) || + curr->op == Abstract::getBinary(type, RotR)) && + left->value.getInteger() == -1LL && + !effects(curr->right).hasSideEffects()) { + return curr->left; + } { // fval(C) / -x ==> -C / x Expression* right; diff --git a/test/passes/optimize-instructions_all-features.txt b/test/passes/optimize-instructions_all-features.txt index 15f0eea86..96346ed22 100644 --- a/test/passes/optimize-instructions_all-features.txt +++ b/test/passes/optimize-instructions_all-features.txt @@ -4359,6 +4359,38 @@ ) ) ) + (func $lhs-is-neg-one (param $x i32) (param $y i64) + (drop + (i32.const -1) + ) + (drop + (i64.const -1) + ) + (drop + (i32.const -1) + ) + (drop + (i64.const -1) + ) + (drop + (i32.const -1) + ) + (drop + (i64.const -1) + ) + (drop + (i32.shr_s + (i32.const -1) + (call $ne0) + ) + ) + (drop + (i32.shr_u + (i32.const -1) + (local.get $x) + ) + ) + ) (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 02f55b20c..cdb3c56f2 100644 --- a/test/passes/optimize-instructions_all-features.wast +++ b/test/passes/optimize-instructions_all-features.wast @@ -4803,6 +4803,45 @@ ) )) ) + (func $lhs-is-neg-one (param $x i32) (param $y i64) + ;; -1 >> x ==> -1 + (drop (i32.shr_s + (i32.const -1) + (local.get $x) + )) + (drop (i64.shr_s + (i64.const -1) + (local.get $y) + )) + ;; rotl(-1, x) ==> -1 + (drop (i32.rotl + (i32.const -1) + (local.get $x) + )) + (drop (i64.rotl + (i64.const -1) + (local.get $y) + )) + ;; rotr(-1, x) ==> -1 + (drop (i32.rotr + (i32.const -1) + (local.get $x) + )) + (drop (i64.rotr + (i64.const -1) + (local.get $y) + )) + ;; skip + (drop (i32.shr_s + (i32.const -1) + (call $ne0) ;; side effect + )) + ;; skip + (drop (i32.shr_u + (i32.const -1) + (local.get $x) + )) + ) (func $pre-combine-or (param $x i32) (param $y i32) (drop (i32.or (i32.gt_s |