commit dac8c31a33977081e510992580a5e47c2d3ffe84
Author:     Roberto E. Vargas Caballero <[email protected]>
AuthorDate: Sun Jul 26 19:54:41 2015 +0200
Commit:     Roberto E. Vargas Caballero <[email protected]>
CommitDate: Sun Jul 26 19:54:41 2015 +0200

    Fix simplification of comparision nodes
    
    Comparision nodes have integer type, but the operands cn have
    a different type, so we cannot take the decision based in the
    type parameter of simplify().

diff --git a/cc1/cc1.h b/cc1/cc1.h
index 385797a..8da3585 100644
--- a/cc1/cc1.h
+++ b/cc1/cc1.h
@@ -335,6 +335,7 @@ extern Node *usimplify(unsigned char op, Type *tp, Node 
*np);
 extern Node *expr(void), *negate(Node *np), *constexpr(void);
 extern Node *convert(Node *np, Type *tp1, char iscast);
 extern Node *iszero(Node *np), *eval(Node *np), *iconstexpr(void);
+extern bool isnodecmp(int op);
 
 /* cpp.c */
 extern void icpp(void);
diff --git a/cc1/code.c b/cc1/code.c
index e982b99..e8ed265 100644
--- a/cc1/code.c
+++ b/cc1/code.c
@@ -391,6 +391,9 @@ sizeofnode(Type *tp)
        ((sym)->u.i = ((ls)->u.i op (rs)->u.i)) :       \
        ((sym)->u.u = ((ls)->u.u op (rs)->u.u)))
 
+#define CMPISYM(sym, ls, rs, op) (((sym)->type->sign) ? \
+       ((ls)->u.i op (rs)->u.i) : ((ls)->u.u op (rs)->u.u))
+
 Node *
 simplify(unsigned char op, Type *tp, Node *lp, Node *rp)
 {
@@ -403,8 +406,22 @@ simplify(unsigned char op, Type *tp, Node *lp, Node *rp)
 
        /* TODO: Add overflow checkings */
 
+       if (isnodecmp(op)) {
+               /*
+                * Comparision nodes have integer type
+                * but the operands can have different
+                * type.
+                */
+               switch (BTYPE(lp)) {
+               case INT:   goto cmp_integers;
+               case FLOAT: goto cmp_floats;
+               default:    goto no_simplify;
+               }
+       }
+
        switch (tp->op) {
        case INT:
+       cmp_integers:
                switch (op) {
                case OADD:
                        FOLDINT(&aux, ls, rs, +);
@@ -431,29 +448,6 @@ simplify(unsigned char op, Type *tp, Node *lp, Node *rp)
                case OSHR:
                        FOLDINT(&aux, ls, rs, >>);
                        break;
-               /*
-                * FIXME: comparision nodes are integers
-                * but it doesn't mean the operands are
-                * integers too
-                */
-               case OLT:
-                       FOLDINT(&aux, ls, rs, <);
-                       break;
-               case OGT:
-                       FOLDINT(&aux, ls, rs, >);
-                       break;
-               case OGE:
-                       FOLDINT(&aux, ls, rs, >=);
-                       break;
-               case OLE:
-                       FOLDINT(&aux, ls, rs, <=);
-                       break;
-               case OEQ:
-                       FOLDINT(&aux, ls, rs, ==);
-                       break;
-               case ONE:
-                       FOLDINT(&aux, ls, rs, !=);
-                       break;
                case OBAND:
                        FOLDINT(&aux, ls, rs, &);
                        break;
@@ -469,9 +463,28 @@ simplify(unsigned char op, Type *tp, Node *lp, Node *rp)
                case OOR:
                        FOLDINT(&aux, ls, rs, ||);
                        break;
+               case OLT:
+                       aux.u.i = CMPISYM(&aux, ls, rs, <);
+                       break;
+               case OGT:
+                       aux.u.i = CMPISYM(&aux, ls, rs, >);
+                       break;
+               case OGE:
+                       aux.u.i = CMPISYM(&aux, ls, rs, >=);
+                       break;
+               case OLE:
+                       aux.u.i = CMPISYM(&aux, ls, rs, <=);
+                       break;
+               case OEQ:
+                       aux.u.i = CMPISYM(&aux, ls, rs, ==);
+                       break;
+               case ONE:
+                       aux.u.i = CMPISYM(&aux, ls, rs, !=);
+                       break;
                }
                break;
        case FLOAT:
+       cmp_floats:
                switch (op) {
                case OADD:
                        aux.u.f = ls->u.f + rs->u.f;
@@ -487,6 +500,24 @@ simplify(unsigned char op, Type *tp, Node *lp, Node *rp)
                                goto division_by_0;
                        aux.u.f = ls->u.f / rs->u.f;
                        break;
+               case OLT:
+                       aux.u.i = ls->u.f < rs->u.f;
+                       break;
+               case OGT:
+                       aux.u.i = ls->u.f > rs->u.f;
+                       break;
+               case OGE:
+                       aux.u.i = ls->u.f >= rs->u.f;
+                       break;
+               case OLE:
+                       aux.u.i = ls->u.f <= rs->u.f;
+                       break;
+               case OEQ:
+                       aux.u.i = ls->u.f == rs->u.f;
+                       break;
+               case ONE:
+                       aux.u.i = ls->u.f != rs->u.f;
+                       break;
                }
                break;
        default:
diff --git a/cc1/expr.c b/cc1/expr.c
index 7ae3666..e0ab3d3 100644
--- a/cc1/expr.c
+++ b/cc1/expr.c
@@ -303,10 +303,10 @@ negate(Node *np)
        return np;
 }
 
-static bool
-isnodecmp(Node *np)
+bool
+isnodecmp(int op)
 {
-       switch (np->op) {
+       switch (op) {
        case OEQ:
        case ONE:
        case OLT:
@@ -322,7 +322,7 @@ isnodecmp(Node *np)
 static Node *
 exp2cond(Node *np, char neg)
 {
-       if (isnodecmp(np))
+       if (isnodecmp(np->op))
                return (neg) ? negate(np) : np;
        return compare(ONE ^ neg, np, constnode(zero));
 }
@@ -374,7 +374,7 @@ array(Node *lp, Node *rp)
 Node *
 iszero(Node *np)
 {
-       if (isnodecmp(np))
+       if (isnodecmp(np->op))
                return np;
        return compare(ONE, np, constnode(zero));
 }

Reply via email to