summaryrefslogtreecommitdiff
path: root/src/passes/OptimizeInstructions.cpp
diff options
context:
space:
mode:
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);