ref: 04eaf8bf9813e47819a823534b8b53e481088f77
parent: 585dc6d025dabe3e95271084e27e6c833c8c3dbf
author: Roberto E. Vargas Caballero <[email protected]>
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);
}
}