Annotation of researchv9/cmd/sun/pcc/optim2.c, revision 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.