diff options
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); |