ref: 04eaf8bf9813e47819a823534b8b53e481088f77
parent: 585dc6d025dabe3e95271084e27e6c833c8c3dbf
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Wed Jul 22 10:30:27 EDT 2015
Simplify multiplicative expressions
--- a/cc1/code.c
+++ b/cc1/code.c
@@ -124,15 +124,20 @@
[OSWITCH] = emitswitch
};
-static Node *simple_sub(Node *), *simple_add(Node *);
+static Node *simple_add(Type *, Node *, Node *),
+ *simple_sub(Type *, Node *, Node *),
+ *simple_mul(Type *, Node *, Node *),
+ *simple_div(Type *, Node *, Node *),
+ *simple_mod(Type *, Node *, Node *);
-static Node *(*opsimp[])(Node *) = {+static Node *(*opsimp[])(Type *, Node *, Node *) = {[OADD] = simple_add,
- [OSUB] = simple_sub
-
+ [OSUB] = simple_sub,
+ [OMUL] = simple_mul,
+ [ODIV] = simple_div,
+ [OMOD] = simple_mod
};
-
void
freetree(Node *np)
{@@ -388,10 +393,8 @@
}
static Node *
-simple_add(Node *np)
+simple_mod(Type *tp, Node *lp, Node *rp)
{- Node *lp = np->left, *rp = np->right;
- Type *tp = np->type;
Symbol *sym, *ls = lp->sym, *rs = rp->sym;
switch (tp->op) {@@ -398,22 +401,94 @@
case INT:
sym = newsym(NS_IDEN);
sym->type = tp;
+ if (tp->sign) {+ if (rs->u.i == 0)
+ goto division_by_0;
+ sym->u.i = ls->u.i % rs->u.i;
+ } else {+ if (rs->u.u == 0)
+ goto division_by_0;
+ sym->u.u = ls->u.u % rs->u.u;
+ }
+ return constnode(sym);
+ default:
+ return NULL;
+ }
+
+division_by_0:
+ warn("division by 0");+ return NULL;
+}
+
+static Node *
+simple_div(Type *tp, Node *lp, Node *rp)
+{+ Symbol *sym, *ls = lp->sym, *rs = rp->sym;
+
+ switch (tp->op) {+ case INT:
+ sym = newsym(NS_IDEN);
+ sym->type = tp;
+ if (tp->sign) {+ if (rs->u.i == 0)
+ goto division_by_0;
+ sym->u.i = ls->u.i / rs->u.i;
+ } else {+ if (rs->u.u == 0)
+ goto division_by_0;
+ sym->u.u = ls->u.u / rs->u.u;
+ }
+ return constnode(sym);
+ default:
+ return NULL;
+ }
+
+division_by_0:
+ warn("division by 0");+ return NULL;
+}
+
+static Node *
+simple_mul(Type *tp, Node *lp, Node *rp)
+{+ Symbol *sym, *ls = lp->sym, *rs = rp->sym;
+
+ switch (tp->op) {+ case INT:
+ sym = newsym(NS_IDEN);
+ sym->type = tp;
if (tp->sign)
+ sym->u.i = ls->u.i * rs->u.i;
+ else
+ sym->u.u = ls->u.u * rs->u.u;
+ return constnode(sym);
+ default:
+ return NULL;
+ }
+}
+
+static Node *
+simple_add(Type *tp, Node *lp, Node *rp)
+{+ Symbol *sym, *ls = lp->sym, *rs = rp->sym;
+
+ switch (tp->op) {+ case INT:
+ sym = newsym(NS_IDEN);
+ sym->type = tp;
+ if (tp->sign)
sym->u.i = ls->u.i + rs->u.i;
else
sym->u.u = ls->u.u + rs->u.u;
- freetree(np);
return constnode(sym);
default:
- return np;
+ return NULL;
}
}
static Node *
-simple_sub(Node *np)
+simple_sub(Type *tp, Node *lp, Node *rp)
{- Node *lp = np->left, *rp = np->right;
- Type *tp = np->type;
Symbol *sym, *ls = lp->sym, *rs = rp->sym;
switch (tp->op) {@@ -424,10 +499,9 @@
sym->u.i = ls->u.i - rs->u.i;
else
sym->u.u = ls->u.u - rs->u.u;
- freetree(np);
return constnode(sym);
default:
- return np;
+ return NULL;
}
}
@@ -434,7 +508,14 @@
Node *
simplify(Node *np)
{- if (!np->left->constant || !np->right->constant)
+ Node *new, *lp = np->left, *rp = np->right;
+
+ if (!lp->constant || !rp->constant)
return np;
- return (*opsimp[np->op])(np);
+ new = (*opsimp[np->op])(np->type, lp, rp);
+ if (new) {+ freetree(np);
+ np = new;
+ }
+ return np;
}
--- a/cc1/expr.c
+++ b/cc1/expr.c
@@ -667,6 +667,7 @@
}
next();
np = (*fun)(op, np, cast());
+ np = simplify(np);
}
}
--
⑨