Annotation of researchv9/jerq/sgs/optim/optutil.c, revision 1.1

1.1     ! root        1: /* @(#) optutil.c: 1.3 3/27/84                         */
        !             2: /* optutil.c
        !             3: **
        !             4: **     Optimizer utilities for 3B code improver (PCI).
        !             5: **
        !             6: **
        !             7: ** This module contains utility routines for the various peephole
        !             8: ** window optimizations.
        !             9: */
        !            10: 
        !            11: /* #include <ctype.h> -- optim.h takes care of this */
        !            12: /* #include "defs" -- optim.h takes care of this; machine-dependent defs */
        !            13: #include "optim.h"                     /* machine independent optimizer defs */
        !            14: 
        !            15: extern long atol();
        !            16: /* isreg -- is operand string a register reference?
        !            17: **
        !            18: ** This routine tells whether an operand string is a register reference.
        !            19: */
        !            20: 
        !            21: boolean
        !            22: isreg(s)
        !            23: char * s;                              /* operand string */
        !            24: {
        !            25: /* assume operand is a register reference if it begins with a % */
        !            26: 
        !            27:        return(*s == '%');
        !            28: }
        !            29: 
        !            30: 
        !            31: 
        !            32: /* isnib -- is operand a nibble?
        !            33: **
        !            34: ** This routine tests an operand string and tells whether it is an
        !            35: ** immediate operand that can fit in a nibble (4 bits).
        !            36: */
        !            37: 
        !            38: boolean
        !            39: isnib(s)
        !            40: char * s;                              /* operand string to check */
        !            41: {
        !            42:     long x;                            /* temporary to hold value */
        !            43: 
        !            44: /* Return true if the operand begins with a '&', it is numeric,
        !            45: ** and the numeric value is between 0 and 15.
        !            46: */
        !            47: 
        !            48:     return(    *s == '&'               /* begins with & */
        !            49:           &&   isdigit(*++s)           /* operand is numeric */
        !            50:           &&   (x = atol(s)) >= 0      /* is positive */
        !            51:           &&   x <= 15                 /* and <= 15 */
        !            52:          );
        !            53: }
        !            54: /* isnegnib -- is operand a negative nibble?
        !            55: **
        !            56: ** This routine tests whether an operand string is an immediate operand
        !            57: ** with a value between -1 and -15.  Another condition tested is that
        !            58: ** the minus sign immediately follows an '&'.  (This condition is
        !            59: ** important if the operand is overwritten.)
        !            60: */
        !            61: 
        !            62: boolean
        !            63: isnegnib(s)
        !            64: char * s;                              /* operand string */
        !            65: {
        !            66:     long n;                            /* temporary operand value */
        !            67: 
        !            68:     return(
        !            69:                s != NULL
        !            70:            &&  *s++ == '&'             /* operand starts with & */
        !            71:            &&  *s++ == '-'             /* followed by - */
        !            72:            &&  isdigit(*s)             /* operand is numeric */
        !            73:            &&  1 <= (n = atol(s))      /* (positive) value between 1... */
        !            74:            &&  n <= 15                 /* and 15 */
        !            75:            );
        !            76: }
        !            77: /* getbit -- get bit number for power of 2
        !            78: **
        !            79: ** This routine tests whether an operand is a power of 2.  If not, it
        !            80: ** returns -1.  Otherwise it returns a bit number, which is also the
        !            81: ** exponent of 2.
        !            82: */
        !            83: 
        !            84: int
        !            85: getbit(s)
        !            86: char * s;                              /* pointer to operand string */
        !            87: {
        !            88:     int bit = 0;                       /* initialize bit number for later */
        !            89:     long n;                            /* numeric value of operand */
        !            90:     boolean isnumlit();
        !            91: 
        !            92:     if ( (! isnumlit(s)) || (n = atol(s+1)) < 0 )
        !            93:        return(-1);                     /* check for numeric literal with
        !            94:                                        ** good value
        !            95:                                        */
        !            96: 
        !            97: /* This test really works, although it looks suspicious.  A power of two
        !            98: ** has only one bit set, so that value minus one has all of the bits to
        !            99: ** the right of the original bit set.  Anding them together gives zero.
        !           100: ** No other value yields zero.
        !           101: */
        !           102: 
        !           103:     if ( ( n & (n-1) ) != 0)
        !           104:        return(-1);                     /* not a power of 2 */
        !           105: 
        !           106: /* Shift right until the word is zero */
        !           107: 
        !           108:     while ((n = n>>1) != 0)
        !           109:        bit++;                          /* bump bit number each time */
        !           110: 
        !           111:     return(bit);                       /* return bit number */
        !           112: }
        !           113: /* insert -- insert new instruction node
        !           114: **
        !           115: ** This routine inserts a new instruction node after the one pointed
        !           116: ** to.  The fields in the node are initialized to null values.
        !           117: */
        !           118: 
        !           119: NODE *                                 /* return pointer to the new node */
        !           120: insert(pn)
        !           121: NODE * pn;                             /* node to add pointer after */
        !           122: {
        !           123:     NODE * Saveop();                   /* in machine-independent part */
        !           124:     NODE * new = Saveop(0,"",0,GHOST); /* create isolated node, init. */
        !           125: 
        !           126:     APPNODE(new,pn);                   /* append new node after current */
        !           127: 
        !           128:     return(new);                       /* return pointer to the new one */
        !           129: }
        !           130: /* chgop -- change op code number and op code string in node
        !           131: **
        !           132: ** This routine changes the op code information in a node.  The
        !           133: ** operand information is unaffected.
        !           134: */
        !           135: 
        !           136: void
        !           137: chgop(n,op,op_code)
        !           138: NODE * n;                              /* pointer to node to change */
        !           139: int op;                                        /* op code number */
        !           140: char * op_code;                                /* pointer to op code string */
        !           141: {
        !           142:     n->op = op;                                /* set op code number */
        !           143:     n->opcode = op_code;               /* and string */
        !           144:     return;
        !           145: }
        !           146: /* copyopn -- copy operand string
        !           147: **
        !           148: ** This routine duplicates an operand string in a new piece of memory.
        !           149: ** The caller can specify a +/- number of additional bytes required,
        !           150: ** as well as an offset for copying.
        !           151: */
        !           152: 
        !           153: char *                                 /* return duplicate string */
        !           154: copyopn(s,extra,offset)
        !           155: char * s;                              /* original operand string */
        !           156: int extra;                             /* number of extra (or fewer) chars */
        !           157: int offset;                            /* offset in original operand from
        !           158:                                        ** which to start copying.
        !           159:                                        */
        !           160: {
        !           161:     int len = strlen(s) + extra;       /* length of duplicate */
        !           162:     char * stemp;                      /* future duplicate string */
        !           163: 
        !           164:     if (len <= 0)
        !           165:        return(NULL);                   /* deleted everything */
        !           166:     
        !           167:     stemp = getspace(len+1);           /* get new string (+1 for null byte) */
        !           168:     return(strcpy(stemp,s+offset));    /* return copy */
        !           169: }
        !           170: /* isdyadic -- is instruction dyadic
        !           171: **
        !           172: ** This routine tells whether an instruction is dyadic according
        !           173: ** to the following conditions:
        !           174: **
        !           175: **     1.      It takes two operands.
        !           176: **     2.      It reads the first operand, writes the second.
        !           177: **     3.      It sets the condition codes according to the value stored in
        !           178: **             the second operand.
        !           179: **     4.      The operands have normal address mode meanings:  disallow,
        !           180: **             for example, MOVAW, which does address arithmetic of op1.
        !           181: */
        !           182: 
        !           183: boolean
        !           184: isdyadic(n)
        !           185: NODE * n;                              /* instruction node to test */
        !           186: {
        !           187:     switch(n->op)                      /* dispatch on op code number */
        !           188:     {
        !           189:     case MCOMW:
        !           190:     case MOVZBH:
        !           191:     case MOVZBW:
        !           192:     case MOVZHW:
        !           193:     case ANDW2:
        !           194:     case ORW2:
        !           195:     case XORW2:
        !           196:     case LLSW2:
        !           197:     case LRSW2:
        !           198:     case MOVW:
        !           199:     case MOVBBH:
        !           200:     case MOVBBW:
        !           201:     case MOVBHW:
        !           202:     case MOVTHB:
        !           203:     case MOVTWB:
        !           204:     case MOVTWH:
        !           205:     case MNEGW:
        !           206:     case ADDW2:
        !           207:     case SUBW2:
        !           208:     case MULW2:
        !           209:     case UMULW2:
        !           210:     case DIVW2:
        !           211:     case UDIVW2:
        !           212:     case UMODW2:
        !           213:     case ALSW2:
        !           214:     case ARSW2:
        !           215:        return(true);                   /* all of these are dyadic */
        !           216:     default:
        !           217:        return(false);                  /* others are not */
        !           218:     }
        !           219: }
        !           220: /* istriadic -- is instruction triadic?
        !           221: **
        !           222: ** This routine serves a similar function to isdyadic, except that
        !           223: ** it also returns the related dyadic op code number and string.
        !           224: ** The only instructions included here are the obvious ones.  They
        !           225: ** are assumed to have integer operands (by callers).
        !           226: */
        !           227: 
        !           228: /* define macro to use below */
        !           229: 
        !           230: #define CHANGE(op,new,newst)   case op: *pnewop=new;*pnewopcode=newst;break;
        !           231: 
        !           232: 
        !           233: boolean
        !           234: istriadic(n,pnewop,pnewopcode)
        !           235: NODE * n;                              /* node to test */
        !           236: int * pnewop;                          /* place to put equiv. dyadic # */
        !           237: char ** pnewopcode;                    /* place to put equiv. dyadic string */
        !           238: {
        !           239:     switch (n->op)                     /* dispatch on op code number */
        !           240:     {
        !           241:     CHANGE(ADDW3,ADDW2,"addw2");
        !           242:     CHANGE(SUBW3,SUBW2,"subw2");
        !           243:     CHANGE(MULW3,MULW2,"mulw2");
        !           244:     CHANGE(UMULW3,UMULW2,"umulw2");
        !           245:     CHANGE(DIVW3,DIVW2,"divw2");
        !           246:     CHANGE(UDIVW3,UDIVW2,"udivw2");
        !           247:     CHANGE(MODW3,MODW2,"modw2");
        !           248:     CHANGE(UMODW3,UMODW2,"umodw2");
        !           249:     CHANGE(ALSW3,ALSW2,"alsw2");
        !           250:     CHANGE(ARSW3,ARSW2,"arsw2");
        !           251:     CHANGE(ANDW3,ANDW2,"andw2");
        !           252:     CHANGE(ORW3,ORW2,"orw2");
        !           253:     CHANGE(XORW3,XORW2,"xorw2");
        !           254:     CHANGE(LLSW3,LLSW2,"llsw2");
        !           255:     CHANGE(LRSW3,LRSW2,"lrsw2");
        !           256:     default:                           /* for op codes not found */
        !           257:        return(false);
        !           258:     }
        !           259:     return(true);                      /* found op code */
        !           260: }
        !           261: /* totriadic -- can dyadic be made triadic?
        !           262: **
        !           263: ** This routine checks a dyadic instruction to see if it can be
        !           264: ** made triadic.  If so, it returns the opcode number and string
        !           265: ** for the corresponding triadic.  Totriadic is really the inverse
        !           266: ** of istriadic.
        !           267: */
        !           268: 
        !           269: boolean
        !           270: totriadic(n,pnewop,pnewopcode)
        !           271: NODE * n;                              /* node to test */
        !           272: int * pnewop;                          /* place to put equiv. triadic # */
        !           273: char ** pnewopcode;                    /* place to put equiv. triadic string */
        !           274: {
        !           275:     switch (n->op)                     /* dispatch on op code number */
        !           276:     {
        !           277:     CHANGE(ADDW2,ADDW3,"addw3");
        !           278:     CHANGE(SUBW2,SUBW3,"subw3");
        !           279:     CHANGE(MULW2,MULW3,"mulw3");
        !           280:     CHANGE(UMULW2,UMULW3,"umulw3");
        !           281:     CHANGE(DIVW2,DIVW3,"divw3");
        !           282:     CHANGE(UDIVW2,UDIVW3,"udivw3");
        !           283:     CHANGE(MODW2,MODW3,"modw3");
        !           284:     CHANGE(UMODW2,UMODW3,"umodw3");
        !           285:     CHANGE(ALSW2,ALSW3,"alsw3");
        !           286:     CHANGE(ARSW2,ARSW3,"arsw3");
        !           287:     CHANGE(ANDW2,ANDW3,"andw3");
        !           288:     CHANGE(ORW2,ORW3,"orw3");
        !           289:     CHANGE(XORW2,XORW3,"xorw3");
        !           290:     CHANGE(LLSW2,LLSW3,"llsw3");
        !           291:     CHANGE(LRSW2,LRSW3,"lrsw3");
        !           292:     default:                           /* for op codes not found */
        !           293:        return(false);
        !           294:     }
        !           295:     return(true);                      /* found op code */
        !           296: }
        !           297: /* makelive -- make register live
        !           298: **
        !           299: ** This routine marks a register operand as live.
        !           300: */
        !           301: 
        !           302: void
        !           303: makelive(s,n)
        !           304: char * s;                              /* operand string (to %r0) */
        !           305: NODE * n;                              /* pointer to node to enliven */
        !           306: {
        !           307:     n->nlive |= setreg(s);
        !           308:     return;
        !           309: }
        !           310: 
        !           311: 
        !           312: 
        !           313: /* makedead -- make register dead
        !           314: **
        !           315: ** This routine marks a register operand as dead.
        !           316: */
        !           317: 
        !           318: void
        !           319: makedead(s,n)
        !           320: char * s;                              /* operand string (to %rn) */
        !           321: NODE * n;                              /* pointer to node to kill */
        !           322: {
        !           323:     n->nlive &= ~ setreg(s);
        !           324:     return;
        !           325: }
        !           326: /* isindex -- is operand an index off a register?
        !           327: **
        !           328: ** This routine checks whether an operand string is of the
        !           329: ** form:
        !           330: **
        !           331: **     n(%rn)
        !           332: **
        !           333: ** and whether it uses a designated register.
        !           334: **
        !           335: ** Actually, it cheats:  it just checks for an initial digit or sign followed
        !           336: ** by a (.  In fact the ( test is a cheat, because we just check to see
        !           337: ** if there's a ( in the string.
        !           338: */
        !           339: 
        !           340: boolean
        !           341: isindex(s,r)
        !           342: char * s;                              /* operand string to test */
        !           343: char * r;                              /* register operand string to check
        !           344:                                        ** for
        !           345:                                        */
        !           346: 
        !           347: {
        !           348:     char * strchr();
        !           349: 
        !           350:     if(*s == '*')
        !           351:                s++;
        !           352:     return(
        !           353:                usesreg(s,r)
        !           354:            &&  (isdigit(*s) || *s == '-') /* could be leading sign, too */
        !           355:            &&  strchr(s,'(') != (char *) 0
        !           356:            );
        !           357: }
        !           358: /* ismove -- is instruction a move?
        !           359: **
        !           360: ** This routine determines whether an instruction is a move-type.
        !           361: ** There is a multiplicity of move instructions which copy, zero-
        !           362: ** or sign-extend, and truncate.  This routine returns the natural
        !           363: ** size of the source and destination operands.
        !           364: */
        !           365: 
        !           366: boolean
        !           367: ismove(n,srcsize,dstsize)
        !           368: NODE * n;                              /* pointer to instruction node */
        !           369: int * srcsize;                         /* place to put size of source
        !           370:                                        ** operand (in bytes)
        !           371:                                        */
        !           372: int * dstsize;                         /* place to put size of destination */
        !           373: {
        !           374:     register int srctemp = 1;          /* temporary source size */
        !           375:     register int dsttemp = 4;          /* temporary destination size */
        !           376: /* Initial values chosen on basis of most common value of each. */
        !           377: 
        !           378:     switch (n->op)                     /* dispatch on op-code number */
        !           379:     {
        !           380:     case MOVZBH:
        !           381:                        dsttemp = 2;    break;
        !           382:     case MOVZBW:
        !           383:                                        break;
        !           384:     case MOVZHW:
        !           385:        srctemp = 2;                    break;
        !           386: 
        !           387:     case MOVB:
        !           388:                        dsttemp = 1;    break;
        !           389:     case MOVH:
        !           390:        srctemp = 2;    dsttemp = 2;    break;
        !           391:     case MOVW:
        !           392:        srctemp = 4;                    break;
        !           393: 
        !           394:     case MOVBBH:
        !           395:                        dsttemp = 2;    break;
        !           396:     case MOVBBW:
        !           397:                                        break;
        !           398:     case MOVBHW:
        !           399:        srctemp = 2;                    break;
        !           400: 
        !           401:     case MOVTHB:
        !           402:        srctemp = 2;    dsttemp = 1;    break;
        !           403:     case MOVTWB:
        !           404:        srctemp = 4;    dsttemp = 1;    break;
        !           405:     case MOVTWH:
        !           406:        srctemp = 4;    dsttemp = 2;    break;
        !           407:     default:
        !           408:        return(false);                  /* not a move instruction */
        !           409:     }
        !           410:     *srcsize = srctemp;                        /* copy out correct values */
        !           411:     *dstsize = dsttemp;
        !           412:     return(true);                      /* found a move */
        !           413: }
        !           414: /* iszoffset -- is operand zero offset from register
        !           415: **
        !           416: ** This routine determines whether a given operand is an indexed
        !           417: ** operation from a designated register, where the index is zero.
        !           418: */
        !           419: 
        !           420: boolean
        !           421: iszoffset(operand,reg)
        !           422: register char * operand;               /* operand string */
        !           423: char * reg;                            /* register string */
        !           424: {
        !           425: 
        !           426: /* We use a quick and dirty strategy here:  we test the operand for
        !           427: ** zero, followed by (, with matching register numbers in the right
        !           428: ** place.  We assume register designations are "%rn".
        !           429: */
        !           430: 
        !           431:     return(
        !           432:                *operand == '0'
        !           433:            &&  *(operand+1) == '('
        !           434:            &&  *(operand+4) == *(reg+2)
        !           435:          );
        !           436: }
        !           437: /* exchange -- exchange node and successor
        !           438: **
        !           439: ** This routine reverses the linkages of two nodes so the first is
        !           440: ** the second and the second is the first.
        !           441: */
        !           442: 
        !           443: void
        !           444: exchange(first)
        !           445: NODE * first;                          /* pointer to first of two nodes */
        !           446: {
        !           447: 
        !           448: /* This can probably be done with fewer temporaries, but it's a lot
        !           449: ** easier to understand what's going on this way....
        !           450: */
        !           451: 
        !           452:     NODE * prev = first->back;         /* predecessor of first node */
        !           453:     NODE * second = first->forw;       /* second node of pair to exchange */
        !           454:     NODE * next = second->forw;                /* successor of second node */
        !           455: 
        !           456:     prev->forw = second;               /* second will now be first */
        !           457:     second->back = prev;
        !           458: 
        !           459:     first->forw = next;                        /* successor of old first is now
        !           460:                                        ** 'next'
        !           461:                                        */
        !           462:     next->back=first;                  /* 'next's' predecessor now 'first' */
        !           463: 
        !           464:     second->forw = first;
        !           465:     first->back = second;              /* re-link connection of node pair */
        !           466: 
        !           467:     return;
        !           468: }
        !           469: /* doindirect -- resolve indirect references
        !           470: **
        !           471: ** This routine changes variable references of the form
        !           472: **     0(%rn)
        !           473: ** to
        !           474: **     *var
        !           475: ** where possible.  Its purpose is to make it possible to discard a
        !           476: ** register load.
        !           477: **
        !           478: ** Here's the scenario:  we're handed an instruction, the name of the
        !           479: ** register whose zero-index use we want to change, and the real location
        !           480: ** of the variable.  For example, in the sequence
        !           481: **
        !           482: **     movw xyz,%r0
        !           483: **     addw2 0(%r0),%r1
        !           484: **
        !           485: ** the instruction we would be handed is the addw2, the register would be
        !           486: ** %r0, and the real location of the variable is 'xyz'.
        !           487: **
        !           488: ** Complications:
        !           489: **     1.  The register must be dead after the instruction.
        !           490: **     2.  We want to change all such references in the instruction.
        !           491: **     3.  If there are any other uses of the register than a zero
        !           492: **             index, like actually using the register contents or
        !           493: **             using an index other than zero (e.g., 4(%r0)), we
        !           494: **             can't make the transformation, since we're going to
        !           495: **             eliminate the preceding register load.
        !           496: **     4.  ... except that if the destination of a triadic instruction or
        !           497: **             move is the register it's safe to proceed.
        !           498: **
        !           499: ** One, possibly unsafe assumption:
        !           500: **     The algorithm assumes that unused operands in an instruction (like
        !           501: **     operands 3 and 4 in a dyadic) are always NULL.  We also assume that
        !           502: **     an instruction has a "destination" (returned by 'dst') if and only
        !           503: **     if it can alter something.  We further assume that the destination
        !           504: **     is always the last operand.
        !           505: */
        !           506: 
        !           507: boolean                                        /* true if the transformation
        !           508:                                        ** was made
        !           509:                                        */
        !           510: doindirect(n,reg,repl)
        !           511: NODE * n;                              /* instruction node to examine */
        !           512: char * reg;                            /* register (string) to look for */
        !           513: char * repl;                           /* operand string to use */
        !           514: {
        !           515:     boolean first = true;              /* if examining first real operand */
        !           516:     int indmask = 0;                   /* will have bits set telling which
        !           517:                                        ** operands to change
        !           518:                                        */
        !           519:     int i;                             /* loop index */
        !           520:     char * operand;                    /* current operand */
        !           521:     int src,dest;                      /* for ismove (but unused) */
        !           522: /* Begin:  check whether transformation can be made, note which operands
        !           523: ** to change if so.
        !           524: */
        !           525: 
        !           526:     if (
        !           527:            isret(n)                    /* will show register dead, which
        !           528:                                        ** will confuse us
        !           529:                                        */
        !           530:        ||  ! (
        !           531:                  isdead(reg,n)         /* reg must be dead after n */
        !           532:               || ( ismove(n,&src,&dest) && samereg(n->op2,reg) )
        !           533:               )                        /* unless set by this inst. as move */
        !           534:        ||  *repl == '*'                /* can't do it if replacement is
        !           535:                                        ** already an indirect...
        !           536:                                        */
        !           537:        ||  *repl == '&'                /* or an immediate */
        !           538:        )
        !           539:        return(false);                  /* can't do it */
        !           540: 
        !           541: /* Now scan operands for things that can't be transformed.  We do this
        !           542: ** backward from higher numbered operands on the assumption that a
        !           543: ** destination, which we treat differently, is the highest numbered
        !           544: ** non-null operand.
        !           545: */
        !           546: 
        !           547:     for ( i = MAXOPS; i > 0; i-- )
        !           548:     {
        !           549:        int opn;                        /* op code number in istriadic */
        !           550:        char * opst;                    /* op code string in istriadic */
        !           551: 
        !           552:        if ( (operand = n->ops[i]) != NULL )
        !           553:        {                               /* found an operand */
        !           554:            if (iszoffset(operand,reg)) /* this is what we want! */
        !           555:                indmask |= 1<<i;        /* remember where it is */
        !           556:            
        !           557:            /* otherwise can only use register if this is the last
        !           558:            ** operand (but the first we'll find) and the instruction
        !           559:            ** is triadic
        !           560:            */
        !           561: 
        !           562:            else if (
        !           563:                         ! (    samereg(operand,reg)
        !           564:                            &&  first
        !           565:                            &&  (
        !           566:                                    istriadic(n,&opn,&opst)
        !           567:                                 || ismove(n,&src,&dest)
        !           568:                                )
        !           569:                            )
        !           570:                     &&  usesreg(operand,reg)
        !           571:                     )
        !           572:                return(false);          /* bad use of register */
        !           573:            
        !           574:            first = false;              /* no longer looking at first (last)
        !           575:                                        ** operand
        !           576:                                        */
        !           577:        }
        !           578:     }
        !           579:     /* Reaching here, we have successfully scanned all operands without
        !           580:     ** finding any register references that violate the required conditions.
        !           581:     */
        !           582: 
        !           583:     if (indmask == 0)                  /* if no register references... */
        !           584:        return(false);                  /* say we didn't change anything */
        !           585:     if ( !isiros(repl) ) return( false ); /* check for mmio */
        !           586: /* Now we're ready to do the actual transformations.  If the replacement
        !           587: ** operand is a register reference, we create a new operand reference
        !           588: ** of the form:
        !           589: **     0(reg) --> 0(repl)
        !           590: **
        !           591: ** Otherwise we have a vanilla operand.  Rewrite it as
        !           592: **
        !           593: **     0(reg) --> *repl
        !           594: */
        !           595: 
        !           596:     {                                  /* for some more variables */
        !           597:        char * indstring;               /* new operand string */
        !           598:        int extra;                      /* number of extra chars in xform */
        !           599:        char * format;                  /* sprintf format string for xform */
        !           600: 
        !           601:        if (isreg(repl))                /* replacement is also reference */
        !           602:        {
        !           603:            format = "0(%s)";           /* to form 0(repl) */
        !           604:            extra = 3;                  /* for 0 ( ) */
        !           605:        }
        !           606:        else
        !           607:        {
        !           608:            format = "*%s";             /* rewrite as *repl */
        !           609:            extra = 1;                  /* prepend * only */
        !           610:        }
        !           611: 
        !           612:        indstring = getspace(strlen(repl) + extra + 1);
        !           613:                                        /* allocate space + 1 for null */
        !           614:        (void) sprintf(indstring,format,repl);
        !           615:                                        /* build replacement */
        !           616:        
        !           617:        wchange();                      /* Finally!  About to make changes */
        !           618: 
        !           619:        /* loop through operands, replacing ones whose bit is set in mask */
        !           620: 
        !           621:        for ( i = MAXOPS; i > 0; i-- )
        !           622:        {
        !           623:            if ( (indmask & (1<<i)) != 0)
        !           624:                n->ops[i] = indstring;  /* stick in replacement string */
        !           625:        }
        !           626: 
        !           627:        return(true);                   /* say we changed stuff */
        !           628:     } /* end extra block */
        !           629: }
        !           630: /* isnumlit -- is operand a numeric literal
        !           631: **
        !           632: ** This routine tests operand strings for the form
        !           633: **
        !           634: **     &[-]n
        !           635: **
        !           636: ** where n is a positive integer.
        !           637: */
        !           638: 
        !           639: boolean
        !           640: isnumlit(s)
        !           641: char * s;                              /* pointer to operand string */
        !           642: {
        !           643:     if (*s++ != '&')
        !           644:        return(false);
        !           645:     
        !           646:     if (*s == '-')                     /* sign okay */
        !           647:        s++;
        !           648:     
        !           649:     while (*s != '\0')                 /* check for all digits */
        !           650:        if ( ! isdigit(*s++) )
        !           651:            return(false);
        !           652:     
        !           653:     return(true);                      /* passed all tests */
        !           654: }
        !           655: /* usesvar -- does first operand use second?
        !           656: **
        !           657: ** This routine is a generalization of "usesreg":  it returns true
        !           658: ** if the first operand uses the second.  An example is
        !           659: ** v1 = "*p", v2 = "p".  v1 uses the contents of v2.
        !           660: */
        !           661: 
        !           662: boolean
        !           663: usesvar(v1,v2)
        !           664: char * v1;                             /* using operand */
        !           665: char * v2;                             /* used operand */
        !           666: {
        !           667:     if (isreg(v2) && usesreg(v1,v2))
        !           668:        return(true);                   /* handle register case specially */
        !           669: 
        !           670:     if (*v1 == '*')                    /* check for initial indirect */
        !           671:        v1++;
        !           672: 
        !           673:     return(strcmp(v1,v2) == 0);                /* result is result of compare */
        !           674: }
        !           675: 
        !           676: 
        !           677: /* These routines try to preserve the line number information.
        !           678:    The criterion for saving or discarding line number information is
        !           679:    that the state of the machine from a C point of view should be the
        !           680:    same at any given line both before and after the optimization.
        !           681:    If it would not be then the line number is deleted.
        !           682:    The exceptions to the above are that the state of the condition codes 
        !           683:    and of dead registers is ignored. 
        !           684:    
        !           685:        May 1983 */
        !           686: 
        !           687: /* NOTE: All instruction nodes that these routines assume will be tossed
        !           688:          have their uniqids set to IDVAL.  For example, in the merges,
        !           689:          the uniqids of the original instructions are set to IDVAL
        !           690:          and then the uniqid of the resultant instruction is computed.
        !           691:          This has the effect of setting the uniqid of the instruction 
        !           692:          not corresponding to the resultant to IDVAL. This fact is used 
        !           693:          in some instances where lnmrginst2 is called -- see w2opt.c */
        !           694: 
        !           695: /* delete instruction -- save line number
        !           696:        if the instruction below has no line number or has a line number
        !           697:        greater than the present instruction, the present number 
        !           698:        is transfered down */
        !           699: 
        !           700: void
        !           701: ldelin(nodep)
        !           702: NODE * nodep;
        !           703: {
        !           704:        if(nodep->uniqid == IDVAL)
        !           705:                return;
        !           706: 
        !           707:        if(nodep->forw != &ntail && 
        !           708:           (nodep->forw->uniqid > nodep->uniqid 
        !           709:                 || nodep->forw->uniqid == IDVAL))
        !           710:                nodep->forw->uniqid = nodep->uniqid;
        !           711: 
        !           712:        nodep->uniqid = IDVAL;
        !           713: 
        !           714: }
        !           715: 
        !           716: /* more conservative version of lndelinst that does not overwrite
        !           717:        line numbers below */
        !           718: void
        !           719: ldelin2(nodep)
        !           720: NODE *nodep;
        !           721: {
        !           722:        if(nodep == IDVAL)
        !           723:                return;
        !           724: 
        !           725:        if(nodep->forw != &ntail && nodep->forw->uniqid == IDVAL)
        !           726:                nodep->forw->uniqid = nodep->uniqid;
        !           727: 
        !           728:        nodep->uniqid = IDVAL;
        !           729: 
        !           730: }
        !           731: 
        !           732: 
        !           733: /* exchange instructions
        !           734:        The line number of the first instruction, if any, is given to the
        !           735:        second instruction.  The line number of the second instruction is 
        !           736:        deleted. */
        !           737: void
        !           738: lexchin(nodep1,nodep2)
        !           739: NODE *nodep1, *nodep2;
        !           740: {
        !           741:        if(nodep1->uniqid != IDVAL) {
        !           742:                nodep2->uniqid = nodep1->uniqid;
        !           743:                nodep1->uniqid = IDVAL;
        !           744:        }
        !           745:        else {
        !           746:                nodep2->uniqid = IDVAL;
        !           747:        }
        !           748: }
        !           749: 
        !           750: 
        !           751: /* merge instructions - case 1
        !           752:        The result instruction is given the line number of the
        !           753:        top instruction, if it exists, or else it is given the line
        !           754:        number of the bottom instruction. */
        !           755: void
        !           756: lmrgin1(nodep1,nodep2,resnode)
        !           757: NODE *nodep1, *nodep2, *resnode;
        !           758: {
        !           759:        IDTYPE val1, val2;
        !           760: 
        !           761:        val1 = nodep1->uniqid;
        !           762:        val2 = nodep2->uniqid;
        !           763: 
        !           764:        nodep1->uniqid = nodep2->uniqid = IDVAL;
        !           765: 
        !           766:        if(val1 != IDVAL)
        !           767:                resnode->uniqid = val1;
        !           768:        else 
        !           769:                resnode->uniqid = val2;
        !           770: 
        !           771: }
        !           772: 
        !           773: 
        !           774: /* instruction merge - case 2
        !           775:        The resultant instruction is given the line number of the
        !           776:        top instruction, if it exists, else it is not given a line number */
        !           777: void
        !           778: lmrgin2(nodep1,nodep2,resnode)
        !           779: NODE *nodep1, *nodep2, *resnode;
        !           780: {
        !           781:        IDTYPE val1;
        !           782: 
        !           783:        val1 = nodep1->uniqid;
        !           784: 
        !           785:        nodep1->uniqid = nodep2->uniqid = IDVAL;
        !           786: 
        !           787:        resnode->uniqid = val1;
        !           788: 
        !           789: }
        !           790: 
        !           791: /* instruction merge - case 3
        !           792:        The resultant instruction is given the line number of the first
        !           793:        instruction, if it exists. The instruction below the pair to be 
        !           794:        merged is given the line number of the second instruction, 
        !           795:        if it exists */
        !           796: void
        !           797: lmrgin3(nodep1,nodep2,resnode)
        !           798: NODE *nodep1, *nodep2, *resnode;
        !           799: {
        !           800:        IDTYPE val1;
        !           801: 
        !           802:        ldelin2(nodep2);
        !           803: 
        !           804:        val1 = nodep1->uniqid;
        !           805: 
        !           806:        nodep1->uniqid = nodep2->uniqid = IDVAL;
        !           807: 
        !           808:        resnode->uniqid = val1;
        !           809: }
        !           810: 
        !           811: /* isiros  --  is operand either immediate, register or on stack?
        !           812: **
        !           813: ** This routine returns true if the the operand 
        !           814: ** pointed to by its argument has address mode
        !           815: **
        !           816: **             immediate,
        !           817: **             register, or
        !           818: **             offset from a stack pointer (fp, ap, or sp).
        !           819: **
        !           820: ** This test is provided for checking operands to see whether they
        !           821: ** can be memory mapped i/o references.
        !           822: */
        !           823: 
        !           824: boolean
        !           825: isiros( op )
        !           826: char *op;
        !           827: {
        !           828:        return( *op == '&' ||
        !           829:                *op == '%' ||
        !           830:                ( *op != '*' && 
        !           831:                        ( usesreg( op, "%fp" ) ||
        !           832:                        usesreg( op, "%ap" ) ||
        !           833:                        usesreg( op, "%sp" ) 
        !           834:                        ) 
        !           835:                )
        !           836:              );
        !           837: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.