optimize structure assignment based on size and alignment
authorSam Leffler <sam@ucbvax.Berkeley.EDU>
Sun, 26 Jan 1986 15:55:34 +0000 (07:55 -0800)
committerSam Leffler <sam@ucbvax.Berkeley.EDU>
Sun, 26 Jan 1986 15:55:34 +0000 (07:55 -0800)
SCCS-vsn: old/pcc/ccom.tahoe/local2.c 1.3

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

index 20e5bee..5e1070f 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)local2.c   1.2 (Berkeley) %G%";
+static char sccsid[] = "@(#)local2.c   1.3 (Berkeley) %G%";
 #endif
 
 # include "mfile2"
 #endif
 
 # include "mfile2"
@@ -380,60 +380,176 @@ zzzcode( p, c ) register NODE *p; {
                }
 
        case 'S':  /* structure assignment */
                }
 
        case 'S':  /* structure assignment */
-               {
-                       register NODE *l, *r;
-                       register int size;
+               stasg(p);
+               break;
 
 
-                       if( p->in.op == STASG ){
-                               l = p->in.left;
-                               r = p->in.right;
+       default:
+               cerror( "illegal zzzcode" );
+               }
+       }
 
 
-                               }
-                       else if( p->in.op == STARG ){  /* store an arg into a temporary */
-                               l = getlr( p, '3' );
-                               r = p->in.left;
-                               }
-                       else cerror( "STASG bad" );
-
-                       if( r->in.op == ICON ) r->in.op = NAME;
-                       else if( r->in.op == REG ) r->in.op = OREG;
-                       else if( r->in.op != OREG ) cerror( "STASG-r" );
-
-                       size = p->stn.stsize;
-
-                       if( size <= 0 || size > 65535 )
-                               cerror("structure size <0=0 or >65535");
-                       /*
-                        * Can't optimize with movw's or movl's here as
-                        * we don't know the alignment properties of
-                        * either source or destination (governed, potentially
-                        * by alignment of enclosing structure/union).
-                        * (PERHAPS WE COULD SIMULATE dclstruct?)
-                        */
-                       if (size != 1) {
-                               printf("\tmovab\t");
-                               adrput(l);
-                               printf(",r1\n\tmovab\t");
-                               adrput(r);
-                               printf(",r0\n\tmovl\t$%d,r2\n\tmovblk\n", size);
-                               rname(2);
-                       } else {
+#define        MOVB(dst, src, off) { \
+       printf("\tmovb\t"); upput(src, off); putchar(','); \
+       upput(dst, off); putchar('\n'); \
+}
+#define        MOVW(dst, src, off) { \
+       printf("\tmovw\t"); upput(src, off); putchar(','); \
+       upput(dst, off); putchar('\n'); \
+}
+#define        MOVL(dst, src, off) { \
+       printf("\tmovl\t"); upput(src, off); putchar(','); \
+       upput(dst, off); putchar('\n'); \
+}
+/*
+ * Generate code for a structure assignment.
+ */
+stasg(p)
+       register NODE *p;
+{
+       register NODE *l, *r;
+       register int size;
+
+       switch (p->in.op) {
+       case STASG:                     /* regular assignment */
+               l = p->in.left;
+               r = p->in.right;
+               break;
+       case STARG:                     /* place arg on the stack */
+               l = getlr(p, '3');
+               r = p->in.left;
+               break;
+       default:
+               cerror("STASG bad");
+               /*NOTREACHED*/
+       }
+       /*
+        * Pun source for use in code generation.
+        */
+       switch (r->in.op) {
+       case ICON:
+               r->in.op = NAME;
+               break;
+       case REG:
+               r->in.op = OREG;
+               break;
+       default:
+               cerror( "STASG-r" );
+               /*NOTREACHED*/
+       }
+       size = p->stn.stsize;
+       if (size <= 0 || size > 65535)
+               cerror("structure size out of range");
+       /*
+        * Generate optimized code based on structure size
+        * and alignment properties....
+        */
+       switch (size) {
+
+       case 1:
+               printf("\tmovb\t");
+       optimized:
+               adrput(r);
+               printf(",");
+               adrput(l);
+               printf("\n");
+werror("optimized structure assignment (size %d alignment %d)", size, p->stn.stalign);
+               break;
+
+       case 2:
+               if (p->stn.stalign != 2) {
+                       MOVB(l, r, SZCHAR);
+                       printf("\tmovb\t");
+               } else
+                       printf("\tmovw\t");
+               goto optimized;
+
+       case 4:
+               if (p->stn.stalign != 4) {
+                       if (p->stn.stalign != 2) {
+                               MOVB(l, r, 3*SZCHAR);
+                               MOVB(l, r, 2*SZCHAR);
+                               MOVB(l, r, 1*SZCHAR);
                                printf("\tmovb\t");
                                printf("\tmovb\t");
-                               adrput(r);
-                               printf(",");
-                               adrput(l);
-                               printf("\n");
+                       } else {
+                               MOVW(l, r, SZSHORT);
+                               printf("\tmovw\t");
                        }
                        }
-                       if( r->in.op == NAME ) r->in.op = ICON;
-                       else if( r->in.op == OREG ) r->in.op = REG;
+               } else
+                       printf("\tmovl\t");
+               goto optimized;
+
+       case 6:
+               if (p->stn.stalign != 2)
+                       goto movblk;
+               MOVW(l, r, 2*SZSHORT);
+               MOVW(l, r, 1*SZSHORT);
+               printf("\tmovw\t");
+               goto optimized;
+
+       case 8:
+               if (p->stn.stalign == 4) {
+                       MOVL(l, r, SZLONG);
+                       printf("\tmovl\t");
+                       goto optimized;
+               }
+               /* fall thru...*/
 
 
-                       }
+       default:
+       movblk:
+               /*
+                * Can we ever get a register conflict with R1 here?
+                */
+               printf("\tmovab\t");
+               adrput(l);
+               printf(",r1\n\tmovab\t");
+               adrput(r);
+               printf(",r0\n\tmovl\t$%d,r2\n\tmovblk\n", size);
+               rname(R2);
                break;
                break;
+       }
+       /*
+        * Reverse above pun for reclaim.
+        */
+       if (r->in.op == NAME)
+               r->in.op = ICON;
+       else if (r->in.op == OREG)
+               r->in.op = REG;
+}
 
 
-       default:
-               cerror( "illegal zzzcode" );
+/*
+ * Output the address of the second item in the
+ * pair pointed to by p.
+ */
+upput(p, size)
+       register NODE *p;
+{
+       CONSZ save;
+
+       if (p->in.op == FLD)
+               p = p->in.left;
+       switch (p->in.op) {
+
+       case NAME:
+       case OREG:
+               save = p->tn.lval;
+               p->tn.lval += size/SZCHAR;
+               adrput(p);
+               p->tn.lval = save;
+               break;
+
+       case REG:
+               if (size == SZLONG) {
+                       printf("%s", rname(p->tn.rval+1));
+                       break;
                }
                }
+               /* fall thru... */
+
+       default:
+               cerror("illegal upper address op %s size %d",
+                   opst[p->tn.op], size);
+               /*NOTREACHED*/
        }
        }
+}
 
 rmove( rt, rs, t ) TWORD t;{
        printf( "       movl    %s,%s\n", rname(rs), rname(rt) );
 
 rmove( rt, rs, t ) TWORD t;{
        printf( "       movl    %s,%s\n", rname(rs), rname(rt) );
@@ -603,33 +719,6 @@ insput( p ) NODE *p; {
        cerror( "insput" );
        }
 
        cerror( "insput" );
        }
 
-upput( p ) register NODE *p; {
-       /* output the address of the second long in the
-          pair pointed to by p (for DOUBLEs)*/
-       CONSZ save;
-
-       if( p->in.op == FLD ){
-               p = p->in.left;
-               }
-       switch( p->in.op ){
-
-       case NAME:
-       case OREG:
-               save = p->tn.lval;
-               p->tn.lval += SZLONG/SZCHAR;
-               adrput(p);
-               p->tn.lval = save;
-               return;
-
-       case REG:
-               printf( "%s", rname(p->tn.rval+1) );
-               return;
-
-       default:
-               cerror( "illegal upper address" );
-               }
-       }
-
 adrput( p ) register NODE *p; {
        register int r;
        /* output an address, with offsets, from p */
 adrput( p ) register NODE *p; {
        register int r;
        /* output an address, with offsets, from p */