diff options
author | Max Graey <maxgraey@gmail.com> | 2021-11-17 00:58:13 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-16 14:58:13 -0800 |
commit | 62c5209be6482836175a236f946b3a7261a47856 (patch) | |
tree | 0a479520c4479647506766b29424e7c9d418a92e /src | |
parent | 4b3d5be999baac642e7664da39c37c6012c11513 (diff) | |
download | binaryen-62c5209be6482836175a236f946b3a7261a47856.tar.gz binaryen-62c5209be6482836175a236f946b3a7261a47856.tar.bz2 binaryen-62c5209be6482836175a236f946b3a7261a47856.zip |
[OptimizeInstructions] Combine some relational ops joined Or/And (Part 1) (#4333)
(i32(x) == 0) & (i32(y) == 0) ==> i32(x | y) == 0
(i64(x) == 0) & (i64(y) == 0) ==> i64(x | y) == 0
Diffstat (limited to 'src')
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 42 |
1 files changed, 34 insertions, 8 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 7c450ac06..c0ba2dc02 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -772,16 +772,21 @@ struct OptimizeInstructions return replaceCurrent(ret); } } - // bitwise operations - // for and and or, we can potentially conditionalize if (curr->op == AndInt32 || curr->op == OrInt32) { - if (auto* ret = conditionalizeExpensiveOnBitwise(curr)) { - return replaceCurrent(ret); + if (curr->op == AndInt32) { + if (auto* ret = combineAnd(curr)) { + return replaceCurrent(ret); + } } - } - // for or, we can potentially combine - if (curr->op == OrInt32) { - if (auto* ret = combineOr(curr)) { + // for or, we can potentially combine + if (curr->op == OrInt32) { + if (auto* ret = combineOr(curr)) { + return replaceCurrent(ret); + } + } + // bitwise operations + // for and and or, we can potentially conditionalize + if (auto* ret = conditionalizeExpensiveOnBitwise(curr)) { return replaceCurrent(ret); } } @@ -2486,6 +2491,27 @@ private: } } + // We can combine `and` operations, e.g. + // (x == 0) & (y == 0) ==> (x | y) == 0 + Expression* combineAnd(Binary* curr) { + using namespace Abstract; + using namespace Match; + { + // (i32(x) == 0) & (i32(y) == 0) ==> i32(x | y) == 0 + // (i64(x) == 0) & (i64(y) == 0) ==> i64(x | y) == 0 + Expression *x, *y; + if (matches(curr, + binary(AndInt32, unary(EqZ, any(&x)), unary(EqZ, any(&y)))) && + x->type == y->type) { + auto* inner = curr->left->cast<Unary>(); + inner->value = Builder(*getModule()) + .makeBinary(Abstract::getBinary(x->type, Or), x, y); + return inner; + } + } + return nullptr; + } + // We can combine `or` operations, e.g. // (x > y) | (x == y) ==> x >= y Expression* combineOr(Binary* binary) { |