scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

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:
Mcc1/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;