commit cd9f71bbfc1f5bf8fc7a63931c29cce9acabda97
parent 9fbe2c36662bf635d8e4d477ea75470a08a5c11f
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Wed, 26 Aug 2015 21:44:06 +0200
Add algebraic identities simplifications
These kind of expressions are common in array expressions, so this commit
simmplify a lot the intermediate file, and makes easier to validate the
regression tests.
Diffstat:
M | cc1/expr.c | | | 88 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- |
1 file changed, 85 insertions(+), 3 deletions(-)
diff --git a/cc1/expr.c b/cc1/expr.c
@@ -40,9 +40,19 @@ static Node *
simplify(unsigned char op, Type *tp, Node *lp, Node *rp)
{
Symbol *sym, *ls, *rs, aux;
+ int iszero, isone, noconst = 0;
- if (!lp->constant || !rp->constant)
+ if (!lp->constant && !rp->constant)
goto no_simplify;
+ if (!rp->constant) {
+ Node *np;
+ np = lp;
+ lp = rp;
+ rp = np;
+ }
+ if (!lp->constant)
+ noconst = 1;
+
ls = lp->sym, rs = rp->sym;
aux.type = tp;
@@ -62,71 +72,143 @@ simplify(unsigned char op, Type *tp, Node *lp, Node *rp)
}
switch (tp->op) {
+ case PTR:
case INT:
cmp_integers:
+ iszero = SYMICMP(rs, 0);
+ isone = SYMICMP(rs, 1);
switch (op) {
case OADD:
+ if (iszero)
+ return lp;
+ if (noconst)
+ goto no_simplify;
FOLDINT(&aux, ls, rs, +);
break;
case OSUB:
+ if (iszero)
+ return lp;
+ if (noconst)
+ goto no_simplify;
FOLDINT(&aux, ls, rs, -);
break;
case OMUL:
+ if (isone)
+ return lp;
+ if (iszero)
+ return constnode(zero);
+ if (noconst)
+ goto no_simplify;
FOLDINT(&aux, ls, rs, *);
break;
case ODIV:
- if (SYMICMP(&aux, 0))
+ if (isone)
+ return lp;
+ if (iszero)
goto division_by_0;
+ if (noconst)
+ goto no_simplify;
FOLDINT(&aux, ls, rs, /);
break;
case OMOD:
- if (SYMICMP(&aux, 0))
+ if (iszero)
goto division_by_0;
+ if (noconst)
+ goto no_simplify;
FOLDINT(&aux, ls, rs, %);
break;
case OSHL:
+ if (iszero)
+ return lp;
+ if (noconst)
+ goto no_simplify;
FOLDINT(&aux, ls, rs, <<);
break;
case OSHR:
+ if (iszero)
+ return lp;
+ if (noconst)
+ goto no_simplify;
FOLDINT(&aux, ls, rs, >>);
break;
case OBAND:
+ if (SYMICMP(rs, ~0))
+ return lp;
+ if (noconst)
+ goto no_simplify;
FOLDINT(&aux, ls, rs, &);
break;
case OBXOR:
+ if (iszero)
+ return lp;
+ if (noconst)
+ goto no_simplify;
FOLDINT(&aux, ls, rs, ^);
break;
case OBOR:
+ if (iszero)
+ return lp;
+ if (noconst)
+ goto no_simplify;
FOLDINT(&aux, ls, rs, |);
break;
case OAND:
+ if (!iszero)
+ return lp;
+ /* TODO: What happens with something like f(0) && 0? */
+ if (noconst)
+ goto no_simplify;
FOLDINT(&aux, ls, rs, &&);
break;
case OOR:
+ if (iszero)
+ return lp;
+ if (noconst)
+ goto no_simplify;
+ /* TODO: What happens with something like f(0) || 1? */
FOLDINT(&aux, ls, rs, ||);
break;
case OLT:
+ /* TODO: what happens with signess? */
+ if (noconst)
+ goto no_simplify;
aux.u.i = CMPISYM(&aux, ls, rs, <);
break;
case OGT:
+ /* TODO: what happens with signess? */
+ if (noconst)
+ goto no_simplify;
aux.u.i = CMPISYM(&aux, ls, rs, >);
break;
case OGE:
+ /* TODO: what happens with signess? */
+ if (noconst)
+ goto no_simplify;
aux.u.i = CMPISYM(&aux, ls, rs, >=);
break;
case OLE:
+ /* TODO: what happens with signess? */
+ if (noconst)
+ goto no_simplify;
aux.u.i = CMPISYM(&aux, ls, rs, <=);
break;
case OEQ:
+ /* TODO: what happens with signess? */
+ if (noconst)
+ goto no_simplify;
aux.u.i = CMPISYM(&aux, ls, rs, ==);
break;
case ONE:
+ /* TODO: what happens with signess? */
+ if (noconst)
+ goto no_simplify;
aux.u.i = CMPISYM(&aux, ls, rs, !=);
break;
}
break;
case FLOAT:
cmp_floats:
+ /* TODO: Add algebraic reductions for floats */
switch (op) {
case OADD:
aux.u.f = ls->u.f + rs->u.f;