Annotation of researchv9/cmd/sun/pcc/optim2.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char sccsid[] = "@(#)optim2.c 1.1 86/02/03 Copyr 1985 Sun Micro";
                      3: #endif
                      4: 
                      5: /*
                      6:  * Copyright (c) 1985 by Sun Microsystems, Inc.
                      7:  */
                      8: 
                      9: #include "cpass2.h"
                     10: 
                     11: /* 
                     12:  * routines to detect and to deal with doubly-indexed OREGs.
                     13:  * Initially, these were all stolen from the vax code.
                     14:  */
                     15: 
                     16: base( p ) 
                     17:     register NODE *p; 
                     18: {
                     19:     register int o = p->in.op;
                     20:     register v,maxoff;
                     21:     register NODE *lp,*rp;
                     22: 
                     23:     if ( BTYPE(p->in.type) == DOUBLE )
                     24:        maxoff = 123;
                     25:     else
                     26:        maxoff = 127;
                     27:     if ( o==REG && isbreg( p->tn.rval ))
                     28:        return( p->tn.rval );
                     29:     lp = p->in.left;
                     30:     rp = p->in.right;
                     31:     if ((o==PLUS || o==MINUS) 
                     32:        && lp->in.op==REG  && isbreg( lp->tn.rval )
                     33:        && rp->in.op==ICON && rp->in.name[0] == '\0'
                     34:        && (use68020 || (v=rp->tn.lval) <= maxoff && v >= -128)
                     35:     )
                     36:        return( lp->tn.rval );
                     37:     return( -1 );
                     38: }
                     39: 
                     40: offset( p, notused ) 
                     41:     register NODE *p;
                     42:     int notused; 
                     43: {
                     44:     if ( p->in.op==REG ) {
                     45:        if ( p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type) ) {
                     46:            return( p->tn.rval );
                     47:        }
                     48:        if ( p->in.type==SHORT ) {
                     49:            /*
                     50:             * result is: short index flag + xreg
                     51:             */
                     52:            return( (1<<8) + p->tn.rval );
                     53:        }
                     54:     }
                     55:     if (use68020) {
                     56:        /*
                     57:         * test for scaled indexing
                     58:         */
                     59:        int count;
                     60:        NODE *lp = p->in.left;
                     61:        NODE *rp = p->in.right;
                     62:        if ( p->in.op==LS && lp->in.op==REG 
                     63:        && (lp->in.type==INT || lp->in.type==UNSIGNED || lp->in.type == SHORT )
                     64:        && (rp->in.op==ICON && rp->in.name[0]=='\0')
                     65:        && (count = rp->tn.lval) >= 0 && count <= 3 ) {
                     66:            int scale = (1 << count);
                     67:            if ( p->in.type == SHORT ) {
                     68:                /*
                     69:                 * result is: short index flag + scale factor + xreg
                     70:                 */
                     71:                return( (1<<8) + (scale<<4) + lp->tn.rval );
                     72:            }
                     73:            /*
                     74:             * result is: scale factor + xreg
                     75:             */
                     76:            return( (scale<<4) + lp->tn.rval );
                     77:        }
                     78:     }
                     79:     return( -1 );
                     80: }
                     81: 
                     82: makeor2( p, basenode, breg, scale_plus_xreg )
                     83:     register NODE *p;          /* node to be rewritten */
                     84:     register NODE *basenode;   /* base node (usually a ptr) */
                     85:     int breg;                  /* base register */
                     86:     int scale_plus_xreg;       /* scale factor + index register */
                     87: {
                     88:     register NODE *t;  /* from which tn.lval, tn.name are obtained */
                     89:     register int i;
                     90:     NODE *f;
                     91: 
                     92:     register flags;
                     93:     int scale, xreg, shortx, ibit;
                     94: 
                     95:     ibit = 0;
                     96:     shortx= (scale_plus_xreg >> 8) & 1;
                     97:     scale = (scale_plus_xreg >> 4) & 017;
                     98:     xreg  = scale_plus_xreg & 017;
                     99: 
                    100:     p->in.op = OREG;
                    101:     f = p->in.left;    /* have to free this subtree later */
                    102: 
                    103:     /* init base */
                    104:     switch (basenode->in.op) {
                    105:            case ICON:
                    106:            case REG:
                    107:            case OREG:
                    108:                    t = basenode;
                    109:                    break;
                    110: 
                    111:            case MINUS:
                    112:                    basenode->in.right->tn.lval = -basenode->in.right->tn.lval;
                    113:            case PLUS:
                    114:                    t = basenode->in.right;
                    115:                    break;
                    116: 
                    117:            case INCR:
                    118:            case ASG MINUS:
                    119:                    t = basenode->in.left;
                    120:                    break;
                    121: 
                    122:            case UNARY MUL:
                    123:                    t = basenode->in.left->in.left;
                    124:                    break;
                    125: 
                    126:            default:
                    127:                    cerror("illegal makeor2");
                    128:     }
                    129: 
                    130:     p->tn.lval = t->tn.lval;
                    131: #ifndef FLEXNAMES
                    132:     for(i=0; i<NCHNAM; ++i)
                    133:            p->in.name[i] = t->in.name[i];
                    134: #else
                    135:     p->in.name = t->in.name;
                    136: #endif
                    137: 
                    138:     /*
                    139:      * For 68020, R2UPK3 encodes the following data:
                    140:      *     int shortx:1; short index
                    141:      *     int ibit:1; memory indirect mode (unused)
                    142:      *     int scale:4; scale factor (1,2,4,8)
                    143:      * For 68010, only the short index flag is encoded.
                    144:      */
                    145:     R2PACKFLGS(flags,shortx,ibit,scale);
                    146:     p->tn.rval = R2PACK( breg, xreg, flags );
                    147: 
                    148:     tfree(f);
                    149:     return;
                    150: }
                    151: 
                    152: 
                    153: /*
                    154:  * Multiply a value by a constant.
                    155:  * Multiplies are slow on the 68010, so do some shifting and
                    156:  * adding here.
                    157:  * For each 1-bit in the constant the value is shifted
                    158:  * by n where 2**n equals the bit.
                    159:  * The shifted value is then added into an accumulated value.
                    160:  * One tricky part is for runs of three or more consecutive
                    161:  * bits.  For a number like 7, it is cheaper to calculate
                    162:  * (8 - 1), than it is (3 + 2 + 1)
                    163:  */
                    164: conmul(p, cookie)
                    165:        register NODE   *p;
                    166: {
                    167:        register const;         /* The constant value */
                    168:        register int    curpos; /* Position of last one bit */
                    169:        register int    power;  /* The bit being tested */
                    170:        int     run;            /* Num of consecutive one bits */
                    171:        int     nbits;          /* Num of bits since the last one bit */
                    172:        int     negconst;       /* Is the constant <0 ? */
                    173:        char *  destreg;        /* name of "AL" register */
                    174:        char *  helper;         /* name of "A1" register */
                    175:        int     helperreg;
                    176:        TWORD   ltype;
                    177:        char    typechar;
                    178:        int     t;
                    179: 
                    180:        /*
                    181:         * first determine how many instructions we will need to do
                    182:         * it in line. Cost estimator is: # single bits + 2* # of multi bit
                    183:         * runs. If this exceeds 5, then it is more compact to use a 
                    184:         * multiply instruction or routine.
                    185:         */
                    186:        const = p->in.right->tn.lval;
                    187:        if (const<0){
                    188:            negconst = 1;
                    189:            const = - const;
                    190:        } else 
                    191:            negconst = 0;
                    192:        run = const & (const>>1); /* each run shortened by one bit */
                    193:        run = cntbits( run ^ (run>>1) ) + (run&1); /* 2*# multibit runs */
                    194:        nbits = cntbits( const ^ (const>>1)) +(const&1); /* 2* #total runs*/
                    195:        run += nbits; /* 2* estimator */
                    196:        ltype = p->in.left->in.type;
                    197:        if ((ttype(ltype,TUCHAR|TCHAR|TUSHORT|TSHORT) && run>6) || (run > 10)){
                    198:            /* old-fashioned way */
                    199:            if (tshape( p->in.right, SSCON ) ){
                    200:                if (negconst){
                    201:                    expand( p->in.left, INAREG|INTAREG, "       negZB   AL\nZv");
                    202:                    p->in.right->tn.lval = const;
                    203:                }
                    204:                if (ttype(ltype, TSHORT|TCHAR)){
                    205:                    expand( p, cookie, "        muls    #CR,AL\nZv");
                    206:                } else if (ttype(ltype, TUSHORT|TUCHAR)){
                    207:                    expand( p, cookie, "        mulu    #CR,AL\n");
                    208:                } else if (use68020) {
                    209:                    if (ISUNSIGNED(p->in.type)) {
                    210:                        expand( p, cookie, "    mulul   #CR,AL\n");
                    211:                    } else {
                    212:                        expand( p, cookie, "    mulsl   #CR,AL\nZv");
                    213:                    }
                    214:                } else {
                    215: 
                    216:                    expand( p, cookie,
                    217:                        "\tmovl\tAL,A1\n\tswap\tA1\n\tmulu\t#CR,AL\n");
                    218:                    fputs( ttype(ltype, TULONG|TUNSIGNED|TUCHAR|TPOINT)
                    219:                        ? "\tmulu" : "\tmuls", stdout);
                    220:                    expand( p, cookie, 
                    221:                        "\t#CR,A1\n\tswap\tA1\n\tclrw\tA1\n\taddl\tA1,AL\nZv");
                    222:                }
                    223:            } else if (use68020) {
                    224:                if (ISUNSIGNED(p->in.type)) {
                    225:                    expand( p, cookie, "        mulul   #CR,AL\n");
                    226:                } else {
                    227:                    expand( p, cookie, "        mulsl   #CR,AL\nZv");
                    228:                }
                    229:            } else {
                    230:                order( p->in.right, INTAREG );
                    231:                order( p, INAREG|INTAREG );
                    232:            }
                    233:            return;
                    234:        }
                    235:        typechar = (((t=p->in.type)==CHAR)||t==UCHAR) ? 'b' 
                    236:                 :  (t==SHORT||t==USHORT) ? 'w'
                    237:                 : 'l';
                    238:        /*
                    239:         * if the result type is larger than the operand type, we must expand
                    240:         * the operand before doing the operation.
                    241:         */
                    242:        switch( p->in.left->tn.type){
                    243:        case UCHAR: 
                    244:        case USHORT: 
                    245:                if (typechar=='b' || typechar=='w') break;
                    246:                expand( p->in.left, INAREG|INTAREG, "   andl    #0xffff,AL\n");
                    247:                break;
                    248:        case CHAR:
                    249:        case SHORT: 
                    250:                if (typechar=='b' || typechar=='w') break;
                    251:                expand( p->in.left, INAREG|INTAREG, "   extl    AL\n");
                    252:                break;
                    253:        }
                    254:        p->in.left->tn.type = t;
                    255:        nbits = ffs( const )-1; 
                    256:        power = 0;
                    257:        helperreg = resc[0].tn.rval ;
                    258:        helper = rnames[ helperreg ];
                    259:        destreg  = rnames[ p->in.left->tn.rval];
                    260:        if (negconst){
                    261:            expand( p->in.left, INAREG|INTAREG, "       negZB   AL\nZv");
                    262:        }
                    263:        if (nbits>0){
                    264:            shiftreg( nbits, destreg, helperreg , 1, typechar, t);
                    265:            const >>= nbits;
                    266:        }
                    267:        if (const==1) return;
                    268:        /* 
                    269:         * the first time is special (ask Ann Landers). If it is a run,
                    270:         * then we move, negate, shift add. Otherwise, we don't negate.
                    271:         */
                    272:        run = ffs( ~const) -1;
                    273:        expand(p, cookie, "     movZB   AL,A1\n");
                    274:        switch (run){
                    275:        case 2:
                    276:                shiftreg( 1, helper, -1, 1, typechar, t);
                    277:                expand( p, cookie, "\taddZB\tA1,AL\nZv");
                    278:                /* fall through */
                    279:        case 1: 
                    280:                curpos = 0;
                    281:                break;
                    282:        default:
                    283:                shiftreg( run, helper, -1, 1, typechar, t);
                    284:                expand( p->in.left, INAREG|INTAREG, "   negZB   AL\nZv");
                    285:                expand( p, cookie, "\taddZB\tA1,AL\nZv");
                    286:                curpos = 1;
                    287:                break;
                    288:        }
                    289:        for ( const >>= run; const >>= (power=ffs(const))-1; const >>= run){
                    290:                run = ffs(~const)-1;
                    291:                switch(run) {
                    292:                case 1:
                    293:                        shiftreg( power-curpos, helper, -1, 1, typechar, t);
                    294:                        expand( p, cookie, "\taddZB\tA1,AL\nZv");
                    295:                        curpos = 0;
                    296:                        break;
                    297:                case 2:
                    298:                        shiftreg( power-curpos, helper, -1, 1, typechar, t);
                    299:                        expand( p, cookie, "\taddZB\tA1,AL\nZv");
                    300:                        shiftreg( 1, helper, -1, 1, typechar, t);
                    301:                        expand( p, cookie, "\taddZB\tA1,AL\nZv");
                    302:                        curpos = 0;
                    303:                        break;
                    304:                default:
                    305:                        shiftreg( power-curpos, helper, -1, 1, typechar, t);
                    306:                        expand( p, cookie, "\tsubZB\tA1,AL\nZv");
                    307:                        shiftreg( run, helper, -1, 1, typechar, t);
                    308:                        expand( p, cookie, "\taddZB\tA1,AL\nZv");
                    309:                        curpos = 1;
                    310:                        break;
                    311:                }
                    312:        }
                    313: }
                    314: 
                    315: /*
                    316:  * divide a signed number by a constant.
                    317:  * divides are really slow on this machine, so we really want to avoid them.
                    318:  * the only interesting case is divide by power-of-two. Others, we really
                    319:  * have to do the division.
                    320:  */
                    321: void
                    322: condiv( p, cookie ) register NODE *p;
                    323: {
                    324:     char sizechar;
                    325:     register const;
                    326:     register TWORD ltype;
                    327:     int lab1f;
                    328:     char * lname = rnames[p->in.left->tn.rval];
                    329:     const = p->in.right->tn.lval;
                    330:     ltype = p->in.left->tn.type;
                    331:     if (const & (const-1)){
                    332:        /* too bad -- not a positive power of two */
                    333:        switch (ltype){
                    334:        case CHAR:
                    335:                print_str_str_nl( "     extw    ", lname );
                    336:                /* fall through */
                    337:        case SHORT:
                    338:                print_str_str_nl( "     extl    ", lname );
                    339:                printf( "       divs    #%d,%s\n", const, lname);
                    340:                break;
                    341:        default:
                    342:                if (use68020) {
                    343:                        printf( "       divsl   #%d,%s\n",
                    344:                                const, lname);
                    345:                } else {
                    346:                        order( p->in.right, INTAREG );
                    347:                        order( p, INTAREG );
                    348:                }
                    349:                break;
                    350:        }
                    351:        return;
                    352:     }
                    353:     switch (ltype){
                    354:     case CHAR: sizechar = 'b'; break;
                    355:     case SHORT: sizechar = 'w'; break;
                    356:     default: sizechar = 'l';
                    357:     }
                    358:     lab1f = getlab();
                    359:     printf("   tst%c   %s\n    jge     L%d\n", sizechar, lname, lab1f);
                    360:     print_str((const >= 1 && const <= 8) ? "   addq" : "       add");
                    361:     printf("%c #%d,%s\n", sizechar, const-1, lname );
                    362:     deflab(lab1f);
                    363:     const = ffs(const)-1;
                    364:     /* like shiftreg(), but for right, arithmetic shifts */
                    365:     while (const > 0){
                    366:        if (const> 8){
                    367:            printf("    asr%c   #8,%s\n", sizechar, lname );
                    368:            const -= 8;
                    369:        } else {
                    370:            printf("    asr%c   #%d,%s\n", sizechar, const, lname );
                    371:            const = 0;
                    372:        }
                    373:     }
                    374:     return;
                    375: }
                    376: 
                    377: 
                    378: /*
                    379:  * remainder a signed number by a constant.
                    380:  * remainders are really slow on this machine, so we really want to avoid them.
                    381:  * the only interesting case is powers-of-two. Others, we really
                    382:  * have to do the division.
                    383:  */
                    384: void
                    385: conrem( p, cookie ) register NODE *p;
                    386: {
                    387:     char sizechar, opchar;
                    388:     register const;
                    389:     register TWORD ltype;
                    390:     char * lname = rnames[p->in.left->tn.rval];
                    391:     char * helper, u;
                    392:     int lab1f, lab2f;
                    393:     const = p->in.right->tn.lval;
                    394:     ltype = p->in.left->tn.type;
                    395:     if (const & (const-1)){
                    396:        /* too bad -- not a positive power of two */
                    397:        switch (ltype){
                    398:        case CHAR:
                    399:                print_str_str_nl( "     extw    ", lname );
                    400:                /* fall through */
                    401:        case SHORT:
                    402:                print_str_str_nl( "     extl    ", lname );
                    403:                printf( "       divs    #%d,%s\n", const, lname);
                    404:                print_str_str_nl( "     swap    ", lname );
                    405:                break;
                    406:        case UCHAR:
                    407:                print_str_str_nl("      andl    #0xff,", lname );
                    408:                goto divu;
                    409:        case USHORT:
                    410:                print_str_str_nl("      andl    #0xffff,", lname );
                    411:        divu:   printf("        divu    #%d,%s\n", const, lname);
                    412:                print_str_str_nl("      swap    ", lname);
                    413:                break;
                    414:        default:
                    415:                if (use68020) {
                    416:                        helper = rnames[resc[0].tn.rval];
                    417:                        printf("        %s      #%d,%s:%s\n",
                    418:                                (ISUNSIGNED(ltype)? "divull" : "divsll"),
                    419:                                const, helper, lname);
                    420:                        printf("        movl    %s,%s\n", helper, lname);
                    421:                } else {
                    422:                        order( p->in.right, INTAREG );
                    423:                        order( p, INTAREG );
                    424:                }
                    425:                break;
                    426:        }
                    427:        return;
                    428:     }
                    429:     helper = rnames[resc[0].tn.rval];
                    430:     u = 0;
                    431:     switch (ltype){
                    432:     case UCHAR: u = 1; /* fall through */
                    433:     case CHAR: sizechar = 'b'; opchar = 'w'; break;
                    434:     case USHORT: u = 1; /* fall through */
                    435:     case SHORT: sizechar = 'w'; opchar = 'w'; break;
                    436:     case UNSIGNED: u = 1; /* fall through */
                    437:     default: sizechar = 'l'; opchar = 'l';
                    438:     }
                    439:     if (!u){
                    440:        lab1f = getlab();
                    441:        lab2f = getlab();
                    442:     }
                    443:     if (const<=128 && const >=-128){
                    444:        printf("        moveq   #%d,%s\n", const-1, helper);
                    445:        if (!u){
                    446:            printf("    tst%c   %s\n    jge     L%d\n   neg%c   %s\n",
                    447:                sizechar, lname, lab1f, sizechar, lname);
                    448:            printf("    and%c   %s,%s\n neg%c   %s\n    jra     L%d\n",
                    449:                opchar, helper, lname, opchar, lname, lab2f );
                    450:            deflab( lab1f );
                    451:        }
                    452:        printf("        and%c   %s,%s\n", opchar, helper, lname);
                    453:        if (!u){ deflab(lab2f);}
                    454:     } else {
                    455:        if (!u){
                    456:            printf("    mov%c   %s,%s\n jge     L%d\n   neg%c   %s\n",
                    457:                    sizechar, lname, helper, lab1f, sizechar, lname);
                    458:            deflab(lab1f);
                    459:        }
                    460:        printf("        and%c   #%d,%s\n", opchar, const-1, lname );
                    461:        if (!u){
                    462:            printf("    tst%c   %s\n    jge     L%d\n   neg%c   %s\n",
                    463:                    sizechar, helper, lab2f, opchar, lname );
                    464:            deflab(lab2f);
                    465:        }
                    466:     }
                    467:     return;
                    468: }
                    469: 
                    470: optim2( p )
                    471: register NODE *p; 
                    472: {
                    473:        register NODE *q;
                    474:        register NODE *r;
                    475:        register long v;
                    476:        register op;
                    477:        int w;
                    478:        int lsize, rsize;
                    479:        NODE *rl, *rr, *qq;
                    480:        TWORD t;
                    481: 
                    482:        /*
                    483:         * reduction of strength on integer constant operands
                    484:         * this is a practical, fruitful area of peephole code optimization,
                    485:         * since there are so many easy things that can be done.
                    486:         * we also check for possible single-o OREGs in a place where
                    487:         * the oreg2() should but does not.
                    488:         */
                    489:        op = p->in.op;
                    490:        switch (optype(op)) {
                    491:        case LTYPE:
                    492:                break;
                    493:        case UTYPE:
                    494:                optim2(p->in.left);
                    495:                break;
                    496:        case BITYPE:
                    497:                optim2(p->in.left);
                    498:                optim2(p->in.right);
                    499:                break;
                    500:        }
                    501:        switch (op){
                    502:        case LS:
                    503:        case ASG LS:
                    504:        case RS:
                    505:        case ASG RS:
                    506:                /* if rhs is an extending SCONV, don't bother converting */ 
                    507:                r = p->in.right;
                    508:                if (isconv(r, SHORT, USHORT) || isconv(r, CHAR, UCHAR)) {
                    509:                    q = r->in.left;
                    510:                    *r = *q;
                    511:                    q->in.op = FREE;
                    512:                }
                    513:                /* one interesting case: <lhs> <op> 0  */
                    514:                if (r->tn.op != ICON ) break;
                    515:                if (r->tn.lval == 0 && r->tn.name[0] == '\0' ){
                    516: promoteleft:
                    517:                    t = p->in.type;
                    518:                    q = p->in.left;
                    519:                    *p = *q; /* paint over */
                    520:                    p->in.type = t;
                    521:                    q->in.op = r->in.op = FREE;
                    522:                }
                    523:                /* could test for count of 1, too, but this is easier to do later on */
                    524:                break;
                    525: 
                    526:        case UNARY MUL:
                    527:                /* in case this wasn't done earlier... */
                    528:                if (p->in.left->in.op == ICON) {
                    529:                        q = p->in.left;
                    530:                        t = p->in.type;
                    531:                        *p = *q;
                    532:                        p->in.op = NAME;
                    533:                        p->in.type = t;
                    534:                        q->in.op = FREE;
                    535:                        break;
                    536:                }
                    537:                /*
                    538:                 * put potential double index OREG trees into a canonical
                    539:                 * form: ( <base> + <offset> ) + <index>
                    540:                 */
                    541:                p = p->in.left;
                    542:                if (p->in.op != PLUS)
                    543:                        break;
                    544:                q = p->in.left;
                    545:                r = p->in.right;
                    546:                if ( ISPTR(r->in.type) ) {
                    547:                        /*
                    548:                         * put the pointer on the left
                    549:                         */
                    550:                        p->in.left = r;
                    551:                        p->in.right = q;
                    552:                        q = p->in.left;
                    553:                        r = p->in.right;
                    554:                }
                    555:                if ( ISPTR(q->in.type)
                    556:                    && (r->in.op == PLUS || r->in.op == MINUS)
                    557:                    && !ISPTR(r->in.left->in.type)
                    558:                    && r->in.right->in.op == ICON ) {
                    559:                        /*
                    560:                         * <ptr exp> + ( <int exp> [+-] ICON )
                    561:                         *      rewrite as
                    562:                         * (<ptr exp> [+-] ICON) + <int exp>
                    563:                         */
                    564:                        p->in.right = r->in.left;
                    565:                        r->in.left = q;
                    566:                        p->in.left = r;
                    567:                        r->in.type = q->in.type;
                    568:                        break;
                    569:                }
                    570:                if (r->in.op == LS
                    571:                    && ( (rr = r->in.right)->in.op == ICON )
                    572:                    && ( (rl = r->in.left)->in.op == PLUS
                    573:                        || rl->in.op == MINUS )
                    574:                    && !ISPTR(rl->in.left->in.type)
                    575:                    && rl->in.right->in.op == ICON ) {
                    576:                        /*
                    577:                         * <ptr exp> + ((<int exp> [+-] ICON) << ICON)
                    578:                         *      rewrite as
                    579:                         * (<ptr exp> [+-] ICON*) + (<int exp> << ICON)
                    580:                         */
                    581:                        r->in.left = rl->in.left;
                    582:                        rl->in.left = q;
                    583:                        p->in.left = rl;
                    584:                        rl->in.type = q->in.type;
                    585:                        rl->in.right->tn.lval <<= rr->tn.lval;
                    586:                        break;
                    587:                }
                    588:                break;
                    589: 
                    590:        case PLUS:
                    591:        case ASG PLUS:
                    592:        case MINUS:
                    593:        case ASG MINUS:
                    594:                /*
                    595:                 * one interesting cases: <lhs> <op> 0.
                    596:                 * <address reg> + SCONV( <short> ) is a good one, too,
                    597:                 * but is best done later on.
                    598:                 */
                    599:                if (((r=p->in.right)->tn.op == ICON
                    600:                    && r->tn.lval == 0 && r->tn.name[0] == '\0' )
                    601:                    || (r->tn.op == FCON && r->fpn.dval == 0.0 )) {
                    602:                        goto promoteleft;
                    603:                }
                    604:                break;
                    605: 
                    606:        case MUL:
                    607:                /*
                    608:                 * put constants on the right
                    609:                 */
                    610:                if (p->in.left->in.op == ICON && p->in.right->in.op != ICON) {
                    611:                        r = p->in.right;
                    612:                        p->in.right = p->in.left;
                    613:                        p->in.left = r;
                    614:                }
                    615:                /* fall through */
                    616: 
                    617:        case ASG MUL:
                    618:        case DIV:
                    619:        case ASG DIV:
                    620:        case MOD:
                    621:        case ASG MOD:
                    622:                /*
                    623:                 * two interesting case: <lhs> <op> 1
                    624:                 * and: small multiplies that can be handled by 
                    625:                 *      the feeble instructions.
                    626:                 */
                    627:                if (((r=p->in.right)->tn.op == ICON
                    628:                    && r->tn.lval == 1 && r->tn.name[0] == '\0')
                    629:                    || (r->tn.op == FCON && r->fpn.dval == 1.0 )) {
                    630:                        switch (op){
                    631:                        case MOD:
                    632:                        case ASG MOD:
                    633:                            /*
                    634:                             * x%1 == 0
                    635:                             * BUT x might have side effects, so...
                    636:                             * x%1 ==> (x,0)
                    637:                             */
                    638:                            p->in.op = COMOP;
                    639:                            if (r->tn.op==FCON)
                    640:                                r->fpn.dval = 0.0;
                    641:                            else
                    642:                                r->tn.lval = 0;
                    643:                            break;
                    644:                        default:
                    645:                            goto promoteleft;
                    646:                        }
                    647:                        break;
                    648:                }
                    649:                if (op == DIV || op == ASG DIV){
                    650:                    /*
                    651:                     * a very particular case: a difference of two
                    652:                     * pointers, divided by a power of two should
                    653:                     * always give an integral result (this is
                    654:                     * pointer subtraction, with the implied divide
                    655:                     * by sizeof( *p ) ). So, we can change this
                    656:                     * into a shift, if we ever see it.
                    657:                     * AND...
                    658:                     * a less peculiar case: unsigned divide by a power of 2.
                    659:                     */
                    660:                    if (
                    661:                       (p->in.type == UNSIGNED && r->in.op ==ICON  )
                    662:                    || ((p->in.type == INT || p->in.type == UNSIGNED) 
                    663:                        && r->in.op == ICON && (q = p->in.left)->in.op == MINUS
                    664:                        && ISPTR(q->in.left->in.type)
                    665:                        && ISPTR(q->in.right->in.type))
                    666:                    ){
                    667:                        if (cntbits( v=r->tn.lval )==1 && r->in.name[0]=='\0' ){
                    668:                            /* well, looks like we found one */
                    669:                            w = ffs( v ) - 1;
                    670:                            p->in.op = op += RS - DIV; /* keep ASG if present */
                    671:                            r->tn.lval = w;
                    672:                            break;
                    673:                        }
                    674:                    }
                    675:                }
                    676:                /* the other good case is multiply by a power of two,
                    677:                        and thats already being handled in the front end */
                    678:                /*
                    679:                 * many multiplies
                    680:                 * can be done directly in the hardware:
                    681:                 * {SHORT, USHORT, CHAR, UCHAR} x
                    682:                 *      {SHORT, USHORT, CHAR, UCHAR, ICON}
                    683:                 *
                    684:                 * so can the corresponding divides.
                    685:                 */
                    686:                if (p->in.type != INT && p->in.type != UNSIGNED &&
                    687:                    !ISPTR(p->in.type))
                    688:                        break;
                    689:                q = p->in.left;
                    690:                if ( isconv(q, SHORT, USHORT ) ) lsize = 2;
                    691:                else if (isconv(q, CHAR, UCHAR )) lsize = 1;
                    692:                else if (q->in.type == SHORT)     lsize = 0;
                    693:                else break;
                    694:                if ( isconv(r, SHORT, USHORT ) ||
                    695:                            special(r, SSCON) ) rsize = 2;
                    696:                else if (isconv(r, CHAR, UCHAR )) rsize = 1;
                    697:                else break;
                    698:                /* we've looked at both sides and it looks plausable */
                    699:                /* rearrange lhs */
                    700:                if (lsize == 1){
                    701:                    /* diddle SCONV, but leave it in place */
                    702:                    q->in.type = (q->in.left->tn.type==UCHAR)?USHORT:SHORT;
                    703:                } else if(lsize == 2){
                    704:                    p->in.left = q->in.left;
                    705:                    q->in.op = FREE;
                    706:                }
                    707:                /* now rearrange rhs */
                    708:                if (rsize == 1){
                    709:                    r->in.type = (r->in.left->tn.type==UCHAR)?USHORT:SHORT;
                    710:                } else if (r->tn.op == ICON){
                    711:                    r->tn.type = SHORT;
                    712:                } else {
                    713:                    p->in.right = r->in.left;
                    714:                    r->in.op = FREE;
                    715:                }
                    716:                /* 
                    717:                 *  The result of the mul[us] instructions are ints
                    718:                 *  anyway, so leave the type of the MUL node alone.
                    719:                 *  But DIV must be acknowleged as short.
                    720:                 */
                    721:                if ( (op==DIV || op== ASG DIV || op==MOD || op==ASG MOD)
                    722:                && p->in.type != SHORT && p->in.type != USHORT){
                    723:                    w = (p->in.right->tn.type==SHORT && p->in.left->tn.type==SHORT) ? SHORT : USHORT;
                    724:                    q = talloc();
                    725:                    *q = *p;
                    726:                    p->in.op = SCONV;
                    727:                    q->in.type = w;
                    728:                    p->in.left = q;
                    729:                    p->in.right = 0;
                    730:                }
                    731:                break;
                    732:        case SCONV:
                    733:                /*
                    734:                 * conversions from float to double
                    735:                 * in a coprocessor register are vacuous
                    736:                 */
                    737:                q = p->in.left;
                    738:                if (p->in.type == DOUBLE && q->in.type == FLOAT
                    739:                  && q->in.op == REG && iscreg(q->tn.rval)) {
                    740:                    TWORD t = p->in.type;
                    741:                    *p = *q;
                    742:                    p->in.type = t;
                    743:                    q->in.op = FREE;
                    744:                    return;
                    745:                }
                    746:                /*
                    747:                 *           John Gilmore memorial hack
                    748:                 *
                    749:                 * garbage-can case: 
                    750:                 *  if this is a shorten of a simple calculation
                    751:                 *  whose (2) operands are no larger than the 
                    752:                 *  result type, then we can do the operation more
                    753:                 *  cheaply, no?
                    754:                 * The architypical case looks like:
                    755:                 *  (SCONV<short> (+<int> (SCONV<int> NAME<short> ) ICON ))
                    756:                 *  p^                    q^                       r^
                    757:                 */
                    758:                if ( q->in.type!=INT && q->in.type!=UNSIGNED ) return;
                    759:                switch (q->in.op){
                    760:                case PLUS:
                    761:                case MINUS:
                    762:                case MUL:
                    763:                case DIV:
                    764:                case MOD:
                    765:                case LS:
                    766:                case RS:
                    767:                case AND:
                    768:                case OR:
                    769:                case ER:
                    770:                    break;
                    771:                default:
                    772:                    return;
                    773:                }
                    774:                if ( p->in.type==SHORT || p->in.type==USHORT ){
                    775:                    w = 2;
                    776:                    v = 0x7fff;
                    777:                }else if ( p->in.type==CHAR  || p->in.type==UCHAR ){
                    778:                    w = 1;
                    779:                    v = 0x7f;
                    780:                }else break;
                    781:                qq = q;
                    782:                r = q->in.right;
                    783:                q = q->in.left;
                    784:                if ( isconv(q, SHORT, USHORT ) ) lsize = 2;
                    785:                else if (isconv(q, CHAR, UCHAR )) lsize = 1;
                    786:                else if (q->in.op == ICON)
                    787:                    if (q->tn.name[0] == '\0' 
                    788:                    && ((q->tn.lval | v)==v || (q->tn.lval|v)==-1))
                    789:                        lsize = 0;
                    790:                    else break;
                    791:                else if (tlen(q) < sizeof(long)) lsize = -1;
                    792:                else break;
                    793:                if ( isconv(r, SHORT, USHORT ) ) rsize = 2;
                    794:                else if (isconv(r, CHAR, UCHAR )) rsize = 1;
                    795:                else if (r->in.op == ICON)
                    796:                    if (r->tn.name[0] == '\0' 
                    797:                    && ((r->tn.lval | v)==v || (r->tn.lval|v)==-1))
                    798:                        rsize = 0;
                    799:                    else break;
                    800:                else if (tlen(r) < sizeof(long)) rsize = -1;
                    801:                else break;
                    802:                if (lsize == -1) {
                    803:                    NODE *t = talloc();
                    804:                    t->in.op = SCONV;
                    805:                    t->in.type = qq->in.type;
                    806:                    t->in.left = q;
                    807:                    lsize = tlen(q);
                    808:                    q = t;
                    809:                    qq->in.left = q;
                    810:                }
                    811:                if (rsize == -1) {
                    812:                    NODE *t = talloc();
                    813:                    t->in.op = SCONV;
                    814:                    t->in.type = qq->in.type;
                    815:                    t->in.left = r;
                    816:                    rsize = tlen(r);
                    817:                    r = t;
                    818:                    qq->in.right = r;
                    819:                }
                    820:                if (rsize > w || lsize > w) {
                    821:                    /* must preserve top SCONV, but weaken operation */
                    822:                    p = p->in.left;
                    823:                    if (rsize >lsize){
                    824:                        p->in.type  =  r->in.left->in.type ;
                    825:                        w = rsize;
                    826:                    } else {
                    827:                        p->in.type  =  q->in.left->in.type;
                    828:                        w = lsize;
                    829:                    }
                    830:                } else {
                    831:                    /* clobber SCONV */
                    832:                    NODE * t = p->in.left;
                    833:                    TWORD tt = p->in.type;
                    834:                    *p = *t; /* paint over */
                    835:                    p->in.type = tt; /* except type */
                    836:                    t->in.op = FREE; /* give a node back */
                    837:                }
                    838:                /* now weaken or elide child convs */
                    839:                switch (lsize){
                    840:                case 0: /* ICON -- diddle type */
                    841:                    q->in.type = p->in.type; break;
                    842:                case 1: /* char */
                    843:                    if (lsize <w){
                    844:                        /* retain SCONV but weaken */
                    845:                        q->in.type = p->in.type; break;
                    846:                    }
                    847:                    /* else fall through */
                    848:                case 2: /* same size -- elide SCONV */
                    849:                    { NODE * t = q->in.left;
                    850:                    *q = *t;
                    851:                    t->in.op = FREE;
                    852:                    }
                    853:                }
                    854:                switch (rsize){
                    855:                case 0: /* ICON -- diddle type */
                    856:                    r->in.type = p->in.type; break;
                    857:                case 1: /* char */
                    858:                    if (rsize <w){
                    859:                        /* retain SCONV but weaken */
                    860:                        r->in.type = p->in.type; break;
                    861:                    }
                    862:                    /* else fall through */
                    863:                case 2: /* same size -- elide SCONV */
                    864:                    { NODE * t = r->in.left;
                    865:                    *r = *t;
                    866:                    t->in.op = FREE;
                    867:                    }
                    868:                }
                    869:                break;
                    870:        case CHK:
                    871:                /*
                    872:                 * A CHK with constant bounds, of which the left-hand-side
                    873:                 * is an SCONV that widens a shorter type can be converted
                    874:                 * to an SCONV over a CHK. This lets us use weaker CHK
                    875:                 * instructions.
                    876:                 */
                    877:                if (p->in.type != INT && p->in.type != UNSIGNED) break;
                    878:                q = p->in.left;
                    879:                if (!isconv(q, CHAR, UCHAR) && !isconv(q, SHORT, USHORT) )break;
                    880:                r = p->in.right;
                    881:                rr = r->in.right;
                    882:                rl = r->in.left;
                    883:                if (rr->in.op != ICON || rl->in.op != ICON) break;
                    884:                /*
                    885:                 * make bounds smaller using the type of the
                    886:                 * converted operand
                    887:                 */
                    888:                t = q->in.left->in.type;
                    889:                switch(t) {
                    890:                case CHAR:
                    891:                    if (reduce_bounds(-128, 127, rl, rr))
                    892:                        goto delete_check;
                    893:                    break;
                    894:                case UCHAR:
                    895:                    if (reduce_bounds(0, 255, rl, rr))
                    896:                        goto delete_check;
                    897:                    break;
                    898:                case SHORT:
                    899:                    if (reduce_bounds(-32768, 32767, rl, rr))
                    900:                        goto delete_check;
                    901:                    break;
                    902:                case USHORT:
                    903:                    if (reduce_bounds(0, 65535, rl, rr))
                    904:                        goto delete_check;
                    905:                    break;
                    906:                delete_check:
                    907:                    *p = *q;
                    908:                    q->in.op = FREE;
                    909:                    tfree(r);
                    910:                    return;
                    911:                }
                    912:                /*
                    913:                 * weaken the conversion by
                    914:                 * exchanging CHK and SCONV nodes
                    915:                 */
                    916:                *p = *q;        /* p becomes SCONV node */
                    917:                p->in.left = q;
                    918:                q->in.op = CHK;
                    919:                q->in.right = r;
                    920:                q->in.type = r->in.type = rl->tn.type = rr->tn.type = t;
                    921:                break;
                    922: 
                    923:        case INIT:
                    924:                /*
                    925:                 * not an optimization, but prevents an
                    926:                 * infinite loop later on in code generation...
                    927:                 */
                    928:                q = p->in.left;
                    929:                if (q->in.op != ICON && q->in.op != FCON) {
                    930:                        uerror("Illegal initialization");
                    931:                        tfree(q);
                    932:                        q = talloc();
                    933:                        q->in.type = p->in.type;
                    934:                        if (ISFLOATING(p->in.type)) {
                    935:                                q->in.op = FCON;
                    936:                                q->fpn.dval = 0.0;
                    937:                        } else {
                    938:                                q->in.op = ICON;
                    939:                                q->tn.name = "";
                    940:                                q->tn.lval = 0;
                    941:                        }
                    942:                        p->in.left = q;
                    943:                }
                    944:                break;
                    945: 
                    946:        case FORCE:
                    947:                /*
                    948:                 * if the type of a FORCE op is {u}char or {u}short,
                    949:                 * extend it into an INT.
                    950:                 */
                    951:                switch(p->in.type){
                    952:                case CHAR:
                    953:                case UCHAR:
                    954:                case SHORT:
                    955:                case USHORT:
                    956:                        q = talloc();
                    957:                        q->in.op = SCONV;
                    958:                        q->in.type = INT;
                    959:                        q->in.left = p->in.left;
                    960:                        q->in.right = NULL;
                    961:                        p->in.left = q;
                    962:                        p->in.type = INT;
                    963:                        break;
                    964:                }
                    965:                break;
                    966: 
                    967:        } /* switch */
                    968: }
                    969: 
                    970: /*
                    971:  * reduce bounds of a range check using
                    972:  * the known bounds of the domain type
                    973:  */
                    974: int
                    975: reduce_bounds(domain_min, domain_max, range_min, range_max)
                    976:     register CONSZ domain_min, domain_max;
                    977:     register NODE *range_min, *range_max;
                    978: {
                    979:     /* do the domain and range intersect? */
                    980:     if (domain_min > range_max->tn.lval || domain_max < range_min->tn.lval) {
                    981:        /* expression value is known to lie outside required range */
                    982:        werror("expression value is out of range");
                    983:     }
                    984:     /* range := intersection(range, domain) */
                    985:     if (domain_min > range_min->tn.lval)
                    986:        range_min->tn.lval = domain_min;
                    987:     if (domain_max < range_max->tn.lval)
                    988:        range_max->tn.lval = domain_max;
                    989:     /* if domain is a subset of range, range check is unnecessary */
                    990:     if (domain_min >= range_min->tn.lval && domain_max <= range_max->tn.lval) {
                    991:        return(1);
                    992:     }
                    993:     return(0);
                    994: }

unix.superglobalmegacorp.com

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