diff options
author | Max Graey <maxgraey@gmail.com> | 2021-09-10 02:27:21 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-09 16:27:21 -0700 |
commit | 0bc719505457acc1a92894b3995ce233fb0cdb20 (patch) | |
tree | a544c18f49c7497b6b1919e45692a93ab0f124ff /src/passes/OptimizeInstructions.cpp | |
parent | d127f82d7dbe27a35e07a4f3a723fa7b6811c756 (diff) | |
download | binaryen-0bc719505457acc1a92894b3995ce233fb0cdb20.tar.gz binaryen-0bc719505457acc1a92894b3995ce233fb0cdb20.tar.bz2 binaryen-0bc719505457acc1a92894b3995ce233fb0cdb20.zip |
[OptimizeInstructions] propagate sign for integer multiplication (#4098)
```ts
-x * -y => (x * y)
-x * y => -(x * y)
x * -y => -(x * y), if x != C && y != C
-x * C => x * -C, if C != C_pot || shrinkLevel != 0
-x * C => -(x * C), otherwise
```
We are skipping propagation when lhs and rhs are constants because this should handled by constant folding. Also skip cases like `-x * 4 -> x * -4` for `shrinkLevel != 0`, as this will be further converted to `-(x << 2)`.
Diffstat (limited to 'src/passes/OptimizeInstructions.cpp')
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 423148510..cbf5d74d4 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -416,6 +416,38 @@ struct OptimizeInstructions } } { + // -x * -y ==> x * y + // where x, y are integers + Binary* bin; + Expression *x, *y; + if (matches(curr, + binary(&bin, + Mul, + binary(Sub, ival(0), any(&x)), + binary(Sub, ival(0), any(&y))))) { + bin->left = x; + bin->right = y; + return replaceCurrent(curr); + } + } + { + // -x * y ==> -(x * y) + // x * -y ==> -(x * y) + // where x, y are integers + Expression *x, *y; + if ((matches(curr, + binary(Mul, binary(Sub, ival(0), any(&x)), any(&y))) || + matches(curr, + binary(Mul, any(&x), binary(Sub, ival(0), any(&y))))) && + !x->is<Const>() && !y->is<Const>()) { + Builder builder(*getModule()); + return replaceCurrent( + builder.makeBinary(Abstract::getBinary(curr->type, Sub), + builder.makeConst(Literal::makeZero(curr->type)), + builder.makeBinary(curr->op, x, y))); + } + } + { if (getModule()->features.hasSignExt()) { Const *c1, *c2; Expression* x; @@ -2216,6 +2248,24 @@ private: matches(curr, binary(And, pure(&left), ival(0)))) { return right; } + // -x * C ==> x * -C, if shrinkLevel != 0 or C != C_pot + // -x * C ==> -(x * C), otherwise + // where x, C are integers + Binary* inner; + if (matches( + curr, + binary(Mul, binary(&inner, Sub, ival(0), any(&left)), ival()))) { + if (getPassOptions().shrinkLevel != 0 || + !Bits::isPowerOf2(right->value.getInteger())) { + right->value = right->value.neg(); + curr->left = left; + return curr; + } else { + curr->left = left; + Const* zero = inner->left->cast<Const>(); + return builder.makeBinary(inner->op, zero, curr); + } + } // x == 0 ==> eqz x if (matches(curr, binary(Eq, any(&left), ival(0)))) { return builder.makeUnary(Abstract::getUnary(type, EqZ), left); |