completely redo handling of SCONV nodes to cope with Tahoe's
authorSam Leffler <sam@ucbvax.Berkeley.EDU>
Sat, 10 Jan 1987 07:25:03 +0000 (23:25 -0800)
committerSam Leffler <sam@ucbvax.Berkeley.EDU>
Sat, 10 Jan 1987 07:25:03 +0000 (23:25 -0800)
incorrect handling of char's and short's in registers (e.g. cvtwl r0,r0
does a movl); also correct OPLOG handling for items shorter than 32-bits:
tst[wb] on registers don't work, but cmp[bw] $0,r? does; finally, handle
change to local.c which leaves in lots of new SCONV's (we optimize those
which are extraneous in code added mainly to optim2)

SCCS-vsn: old/pcc/ccom.tahoe/local2.c 1.8
SCCS-vsn: old/pcc/ccom.tahoe/table.c 1.5

usr/src/old/pcc/ccom.tahoe/local2.c
usr/src/old/pcc/ccom.tahoe/table.c

index f3bd37c..3126141 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)local2.c   1.7 (Berkeley) %G%";
+static char sccsid[] = "@(#)local2.c   1.8 (Berkeley) %G%";
 #endif
 
 # include "pass2.h"
 #endif
 
 # include "pass2.h"
@@ -132,6 +132,16 @@ tlen(p) NODE *p;
                }
 }
 
                }
 }
 
+anyfloat(p, q)
+       NODE *p, *q;
+{
+       register TWORD tp, tq;
+
+       tp = p->in.type;
+       tq = q->in.type;
+       return (tp == FLOAT || tp == DOUBLE || tq == FLOAT || tq == DOUBLE);
+}
+
 prtype(n) NODE *n;
 {
        switch (n->in.type)
 prtype(n) NODE *n;
 {
        switch (n->in.type)
@@ -331,8 +341,7 @@ zzzcode( p, c ) register NODE *p; {
                return;
                }
 
                return;
                }
 
-       case 'M':  /* initiate ediv for mod and unsigned div */
-               {
+       case 'M': {  /* initiate ediv for mod and unsigned div */
                register char *r;
                m = getlr(p, '1')->tn.rval;
                r = rname(m);
                register char *r;
                m = getlr(p, '1')->tn.rval;
                r = rname(m);
@@ -344,42 +353,15 @@ zzzcode( p, c ) register NODE *p; {
                        printf("\tjgeq\tL%d\n\tmnegl\t$1,%s\n", m, r);
                        deflab(m);
                }
                        printf("\tjgeq\tL%d\n\tmnegl\t$1,%s\n", m, r);
                        deflab(m);
                }
-               }
                return;
                return;
+       }
 
 
-       case 'U':
-               /* Truncate int for type conversions:
-                   LONG|ULONG -> CHAR|UCHAR|SHORT|USHORT
-                   SHORT|USHORT -> CHAR|UCHAR
-                  increment offset to correct byte */
-               {
-               register NODE *p1;
-               int dif;
-
-               p1 = p->in.left;
-               switch( p1->in.op ){
-               case NAME:
-               case OREG:
-                       dif = tlen(p1)-tlen(p);
-                       p1->tn.lval += dif;
-                       adrput(p1);
-                       p1->tn.lval -= dif;
-                       return;
-               default:
-                       cerror( "Illegal ZU type conversion" );
-                       return;
-                       }
-               }
-
-       case 'T':       /* rounded structure length for arguments */
-               {
-               int size;
-
-               size = p->stn.stsize;
+       case 'T': {     /* rounded structure length for arguments */
+               int size = p->stn.stsize;
                SETOFF( size, 4);
                printf("movab   -%d(sp),sp", size);
                return;
                SETOFF( size, 4);
                printf("movab   -%d(sp),sp", size);
                return;
-               }
+       }
 
        case 'S':  /* structure assignment */
                stasg(p);
 
        case 'S':  /* structure assignment */
                stasg(p);
@@ -408,10 +390,32 @@ zzzcode( p, c ) register NODE *p; {
                printf("\n");
                return;
 
                printf("\n");
                return;
 
+       case 'U':               /* SCONV */
+       case 'V':               /* SCONV with FORCC */
+               sconv(p, c == 'V');
+               break;
+
+       case 'Z':
+               p = p->in.right;
+               switch (p->in.type) {
+               case SHORT: {
+                       short w = p->tn.lval;
+                       p->tn.lval = w;
+                       break;
+               }
+               case CHAR: {
+                       char c = p->tn.lval;
+                       p->tn.lval = c;
+                       break;
+               }
+               }
+               printf("$%d", p->tn.lval);
+               break;
+
        default:
                cerror( "illegal zzzcode" );
        default:
                cerror( "illegal zzzcode" );
-               }
        }
        }
+}
 
 #define        MOVB(dst, src, off) { \
        putstr("\tmovb\t"); upput(src, off); putchar(','); \
 
 #define        MOVB(dst, src, off) { \
        putstr("\tmovb\t"); upput(src, off); putchar(','); \
@@ -575,6 +579,121 @@ upput(p, size)
        }
 }
 
        }
 }
 
+/*
+ * Generate code for storage conversions.
+ */
+sconv(p, forcc)
+       NODE *p;
+{
+       register NODE *l, *r;
+       register wfrom, wto;
+       int oltype;
+
+       l = getlr(p, '1');
+       oltype = l->in.type, l->in.type = r->in.type;
+       r = getlr(p, 'L');
+       wfrom = tlen(r), wto = tlen(l);
+       if (wfrom == wto)               /* e.g. int -> unsigned */
+               goto done;
+       /*
+        * Conversion in registers requires care
+        * as cvt and movz instruction don't work
+        * as expected (they end up as plain mov's).
+        */
+       if (l->in.op == REG && r->in.op == REG) {
+               if (ISUNSIGNED(r->in.type)) {           /* unsigned, mask */
+                       if (r->tn.lval != l->tn.lval) {
+                               printf("\tandl3\t$%d,", (1<<(wto*SZCHAR))-1);
+                               adrput(r);
+                               putchar(',');
+                       } else
+                               printf("\tandl2\t$%d,", (1<<(wto*SZCHAR))-1);
+                       adrput(l);
+               } else {                                /* effect sign-extend */
+                       int shift = (sizeof (int)-wto)*SZCHAR;
+                       printf("\tshll\t$%d,", shift);
+                       adrput(r); putchar(','); adrput(l);
+                       printf("\n\tshar\t$%d,", shift);
+                       adrput(l); putchar(','); adrput(l);
+                       if (wfrom != sizeof (int)) {
+                               /*
+                                * Must mask if result is shorter than
+                                * the width of a register (to account
+                                * for register treatment).
+                                */
+                               printf("\n\tandl2\t$%d,",(1<<(wfrom*SZCHAR))-1);
+                               adrput(l);
+                       } else
+                               forcc = 0;
+               }
+               /*
+                * If condition codes are required and the last thing
+                * we did was mask the result, then we must generate a
+                * test of the appropriate type.
+                */
+               if (forcc) {
+                       printf("\n\tcmp");
+                       prtype(l);
+                       putchar('\t');
+                       printf("$0,");
+                       adrput(l);
+               }
+       } else {
+               /*
+                * Conversion with at least one parameter in memory.
+                */
+               if (wfrom < wto) {              /* expanding datum */
+                       if (ISUNSIGNED(r->in.type)) {
+                               printf("\tmovz");
+                               prtype(r);
+                               /*
+                                * If target is a register, generate
+                                * movz?l so optimizer can compress
+                                * argument pushes.
+                                */
+                               if (l->in.op == REG)
+                                       putchar('l');
+                               else
+                                       prtype(l);
+                       } else {
+                               printf("\tcvt");
+                               prtype(r), prtype(l);
+                       }
+                       putchar('\t');
+                       adrput(r);
+               } else {                        /* shrinking dataum */
+                       int off = wfrom - wto;
+                       if (l->in.op == REG) {
+                               printf("\tmovz");
+                               prtype(l);
+                               putchar('l');
+                       } else {
+                               printf("\tcvt");
+                               prtype(l), prtype(r);
+                       }
+                       putchar('\t');
+                       switch (r->in.op) {
+                       case NAME: case OREG:
+                               r->tn.lval += off;
+                               adrput(r);
+                               r->tn.lval -= off;
+                               break;
+                       case REG: case ICON: case UNARY MUL:
+                               adrput(r);
+                               break;
+                       default:
+                               cerror("sconv: bad shrink op");
+                               /*NOTREACHED*/
+                       }
+               }
+               putchar(',');
+               adrput(l);
+       }
+       putchar('\n');
+done:
+       l->in.type = oltype;
+}
+
 rmove( rt, rs, t ) TWORD t;{
        printf( "       movl    %s,%s\n", rname(rs), rname(rt) );
        if(t==DOUBLE)
 rmove( rt, rs, t ) TWORD t;{
        printf( "       movl    %s,%s\n", rname(rs), rname(rt) );
        if(t==DOUBLE)
@@ -967,28 +1086,65 @@ optim2( p ) register NODE *p; {
        /* do local tree transformations and optimizations */
 # define RV(p) p->in.right->tn.lval
 # define nncon(p)      ((p)->in.op == ICON && (p)->in.name[0] == 0)
        /* do local tree transformations and optimizations */
 # define RV(p) p->in.right->tn.lval
 # define nncon(p)      ((p)->in.op == ICON && (p)->in.name[0] == 0)
-       register int o = p->in.op;
-       register int i;
+       register int o, i;
+       register NODE *l, *r;
 
 
-       /* change unsigned mods and divs to logicals (mul is done in mip & c2) */
-       if(optype(o) == BITYPE && ISUNSIGNED(p->in.left->in.type)
-        && nncon(p->in.right) && (i=ispow2(RV(p)))>=0){
-               switch(o) {
-               case DIV:
-               case ASG DIV:
-                       p->in.op = RS;
-                       RV(p) = i;
-                       break;
-               case MOD:
-               case ASG MOD:
-                       p->in.op = AND;
-                       RV(p)--;
-                       break;
-               default:
-                       return;
+       switch (o = p->in.op) {
+
+       case DIV: case ASG DIV:
+       case MOD: case ASG MOD:
+               /*
+                * Change unsigned mods and divs to
+                * logicals (mul is done in mip & c2)
+                */
+               if (ISUNSIGNED(p->in.left->in.type) && nncon(p->in.right) &&
+                   (i = ispow2(RV(p))) >= 0) {
+                       if (o == DIV || o == ASG DIV) {
+                               p->in.op = RS;
+                               RV(p) = i;
+                       } else {
+                               p->in.op = AND;
+                               RV(p)--;
+                       }
+                       if (asgop(o))
+                               p->in.op = ASG p->in.op;
+               }
+               return;
+
+       case SCONV:
+               l = p->in.left;
+               /* clobber conversions w/o side effects */
+               if (!anyfloat(p, l) && l->in.op != PCONV &&
+                   tlen(p) == tlen(l)) {
+                       if (l->in.op != FLD)
+                               l->in.type = p->in.type;
+                       ncopy(p, l);
+                       l->in.op = FREE;
+               }
+               return;
+
+       case ASSIGN:
+               /*
+                * Try to zap storage conversions of non-float items.
+                */
+               r = p->in.right;
+               if (r->in.op == SCONV && !anyfloat(r->in.left, r)) {
+                       int wdest, wconv, wsrc;
+                       wdest = tlen(p->in.left);
+                       wconv = tlen(r);
+                       /*
+                        * If size doesn't change across assignment or
+                        * conversion expands src before shrinking again
+                        * due to the assignment, delete conversion so
+                        * code generator can create optimal code.
+                        */
+                       if (wdest == wconv ||
+                        (wdest == (wsrc = tlen(r->in.left)) && wconv > wsrc)) {
+                               p->in.right = r->in.left;
+                               r->in.op = FREE;
+                       }
                }
                }
-               if(asgop(o))
-                       p->in.op = ASG p->in.op;
+               return;
        }
 # endif
 }
        }
 # endif
 }
@@ -1151,7 +1307,26 @@ main( argc, argv ) char *argv[]; {
        }
 # endif
 
        }
 # endif
 
+strip(p) register NODE *p; {
+       NODE *q;
+
+       /* strip nodes off the top when no side effects occur */
+       for( ; ; ) {
+               switch( p->in.op ) {
+               case SCONV:                     /* remove lint tidbits */
+                       q = p->in.left;
+                       ncopy( p, q );
+                       q->in.op = FREE;
+                       break;
+               /* could probably add a few more here */
+               default:
+                       return;
+                       }
+               }
+       }
+
 myreader(p) register NODE *p; {
 myreader(p) register NODE *p; {
+       strip( p );             /* strip off operations with no side effects */
        walkf( p, hardops );    /* convert ops to function calls */
        canon( p );             /* expands r-vals for fileds */
        walkf( p, optim2 );
        walkf( p, hardops );    /* convert ops to function calls */
        canon( p );             /* expands r-vals for fileds */
        walkf( p, optim2 );
index 38bb8f0..7b55c68 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)table.c    1.4 (Berkeley) %G%";
+static char sccsid[] = "@(#)table.c    1.5 (Berkeley) %G%";
 #endif
 
 # include "pass2.h"
 #endif
 
 # include "pass2.h"
@@ -59,49 +59,17 @@ SCONV,      INAREG|INTAREG|FORCC,
                NAREG|NASL,     RESC1|RESCC,
                "       ldZL    AL\n    cvZLl   A1\n",
 
                NAREG|NASL,     RESC1|RESCC,
                "       ldZL    AL\n    cvZLl   A1\n",
 
-/* cast to longer types */
-SCONV, INAREG|INTAREG|FORCC,
-       SAREG|AWD,      TCHAR,
-       SANY,   TUSHORT,
-               NAREG|NASL,     RESC1|RESCC,
-               "       cvtbw   AL,A1\n andl2   $0xffff,A1\n",
-
-/* casts to shorter types */
-SCONV, INAREG|INTAREG|FORCC,
-       SAREG|SCON,     ANYFIXED,
-       SANY,   ANYUSIGNED,
-               NAREG|NASL,     RESC1|RESCC,
-               "       movzZRl AL,A1\n",
-
-SCONV, INAREG|INTAREG|FORCC,
-       SNAME,  ANYFIXED,
-       SANY,   ANYUSIGNED,
-               NAREG|NASL,     RESC1|RESCC,
-               "       movzZRl ZU,A1\n",
-
-SCONV, INAREG|INTAREG|FORCC,
-       SSOREG, ANYFIXED,
-       SANY,   ANYUSIGNED,
-               NAREG|NASL,     RESC1|RESCC,
-               "       movzZRl ZU,A1\n",
-
-SCONV, INAREG|INTAREG|FORCC,
-       SAREG|SCON,     ANYFIXED,
-       SANY,   ANYFIXED,
-               NAREG|NASL,     RESC1|RESCC,
-               "       cvtZRl  AL,A1\n",
-
-SCONV, INAREG|INTAREG|FORCC,
-       SNAME,  ANYFIXED,
+SCONV, INAREG|INTAREG,
+       SAREG|AWD,      ANYFIXED,
        SANY,   ANYFIXED,
                NAREG|NASL,     RESC1|RESCC,
        SANY,   ANYFIXED,
                NAREG|NASL,     RESC1|RESCC,
-               "       cvtZRl  ZU,A1\n",
+               "ZU",
 
 SCONV, INAREG|INTAREG|FORCC,
 
 SCONV, INAREG|INTAREG|FORCC,
-       SSOREG, ANYFIXED,
+       SAREG|AWD,      ANYFIXED,
        SANY,   ANYFIXED,
                NAREG|NASL,     RESC1|RESCC,
        SANY,   ANYFIXED,
                NAREG|NASL,     RESC1|RESCC,
-               "       cvtZRl  ZU,A1\n",
+               "ZV",
 
 INIT,  FOREFF,
        SCON,   TANY,
 
 INIT,  FOREFF,
        SCON,   TANY,
@@ -178,34 +146,16 @@ OPLOG,    FORCC,
                "       cmpl    AL,AR\nZP",
 
 OPLOG, FORCC,
                "       cmpl    AL,AR\nZP",
 
 OPLOG, FORCC,
-       SAREG|AWD,      TSHORT|TUSHORT,
-       SCON     ,      TUSHORT,
+       AWD,            TUSHORT,
+       SCON,   TANY,
                NAREG,  RESCC,
                "       movzwl  AL,A1\n cmpw    A1,AR\nZP",
                NAREG,  RESCC,
                "       movzwl  AL,A1\n cmpw    A1,AR\nZP",
-OPLOG, FORCC,
-       SAREG|AWD,      TSHORT|TUSHORT,
-       SAREG|AWD,      TSHORT|TUSHORT,
-               0,      RESCC,
-               "       cmpw    AL,AR\nZP",
-
-OPLOG, FORCC,
-       SAREG|AWD,      TCHAR|TUCHAR,
-       SCON     ,      TUCHAR,
-               NAREG,  RESCC,
-               "       movzbl  AL,A1\n cmpb    A1,AR\nZP",
-
-OPLOG, FORCC,
-       SAREG|AWD,      TCHAR|TUCHAR,
-       SAREG|AWD,      TCHAR|TUCHAR,
-               0,      RESCC,
-               "       cmpb    AL,AR\nZP",
 
 OPLOG, FORCC,
        SAREG|AWD,      TSHORT|TUSHORT,
 
 OPLOG, FORCC,
        SAREG|AWD,      TSHORT|TUSHORT,
-       SSCON,  TANY,
+       SCON,   TANY,
                0,      RESCC,
                0,      RESCC,
-               "       cmpw    AL,AR\nZP",
-
+               "       cmpw    AL,ZZ\nZP",
 
 OPLOG, FORCC,
        SAREG|AWD,      TSHORT|TUSHORT,
 
 OPLOG, FORCC,
        SAREG|AWD,      TSHORT|TUSHORT,
@@ -214,20 +164,20 @@ OPLOG,    FORCC,
                "       cmpw    AL,AR\nZP",
 
 OPLOG, FORCC,
                "       cmpw    AL,AR\nZP",
 
 OPLOG, FORCC,
-       SAREG|AWD,      TCHAR|TUCHAR,
-       SAREG|AWD,      TCHAR|TUCHAR,
-               0,      RESCC,
-               "       cmpb    AL,AR\nZP",
+       AWD,            TUCHAR,
+       SCON,           TANY,
+               NAREG,  RESCC,
+               "       movzbl  AL,A1\n cmpb    A1,AR\nZP",
 
 OPLOG, FORCC,
 
 OPLOG, FORCC,
-       SAREG|AWD,      TSHORT|TUSHORT,
-       SSCON,  TANY,
+       SAREG|AWD,      TCHAR|TUCHAR,
+       SCON,   TANY,
                0,      RESCC,
                0,      RESCC,
-               "       cmpw    AL,AR\nZP",
+               "       cmpb    AL,ZZ\nZP",
 
 OPLOG, FORCC,
        SAREG|AWD,      TCHAR|TUCHAR,
 
 OPLOG, FORCC,
        SAREG|AWD,      TCHAR|TUCHAR,
-       SCCON,  TANY,
+       SAREG|AWD,      TCHAR|TUCHAR,
                0,      RESCC,
                "       cmpb    AL,AR\nZP",
 
                0,      RESCC,
                "       cmpb    AL,AR\nZP",