summaryrefslogtreecommitdiff
path: root/src/passes/OptimizeInstructions.cpp
diff options
context:
space:
mode:
authorMax Graey <maxgraey@gmail.com>2021-09-10 02:27:21 +0300
committerGitHub <noreply@github.com>2021-09-09 16:27:21 -0700
commit0bc719505457acc1a92894b3995ce233fb0cdb20 (patch)
treea544c18f49c7497b6b1919e45692a93ab0f124ff /src/passes/OptimizeInstructions.cpp
parentd127f82d7dbe27a35e07a4f3a723fa7b6811c756 (diff)
downloadbinaryen-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.cpp50
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);