[hackers] [scc] [cc1] Rewrite fold.c || Roberto E. Vargas Caballero

From: <git_AT_suckless.org>
Date: Sat, 4 Feb 2017 21:58:35 +0100 (CET)

commit a794c4b02bb81b0b563d579a46bc25cf42582352
Author: Roberto E. Vargas Caballero <k0ga_AT_shike2.com>
AuthorDate: Sat Feb 4 21:42:12 2017 +0100
Commit: Roberto E. Vargas Caballero <k0ga_AT_shike2.com>
CommitDate: Sat Feb 4 21:42:12 2017 +0100

    [cc1] Rewrite fold.c
    
    The big problem of simplify() was being no recursive, and it meant
    that a lot of oportunities to fold were lost.

diff --git a/cc1/cc1.h b/cc1/cc1.h
index c118641..3052c10 100644
--- a/cc1/cc1.h
+++ b/cc1/cc1.h
_AT_@ -420,7 +420,7 @@ extern void freetree(Node *np);
 #define BTYPE(np) ((np)->type->op)
 
 /* fold.c */
-extern Node *simplify(int op, Type *tp, Node *lp, Node *rp);
+extern Node *simplify(Node *np);
 extern TUINT ones(int nbytes);
 
 /* expr.c */
diff --git a/cc1/expr.c b/cc1/expr.c
index a009a48..8442619 100644
--- a/cc1/expr.c
+++ b/cc1/expr.c
_AT_@ -11,7 +11,7 @@ static char sccsid[] = "@(#) ./cc1/expr.c";
 
 #define XCHG(lp, rp, np) (np = lp, lp = rp, rp = np)
 
-Node *expr(void);
+static Node *xexpr(void);
 
 int
 cmpnode(Node *np, TUINT val)
_AT_@ -215,7 +215,7 @@ integerop(int op, Node *lp, Node *rp)
         if (!(lp->type->prop & TINTEGER) || !(rp->type->prop & TINTEGER))
                 error("operator requires integer operands");
         arithconv(&lp, &rp);
- return simplify(op, lp->type, lp, rp);
+ return node(op, lp->type, lp, rp);
 }
 
 static Node *
_AT_@ -224,9 +224,7 @@ integeruop(int op, Node *np)
         if (!(np->type->prop & TINTEGER))
                 error("unary operator requires integer operand");
         np = promote(np);
- if (op == OCPL && np->op == OCPL)
- return np->left;
- return simplify(op, np->type, np, NULL);
+ return node(op, np->type, np, NULL);
 }
 
 static Node *
_AT_@ -235,68 +233,7 @@ numericaluop(int op, Node *np)
         if (!(np->type->prop & TARITH))
                 error("unary operator requires numerical operand");
         np = promote(np);
- if (op == OSNEG && np->op == OSNEG)
- return np->left;
- if (op == OADD)
- return np;
- return simplify(op, np->type, np, NULL);
-}
-
-/* TODO: check validity of types */
-static Node *
-castcode(Node *np, Type *newtp)
-{
- TUINT negmask, mask, u;
- Type *oldtp = np->type;
- Symbol aux, *sym, *osym = np->sym;
-
- if (!(np->flags & NCONST))
- goto noconstant;
-
- switch (newtp->op) {
- case PTR:
- case INT:
- case ENUM:
- switch (oldtp->op) {
- case PTR:
- case INT:
- case ENUM:
- u = (oldtp->prop & TSIGNED) ? osym->u.i : osym->u.u;
- break;
- case FLOAT:
- oldtp = newtp;
- u = osym->u.f;
- break;
- default:
- goto noconstant;
- }
- mask = ones(newtp->size);
- if (newtp->prop & TSIGNED) {
- negmask = ~mask;
- if (u & (negmask >> 1) & mask)
- u |= negmask;
- aux.u.i = u;
- } else {
- aux.u.u = u & mask;
- }
- break;
- case FLOAT:
- /* FIXME: The cast can be from another float type */
- aux.u.f = (oldtp->prop & TSIGNED) ? osym->u.i : osym->u.u;
- break;
- default:
- goto noconstant;
- }
-
- sym = newsym(NS_IDEN, NULL);
- np->type = sym->type = newtp;
- np->sym = sym;
- sym->u = aux.u;
-
- return np;
-
-noconstant:
- return node(OCAST, newtp, np, NULL);
+ return node(op, np->type, np, NULL);
 }
 
 Node *
_AT_@ -345,7 +282,7 @@ convert(Node *np, Type *newtp, char iscast)
         default:
                 return NULL;
         }
- return castcode(np, newtp);
+ return node(OCAST, newtp, np, NULL);
 }
 
 static Node *
_AT_@ -375,10 +312,10 @@ parithmetic(int op, Node *lp, Node *rp)
                 goto incorrect;
 
         rp = convert(promote(rp), sizettype, 0);
- rp = simplify(OMUL, sizettype, rp, size);
+ rp = node(OMUL, sizettype, rp, size);
         rp = convert(rp, tp, 1);
 
- return simplify(op, tp, lp, rp);
+ return node(op, tp, lp, rp);
 
 incomplete:
         errorp("invalid use of undefined type");
_AT_@ -396,7 +333,7 @@ arithmetic(int op, Node *lp, Node *rp)
 
         if ((ltp->prop & TARITH) && (rtp->prop & TARITH)) {
                 arithconv(&lp, &rp);
- return simplify(op, lp->type, lp, rp);
+ return node(op, lp->type, lp, rp);
         } else if ((ltp->op == PTR || rtp->op == PTR)) {
                 switch (op) {
                 case OADD:
_AT_@ -432,7 +369,7 @@ pcompare(int op, Node *lp, Node *rp)
         }
         if (err)
                 errorp("incompatible types in comparison");
- return simplify(op, inttype, lp, rp);
+ return node(op, inttype, lp, rp);
 }
 
 static Node *
_AT_@ -447,7 +384,7 @@ compare(int op, Node *lp, Node *rp)
                 return pcompare(op, rp, lp);
         } else if ((ltp->prop & TARITH) && (rtp->prop & TARITH)) {
                 arithconv(&lp, &rp);
- return simplify(op, inttype, lp, rp);
+ return node(op, inttype, lp, rp);
         } else {
                 errorp("incompatible types in comparison");
                 freetree(lp);
_AT_@ -532,7 +469,7 @@ logic(int op, Node *lp, Node *rp)
 {
         lp = exp2cond(lp, 0);
         rp = exp2cond(rp, 0);
- return simplify(op, inttype, lp, rp);
+ return node(op, inttype, lp, rp);
 }
 
 static Node *
_AT_@ -657,13 +594,7 @@ address(int op, Node *np)
 dont_check_lvalue:
         if (np->sym && (np->sym->flags & SREGISTER))
                 errorp("address of register variable '%s' requested", yytext);
- if (np->op == OPTR) {
- Node *new = np->left;
- free(np);
- return new;
- }
         new = node(op, mktype(np->type, PTR, 0, NULL), np, NULL);
-
         if (np->sym && np->sym->flags & (SGLOBAL|SLOCAL|SPRIVATE))
                 new->flags |= NCONST;
         return new;
_AT_@ -674,7 +605,6 @@ negation(int op, Node *np)
 {
         if (!(np->type->prop & TARITH) && np->type->op != PTR) {
                 errorp("invalid argument of unary '!'");
- freetree(np);
                 return constnode(zero);
         }
         return exp2cond(np, 1);
_AT_@ -864,7 +794,7 @@ postfix(Node *lp)
                         switch (yytoken) {
                         case '[':
                                 next();
- rp = expr();
+ rp = xexpr();
                                 expect(']');
                                 lp = array(lp, rp);
                                 break;
_AT_@ -987,7 +917,7 @@ cast(int needdecay)
                 if (nested == NR_SUBEXPR)
                         error("too many expressions nested by parentheses");
                 ++nested;
- rp = expr();
+ rp = xexpr();
                 --nested;
                 expect(')');
                 rp = postfix(rp);
_AT_@ -1155,11 +1085,11 @@ ternary(void)
                 Node *ifyes, *ifno, *np;
 
                 cond = exp2cond(cond, 0);
- ifyes = expr();
+ ifyes = xexpr();
                 expect(':');
                 ifno = ternary();
                 np = chkternary(ifyes, ifno);
- cond = simplify(OASK, np->type, cond, np);
+ cond = node(OASK, np->type, cond, np);
         }
         return cond;
 }
_AT_@ -1193,31 +1123,38 @@ assign(void)
         }
 }
 
+static Node *
+xexpr(void)
+{
+ Node *lp, *rp;
+
+ lp = assign();
+ while (accept(',')) {
+ rp = assign();
+ lp = node(OCOMMA, rp->type, lp, rp);
+ }
+ return lp;
+}
+
 Node *
 constexpr(void)
 {
         Node *np;
 
         np = ternary();
- if (!np || !(np->flags & NCONST) || np->type->op != INT) {
- freetree(np);
- return NULL;
+ if (np && np->type->op == INT) {
+ np = simplify(convert(np, inttype, 0));
+ if (np->flags & NCONST)
+ return np;
         }
- return convert(np, inttype, 0);
+ freetree(np);
+ return NULL;
 }
 
 Node *
 expr(void)
 {
- Node *lp, *rp;
-
- lp = assign();
- while (accept(',')) {
- rp = assign();
- lp = node(OCOMMA, rp->type, lp, rp);
- }
-
- return lp;
+ return simplify(xexpr());
 }
 
 Node *
_AT_@ -1225,8 +1162,8 @@ condexpr(void)
 {
         Node *np;
 
- np = exp2cond(expr(), 0);
+ np = exp2cond(xexpr(), 0);
         if (np->flags & NCONST)
                 warn("conditional expression is constant");
- return np;
+ return simplify(np);
 }
diff --git a/cc1/fold.c b/cc1/fold.c
index d3c0f35..90a3445 100644
--- a/cc1/fold.c
+++ b/cc1/fold.c
_AT_@ -195,7 +195,7 @@ foldint(int op, Symbol *res, TINT l, TINT r)
         }
         res->u.i = i;
 
- DBG("FOLD %lld %d %lld = %lld", l, op, r, i);
+ DBG("FOLD i l=%lld %d r=%lld = %lld", l, op, r, i);
         return 1;
 }
 
_AT_@ -231,13 +231,13 @@ folduint(int op, Symbol *res, TUINT l, TUINT r)
         }
         res->u.u = u & ones(res->type->size);
 
- DBG("FOLD %llu %d %llu = %llu", l, op, r, i);
+ DBG("FOLD ui l=%llu %d r=%llu = %llu", l, op, r, i);
         return 1;
 
 sign:
         res->u.i = i;
 
- DBG("FOLD %llu %d %llu = %llu", l, op, r, i);
+ DBG("FOLD sui %llu %d %llu = %llu", l, op, r, i);
         return 1;
 }
 
_AT_@ -273,10 +273,14 @@ foldfloat(int op, Symbol *res, TFLOAT l, TFLOAT r)
         default: return 0;
         }
         res->u.f = f;
+
+ DBG("FOLD f l=%lf %d r=%lf = %lf", l, op, r, f);
         return 1;
 
 comparison:
         res->u.i = i;
+
+ DBG("FOLD if l=%lf %d r=%lf = %lld", l, op, r, i);
         return 1;
 }
 
_AT_@ -307,19 +311,122 @@ foldconst(int type, int op, Type *tp, Symbol *ls, Symbol *rs)
                 break;
         }
         sym = newsym(NS_IDEN, NULL);
+ sym->flags |= SCONSTANT;
         sym->type = tp;
         sym->u = aux.u;
         return constnode(sym);
 }
 
 static Node *
-fold(int op, Type *tp, Node *lp, Node *rp)
+foldcast(Node *np, Node *l)
+{
+ TUINT negmask, mask, u;
+ Type *newtp = np->type, *oldtp = l->type;
+ Symbol aux, *sym, *osym = l->sym;
+
+ if (!(l->flags & NCONST))
+ return np;
+
+ switch (newtp->op) {
+ case PTR:
+ case INT:
+ case ENUM:
+ switch (oldtp->op) {
+ case PTR:
+ case INT:
+ case ENUM:
+ u = (oldtp->prop & TSIGNED) ? osym->u.i : osym->u.u;
+ break;
+ case FLOAT:
+ oldtp = newtp;
+ u = osym->u.f;
+ break;
+ default:
+ return np;
+ }
+ mask = ones(newtp->size);
+ if (newtp->prop & TSIGNED) {
+ negmask = ~mask;
+ if (u & (negmask >> 1) & mask)
+ u |= negmask;
+ aux.u.i = u;
+ } else {
+ aux.u.u = u & mask;
+ }
+ break;
+ case FLOAT:
+ /* FIXME: The cast can be from another float type */
+ aux.u.f = (oldtp->prop & TSIGNED) ? osym->u.i : osym->u.u;
+ break;
+ default:
+ return np;
+ }
+ DBG("FOLD cast %c->%c", oldtp->letter, newtp->letter);
+ freetree(np);
+ sym = newsym(NS_IDEN, NULL);
+ sym->flags |= SCONSTANT;
+ sym->type = newtp;
+ sym->u = aux.u;
+ return constnode(sym);
+}
+
+static Node *
+foldunary(Node *np, Node *l)
+{
+ int op = l->op;
+ Node *aux;
+
+ switch (np->op) {
+ case OADD:
+ DBG("FOLD unary delete %d", np->op);
+ np->left = NULL;
+ freetree(np);
+ return l;
+ case OCAST:
+ if (op != OCAST)
+ return foldcast(np, l);
+ DBG("FOLD unary collapse %d", np->op);
+ np->left = l->left;
+ l->left = NULL;
+ freetree(l);
+ return np;
+ case OSNEG:
+ case OCPL:
+ if (op != np->op)
+ return NULL;
+ break;
+ case OPTR:
+ if (op != OADDR)
+ return NULL;
+ break;
+ case OADDR:
+ if (op != OPTR)
+ return NULL;
+ break;
+ default:
+ return NULL;
+ }
+ DBG("FOLD unary cancel %d", np->op);
+ aux = l->left;
+ l->left = NULL;
+ freetree(np);
+ return aux;
+}
+
+static Node *
+fold(Node *np)
 {
         Symbol *rs, *ls;
- Node *np;
         Type *optype;
         int type;
+ int op = np->op;
+ Node *p, *lp = np->left, *rp = np->right;
+ Type *tp = np->type;
 
+ if (!lp && !rp)
+ return np;
+ if (!rp && (p = foldunary(np, lp)) != NULL)
+ return p;
         if ((op == ODIV || op == OMOD) && cmpnode(rp, 0)) {
                 warn("division by 0");
                 return NULL;
_AT_@ -331,13 +438,18 @@ fold(int op, Type *tp, Node *lp, Node *rp)
          * (when we don't know the physical address so
          * we cannot fold it)
          */
- if (!(lp->flags & NCONST) || !lp->sym ||
- rp && (!(rp->flags & NCONST) || !rp->sym)) {
- return NULL;
+ if (!rp) {
+ rs = NULL;
+ } else {
+ if (!(rp->flags & NCONST) || !rp->sym)
+ return NULL;
+ rs = rp->sym;
         }
+
+ if (!(lp->flags & NCONST) || !lp->sym)
+ return NULL;
         optype = lp->type;
         ls = lp->sym;
- rs = (rp) ? rp->sym : NULL;
 
         switch (type = optype->op) {
         case ENUM:
_AT_@ -346,31 +458,30 @@ fold(int op, Type *tp, Node *lp, Node *rp)
                         type = UNSIGNED;
         case PTR:
         case FLOAT:
- if ((np = foldconst(type, op, tp, ls, rs)) != NULL)
- break;
+ if ((p = foldconst(type, op, tp, ls, rs)) == NULL)
+ return NULL;
+ freetree(np);
+ return p;
         default:
                 return NULL;
         }
-
- freetree(lp);
- freetree(rp);
- return np;
 }
 
 static void
-commutative(int *op, Node **lp, Node **rp)
+commutative(Node *np, Node *l, Node *r)
 {
- Node *l = *lp, *r = *rp, *aux;
+ int op = np->op;
 
- if (r == NULL || r->flags & NCONST || !(l->flags & NCONST))
+ if (r == NULL || r->flags&NCONST || !(l->flags&NCONST))
                 return;
 
- switch (*op) {
+ switch (op) {
         case OLT:
         case OGT:
         case OGE:
         case OLE:
- *op = negop(*op);
+ DBG("FOLD neg commutative %d", np->op);
+ np->op = negop(op);
         case OEQ:
         case ONE:
         case OADD:
_AT_@ -378,20 +489,19 @@ commutative(int *op, Node **lp, Node **rp)
         case OBAND:
         case OBXOR:
         case OBOR:
- aux = l;
- l = r;
- r = aux;
+ DBG("FOLD commutative %d", np->op);
+ np->left = r;
+ np->right = l;
                 break;
         }
- *rp = r;
- *lp = l;
 }
 
 static Node *
-identity(int *op, Node *lp, Node *rp)
+identity(Node *np)
 {
         int iszeror, isoner, istruer;
         int iszerol, isonel, istruel;
+ Node *lp = np->left, *rp = np->right;
 
         if (!rp)
                 return NULL;
_AT_@ -403,7 +513,7 @@ identity(int *op, Node *lp, Node *rp)
         isonel = cmpnode(lp, 1),
         istruel = !iszerol && lp->flags & NCONST;
 
- switch (*op) {
+ switch (np->op) {
         case OOR:
                 /*
                  * 1 || i => 1 (free right)
_AT_@ -485,28 +595,28 @@ identity(int *op, Node *lp, Node *rp)
         }
 
 free_right:
- DBG("FOLD identity %d", op);
- freetree(rp);
+ DBG("FOLD identity %d", np->op);
+ np->left = NULL;
+ freetree(np);
         return lp;
 
 free_left:
- DBG("FOLD identity %d", op);
- freetree(lp);
+ DBG("FOLD identity %d", np->op);
+ np->right = NULL;
+ freetree(np);
         return rp;
 
 change_to_comma:
- DBG("FOLD identity %d", op);
- *op = OCOMMA;
- return NULL;
+ DBG("FOLD identity %d", np->op);
+ np->op = OCOMMA;
+ return np;
 }
 
 static Node *
-foldternary(int op, Type *tp, Node *cond, Node *body)
+foldternary(Node *np, Node *cond, Node *body)
 {
- Node *np;
-
         if (!(cond->flags & NCONST))
- return node(op, tp, cond, body);
+ return np;
         if (cmpnode(cond, 0)) {
                 np = body->right;
                 freetree(body->left);
_AT_@ -514,86 +624,43 @@ foldternary(int op, Type *tp, Node *cond, Node *body)
                 np = body->left;
                 freetree(body->right);
         }
+
         DBG("FOLD ternary");
+ body->left = NULL;
+ body->right = NULL;
         freetree(cond);
         free(body);
         return np;
 }
 
-/*
- * TODO: transform simplify in a recursivity
- * function, because we are losing optimization
- * chances
- */
-Node *
-simplify(int op, Type *tp, Node *lp, Node *rp)
-{
- Node *np;
-
- if (op == OASK)
- return foldternary(op, tp, lp, rp);
- commutative(&op, &lp, &rp);
- if ((np = fold(op, tp, lp, rp)) != NULL)
- return np;
- if ((np = identity(&op, lp, rp)) != NULL)
- return np;
- return node(op, tp, lp, rp);
-}
-
-/* TODO: check validity of types */
+/* TODO: fold OCOMMA */
 
 Node *
-castcode(Node *np, Type *newtp)
+simplify(Node *np)
 {
- TUINT negmask, mask, u;
- Type *oldtp = np->type;
- Symbol aux, *sym, *osym = np->sym;
+ Node *p, *l, *r;
+ extern int debug;
 
- if (!(np->flags & NCONST))
- goto noconstant;
+ if (!np)
+ return NULL;
+ if (debug)
+ prtree(np);
 
- switch (newtp->op) {
- case PTR:
- case INT:
- case ENUM:
- switch (oldtp->op) {
- case PTR:
- case INT:
- case ENUM:
- u = (oldtp->prop & TSIGNED) ? osym->u.i : osym->u.u;
- break;
- case FLOAT:
- oldtp = newtp;
- u = osym->u.f;
- break;
- default:
- goto noconstant;
- }
- mask = ones(newtp->size);
- if (newtp->prop & TSIGNED) {
- negmask = ~mask;
- if (u & (negmask >> 1) & mask)
- u |= negmask;
- aux.u.i = u;
- } else {
- aux.u.u = u & mask;
- }
- break;
- case FLOAT:
- /* FIXME: The cast can be from another float type */
- aux.u.f = (oldtp->prop & TSIGNED) ? osym->u.i : osym->u.u;
- break;
+ l = np->left = simplify(np->left);
+ r = np->right = simplify(np->right);
+
+ switch (np->op) {
+ case OASK:
+ return foldternary(np, l, r);
+ case OCALL:
+ case OPAR:
+ return np;
         default:
- goto noconstant;
+ commutative(np, l, r);
+ if ((p = fold(np)) != NULL)
+ return p;
+ if ((p = identity(np)) != NULL)
+ return p;
+ return np;
         }
-
- sym = newsym(NS_IDEN, NULL);
- np->type = sym->type = newtp;
- np->sym = sym;
- sym->u = aux.u;
-
- return np;
-
-noconstant:
- return node(OCAST, newtp, np, NULL);
 }
diff --git a/cc1/init.c b/cc1/init.c
index 8e16420..468a3b9 100644
--- a/cc1/init.c
+++ b/cc1/init.c
_AT_@ -94,7 +94,7 @@ designation(Init *ip)
 static Node *
 initialize(Type *tp)
 {
- Node *np, *aux;
+ Node *np;
         Symbol *sym;
         Type *btp;
         size_t len;
_AT_@ -133,12 +133,16 @@ initialize(Type *tp)
                 np->type = sym->type;
 
                 return np;
+ } else {
+ if (eqtype(tp, np->type, 1))
+ return np;
+ np = convert(decay(np), tp, 0);
+ if (!np) {
+ errorp("incorrect initializer");
+ goto return_zero;
+ }
         }
- if (eqtype(tp, np->type, 1))
- return np;
- if ((aux = convert(decay(np), tp, 0)) != NULL)
- return aux;
- errorp("incorrect initializer");
+ return simplify(np);
 
 return_zero:
         return constnode(zero);
Received on Sat Feb 04 2017 - 21:58:35 CET

This archive was generated by hypermail 2.3.0 : Sat Feb 04 2017 - 22:00:20 CET