Annotation of researchv10no/cmd/ccom/common/cost.c, revision 1.1.1.1

1.1       root        1: /*     @(#) cost.c: 1.4 3/4/84 */
                      2: 
                      3: # include "mfile2.h"
                      4: 
                      5: # ifndef CSTORE
                      6: # define CSTORE(q) 2
                      7: # endif
                      8: # ifndef CLOAD
                      9: # define CLOAD(q) 2
                     10: # endif
                     11: # ifndef CCTEST
                     12: # define CCTEST(q) 1
                     13: # endif
                     14: # ifndef DFLT_STRATEGY
                     15: # define DFLT_STRATEGY LTOR|RTOL
                     16: # endif
                     17: 
                     18:        /* enough regs so there is always a free pair */
                     19: # define HREG ((1+NRGS)/2+1)
                     20: 
                     21: #define LSAVED 30      /* since we're storing goals, also */
                     22:                        /* actually, since only 0.6% of time is here, */
                     23:                        /* who cares what the size is */
                     24: /* stores costs of leaves costed so far */
                     25: static struct leaf {
                     26: /*             int op;
                     27: /*             int type;
                     28: /*             int goal;
                     29: */
                     30:                unsigned long key;      /* (goal<<26) | (type<<9) | op */
                     31:                int cst[NCOSTS];
                     32: }      leafcosts[LSAVED], *leaf_ptr=leafcosts, *recost_leaf=0;
                     33:        /* used to identify subtrees */
                     34: # define NSUBTREES 10
                     35: int nsubtree;
                     36: NODE *subtree[NSUBTREES];
                     37: int subgoal[NSUBTREES];
                     38: 
                     39: int strbc[NCOSTS];  /* the strategy done by bcost */
                     40: SHAPE * lshbc[NCOSTS];  /* left-hand shape */
                     41: SHAPE * rshbc[NCOSTS];  /* right-hand shape */
                     42: 
                     43: commute( p ) NODE *p; {
                     44:        /* commute p in place */
                     45:        register NODE *q;
                     46: #ifndef NODBG
                     47:        if(odebug) printf("commute: .=%u l=%u r=%u\n",p,p->in.left,p->in.right);
                     48: #endif
                     49:        q = p->in.left;
                     50:        p->in.left = p->in.right;
                     51:        p->in.right = q;
                     52:        }
                     53: 
                     54: # ifndef NODBG
                     55: # define GETS(x,y) if( e2debug>1) printf( "    x gets %d\n", y );
                     56: # define GETSN(x,y) if( e2debug>1) printf( "   cst[%d] gets %d\n", x, y );
                     57: # else
                     58: # define GETS(x,y)
                     59: # define GETSN(x,y)
                     60: # endif
                     61: 
                     62: bcost( p, q )
                     63: register NODE *p;
                     64: register OPTAB *q;
                     65: {
                     66:        /* return the basic costs of matching q against tree p */
                     67:        /* sha is set previously by match with a list of legal left
                     68:        /* and right shapes */
                     69:        /* bcost updates strbc, lshbc, and rshbc to reflect the
                     70:        /* strategy, left shape, and right shape, that minimizes the cost
                     71:        /* for q on p */
                     72: 
                     73:        /* j has its address taken, so it can't be in a reg */
                     74:        int j;
                     75:        int o, cc, c, s, tc, ttc, n, nn, lnn, lregs, rregs, cs, res;
                     76:        int il, ir;  /* index into left and right address shapes */
                     77:        int lsubtree;
                     78:        NODE *l, *r;
                     79:        register NODE *pp;
                     80:        register ix;
                     81:        SHAPE *sl, *sr;
                     82: 
                     83:        o = p->tn.op;
                     84: 
                     85:        /* look for the simple cases with register counts */
                     86:        n = (q->needs&NCOUNT);
                     87:        if( (q->needs&NPAIR) && n<HREG ) n = HREG;
                     88: 
                     89:        /* set up the left and right descendents */
                     90:        l = getlo( p, o );
                     91:        r = getro( p, o );
                     92:        /*
                     93:         *      If the operator table entry does not have a left shape,
                     94:         *      but it does have a right shape, then this
                     95:         *      table entry is for leaves ONLY, referenced to p, not to r
                     96:         */
                     97:        if( q->rshape && !q->lshape)
                     98:                r = p;
                     99: 
                    100:        res = q->rewrite;
                    101: 
                    102:        /* determine the code generation strategy */
                    103: 
                    104:        if( o == COMOP ) cerror( "COMOP in bcost" );
                    105: 
                    106:        s = LTOR;  /* default strategy */
                    107: 
                    108:        if( optype(o) == BITYPE ) {
                    109: 
                    110:                switch( o ) {
                    111: 
                    112:                case CALL:
                    113:                case STCALL:
                    114:                case FORTCALL:
                    115: # ifndef LTORARGS
                    116:                case CM:  /* function arguments */
                    117: # endif
                    118:                        s = RTOL;
                    119:                        break;
                    120: 
                    121:                default:
                    122: # ifdef STACK
                    123:                        if( asgop(o) ) s = RTOL;
                    124:                        else s = LTOR;
                    125: # else
                    126:                        s = DFLT_STRATEGY;
                    127: # endif
                    128:                        break;
                    129:                }
                    130:        }
                    131: 
                    132: # ifndef NODBG
                    133:        if(e2debug) {
                    134:                printf("bcost(%d(%s),%d(%s),%x), s = ",
                    135:                        p-node, opst[o], q->stinline, opst[q->op], sha[0] );
                    136:                pstrat(s);
                    137:                printf( "\n" );
                    138:                printf( "\tneeds=%d%s%s\n", n,
                    139:                        (q->needs&LSHARE)?", LSHARE":"",
                    140:                        (q->needs&RSHARE)?", RSHARE":"" );
                    141:                printf( "\tshape table: (%d %d %d ... )(%d %d %d ... )\n",
                    142:                        sha[0][0]-shapes, sha[0][1]-shapes, sha[0][2]-shapes,
                    143:                        sha[1][0]-shapes, sha[1][1]-shapes, sha[1][2]-shapes
                    144:                        );
                    145:                }
                    146: # endif
                    147: 
                    148:        /* triple loop:
                    149:        /* double loop over the left and right sides */
                    150:        /* single loop over the number of regs available */
                    151: 
                    152:        for( il=0; (sl = sha[0][il]) || il==0; ++il ) {
                    153:                lregs = lsubtree = nsubtree = 0;
                    154:                c = q->cost;
                    155:                lnn = n;
                    156:                if( sl ) {
                    157:                        /* list the left subtrees */
                    158:                        findsub( l, sl );
                    159:                        if( l->tn.op==REG && sl->op==REG && asgop(q->op)
                    160:                                && !asgop(o) ) {
                    161: 
                    162:                                /* in an expression such as a+b, where a is */
                    163:                                /* a register var, copy a to a scratch reg */
                    164:                                /* before using += to do the add */
                    165:                                /* this test causes that copy, by suggesting */
                    166:                                /* that the lhs is a subtree, even though it
                    167:                                /* matches the template exactly */
                    168: 
                    169:                                subtree[nsubtree] = l;
                    170:                                subgoal[nsubtree] = NRGS;
                    171:                                ++nsubtree;
                    172:                                }
                    173:                        lsubtree = nsubtree;
                    174: 
                    175:                        /* account for the cost of the shape */
                    176:                        c += q->lcount * sl->sc;
                    177: 
                    178:                        /* count lhs register usage */
                    179:                        for( lregs=ix=0; ix<lsubtree; ++ix ) {
                    180:                                if( subgoal[ix] == NRGS ) {
                    181:                                        lregs += szty(subtree[ix]->tn.type);
                    182:                                        }
                    183:                                }
                    184:                        if( !(q->needs&LSHARE) ) lnn += lregs;
                    185:                        }
                    186: 
                    187: # ifndef NODBG
                    188:                if( e2debug ) {
                    189:                        printf( "\tbcost left shape: sl=%d(%s), cost=%d\n",
                    190:                                sl-shapes, sl?opst[sl->op]:"?", c );
                    191:                        printf( "\t%d left subtrees\n", nsubtree );
                    192:                        for( j=0; j<nsubtree; ++j ) {
                    193:                                printf( "\t\tsubtree %d, goal %d\n",
                    194:                                        subtree[j]-node, subgoal[j] );
                    195:                                }
                    196:                        }
                    197: # endif
                    198: 
                    199:                for( ir=0; (sr = sha[1][ir]) || ir==0; ++ir ) {
                    200:                        ttc = c;
                    201:                        nsubtree = lsubtree;
                    202:                        if( sr ) {
                    203:                                ttc += q->rcount * sr->sc;
                    204:                                findsub( r, sr );
                    205:                                }
                    206: # ifndef NODBG
                    207:                        if( e2debug ) {
                    208:                                printf( "\tbcost rt. shp: sr=%d(%s), cost=%d\n",
                    209:                                        sr-shapes, sr?opst[sr->op]:"?", ttc );
                    210:                                printf( "\t%d right subtrees\n",
                    211:                                        nsubtree-lsubtree );
                    212:                                for( j=lsubtree; j<nsubtree; ++j ) {
                    213:                                        printf( "\t\tsubtree %d, goal %d\n",
                    214:                                                subtree[j]-node, subgoal[j] );
                    215:                                        }
                    216:                                }
                    217: # endif
                    218: 
                    219:                        /* figure out the minimum number of regs. possible */
                    220:                        for( rregs=0,ix=lsubtree; ix<nsubtree; ++ix ) {
                    221:                                if( subgoal[ix] == NRGS ) {
                    222:                                        rregs += szty(subtree[ix]->tn.type);
                    223:                                        }
                    224:                                }
                    225: 
                    226:                        nn = lnn;
                    227:                        if( q->needs & RSHARE ) nn -= rregs;
                    228:                        if( nn < lregs ) nn = lregs;
                    229:                        nn += rregs;
                    230: 
                    231: # ifndef NODBG
                    232:                        if( e2debug ) {
                    233:                                printf( "%d left, %d right regs, need >= %d\n",
                    234:                                        lregs, rregs, nn );                             
                    235:                                }
                    236: # endif
                    237: 
                    238:                        for( j=NRGS; j>=nn; --j ) {
                    239: # ifndef NODBG
                    240:                                if( e2debug ) {
                    241:                                        printf( "\t***  j = %d  ***\n", j );
                    242:                                        }
                    243: # endif
                    244:                                /* exact match: don't fool around */
                    245:                                if( nsubtree==0 ) {
                    246:                                        cc = ttc;
                    247:                                        cs = LTOR;
                    248:                                        goto distribute;
                    249:                                        }
                    250:                                /* general case: grub around */
                    251:                                /* LTOR means ascending, RTOL means descending*/
                    252: 
                    253:                                cc = INFINITY;
                    254:                                if( s&LTOR ){ /* do it left to right */
                    255:                                        int j1 = j;
                    256:                                        tc = ttc;
                    257:                                        for( ix=0; ix<nsubtree; ++ix ) {
                    258:                                                pp = subtree[ix];
                    259:                                                if( subgoal[ix] == NRGS ){
                    260:                                                        /* shouldn't happen */
                    261:                                                        if( j1<0 ) tc=INFINITY;
                    262:                                                        else tc+=pp->tn.cst[j1];
                    263:                                                        j1 -= szty(pp->tn.type);
                    264:                                                        }
                    265:                                                else tc +=
                    266:                                                        pp->tn.cst[subgoal[ix]];
                    267:                                                }
                    268:                                        cc = tc;
                    269:                                        cs = LTOR;
                    270:                                        }
                    271:                                if( s&RTOL ){ /* do it right to left */
                    272:                                        int j1 = j;
                    273:                                        tc = ttc;
                    274:                                        for( ix=nsubtree-1; ix>=0; --ix ) {
                    275:                                                pp = subtree[ix];
                    276:                                                if( subgoal[ix] == NRGS ){
                    277:                                                        /* shouldn't happen */
                    278:                                                        if( j1<0 ) tc=INFINITY;
                    279:                                                        else tc+=pp->tn.cst[j1];
                    280:                                                        j1 -= szty(pp->tn.type);
                    281:                                                        }
                    282:                                                else tc +=
                    283:                                                        pp->tn.cst[subgoal[ix]];
                    284:                                                }
                    285:                                        if( tc < cc ){
                    286:                                                cc = tc;
                    287:                                                cs = RTOL;
                    288:                                                }
                    289:                                        }
                    290:                                if( cc >= INFINITY ) break; /* done */
                    291: 
                    292:                                /* now, cc is the minmal cost with j regs */
                    293:                                /* update the various cost measures */
                    294:                                /* everything affects CEFF */
                    295:                        distribute:
                    296: # ifndef NODBG
                    297:                                if( e2debug ) {
                    298:                                        printf( "\tdistribute %d\n", cc );
                    299:                                        }
                    300: # endif
                    301:                                if( cc < p->tn.cst[CEFF] ) {
                    302:                                        GETS(EFF,cc);
                    303:                                        p->tn.cst[CEFF] = cc;
                    304:                                        strbc[CEFF] = cs;
                    305:                                        lshbc[CEFF] = sl;
                    306:                                        rshbc[CEFF] = sr;
                    307:                                        }
                    308:                                /* for EFF, only do with NRGS */
                    309:                                if( p->tn.goal == CEFF ) break;
                    310:                                if( res == RNULL || res == RNOP ){
                    311:                                        /* affects only CEFF */
                    312:                                        cerror( "RNULL/RNOP error" );
                    313:                                        }
                    314: 
                    315:                                if( (p->tn.goal==CCC) && (res&RESCC) ) {
                    316:                                        /* CC's set */
                    317:                                        if( cc < p->tn.cst[CCC] ) {
                    318:                                                GETS(CC,cc);
                    319:                                                p->tn.cst[CCC] = cc;
                    320:                                                strbc[CCC] = cs;
                    321:                                                lshbc[CCC] = sl;
                    322:                                                rshbc[CCC] = sr;
                    323:                                                }
                    324:                                        }
                    325: 
                    326: 
                    327:                                /* now, the register cost */
                    328:                                tc = cc;
                    329:                                if( (res&RLEFT) && sl->op != REG ){
                    330:                                        cc += CLOAD(q);
                    331:                                        }
                    332:                                else if( (res&RRIGHT) && sr->op != REG ){
                    333:                                        cc += CLOAD(q);
                    334:                                        }
                    335:                                if( cc < p->tn.cst[j] ) {
                    336:                                        GETSN(j,cc);
                    337:                                        p->tn.cst[j] = cc;
                    338:                                        strbc[j] = cs;
                    339:                                        lshbc[j] = sl;
                    340:                                        rshbc[j] = sr;
                    341:                                        }
                    342: 
                    343:                                /* for CC's, only do w. NRGS */
                    344:                                if( p->tn.goal == CCC ) break;
                    345: 
                    346:                                if( j != NRGS ) continue;
                    347: 
                    348:                                /* record if lhs is actually a temp */
                    349:                                /* need only do for NRGS */
                    350: 
                    351:                                if( tempok(p) && tc < p->tn.cst[CTEMP] ) {
                    352:                                        GETS(TEMP,tc);
                    353:                                        p->tn.cst[CTEMP] = tc;
                    354:                                        strbc[CTEMP] = cs;
                    355:                                        lshbc[CTEMP] = sl;
                    356:                                        rshbc[CTEMP] = sr;
                    357:                                        }
                    358:                                }
                    359:                        }
                    360:                }
                    361: 
                    362:        /* now, some global cleanup */
                    363:        /* some things are worth updating only once per template */
                    364: 
                    365:        if( p->tn.goal == CEFF ) return;  /* done */
                    366: 
                    367:        /* set Condition Codes by testing a register */
                    368:        if( p->tn.goal == CCC ) {
                    369:                tc = p->tn.cst[NRGS]+CCTEST(q);
                    370:                if( tc < p->tn.cst[CCC] ) {
                    371:                        GETS(CC,tc);
                    372:                        p->tn.cst[CCC] = tc;
                    373:                        strbc[CCC] = strbc[NRGS];
                    374:                        lshbc[CCC] = lshbc[NRGS];
                    375:                        rshbc[CCC] = rshbc[NRGS];
                    376:                        }
                    377:                return;
                    378:                }
                    379: 
                    380:        /* put into TEMP by putting into REG, then storing */
                    381:        /* if the lhs type is OK and we have an assignment op, don't
                    382:        /* need to store: just use the result from EFF */
                    383: 
                    384:        if( asgop(o) && o!=INCR && o!= DECR && lhsok( l ) &&
                    385:                        p->tn.type == l->tn.type ) {
                    386:                cc = p->tn.cst[CEFF];
                    387:                if( cc < p->tn.cst[CTEMP] ) {
                    388:                        GETS(CTEMP,cc);
                    389:                        p->tn.cst[CTEMP] = cc;
                    390:                        strbc[CTEMP] = strbc[CEFF];
                    391:                        lshbc[CTEMP] = lshbc[CEFF];
                    392:                        rshbc[CTEMP] = rshbc[CEFF];
                    393:                }
                    394:        }
                    395:        tc = p->tn.cst[NRGS] + CSTORE(q);
                    396: 
                    397:        if( tc < p->tn.cst[CTEMP] ) {
                    398:                GETS(TEMP,tc);
                    399:                p->tn.cst[CTEMP] = tc;
                    400:                strbc[CTEMP] = strbc[NRGS];
                    401:                lshbc[CTEMP] = lshbc[NRGS];
                    402:                rshbc[CTEMP] = rshbc[NRGS];
                    403:                }
                    404: 
                    405:        /* compute with few regs by storing, then loading */
                    406: 
                    407:        tc = p->tn.cst[CTEMP] + CLOAD(q);
                    408: 
                    409:        for( j=1; j<NRGS; ++j ) {
                    410:                if( tc < p->tn.cst[j] ) {
                    411:                        p->tn.cst[j] = tc;
                    412:                        GETSN(j,tc);
                    413:                        strbc[j] = strbc[CTEMP] | STORE;
                    414:                        lshbc[j] = lshbc[CTEMP];
                    415:                        rshbc[j] = rshbc[CTEMP];
                    416:                        }
                    417:                }
                    418:        }
                    419: 
                    420: lhsok( p )
                    421: NODE *p;
                    422: {
                    423:        /* p appears on the lhs of an assignment op */
                    424:        /* is it an OK substitute for a TEMP? */
                    425: 
                    426:        switch( p->tn.op ) {
                    427: 
                    428:        case NAME:
                    429:        case VAUTO:
                    430:        case VPARAM:
                    431:        case TEMP:
                    432:        case REG:
                    433:                return( 1 );
                    434: 
                    435:        }
                    436:        return( 0 );
                    437: }
                    438: 
                    439: shpr(sp) register SHAPE *sp; {
                    440:        if (!sp) return;
                    441:        if( sp->op < 0 || sp->op > DSIZE ) cerror( "shape op %d\n", sp->op );
                    442:        printf(" %s", opst[sp->op]);
                    443:        shpr(sp->sl);
                    444:        shpr(sp->sr);
                    445:        }
                    446: 
                    447: pstrat( s ) {
                    448:        /* print a nice version of the strategy s */
                    449:        register i, flag;
                    450:        static char *stratnames[] = {
                    451:                "STORE",
                    452:                "LTOR",
                    453:                "RTOL",
                    454:                0 };
                    455:        flag = 0;
                    456:        for( i=0; stratnames[i]; ++i ){
                    457:                if( s & (1<<i) ) {
                    458:                        if( flag ) putchar( '|' );
                    459:                        printf( "%s", stratnames[i] );
                    460:                        flag = 1;
                    461:                        }
                    462:                }
                    463:        if( !flag ) printf( "0" );
                    464:        }
                    465: 
                    466: insout( p, i )
                    467: NODE *p;
                    468: {
                    469:        OPTAB *q;
                    470:        int c, o, j;
                    471: 
                    472:        /* generate the actual instructions */
                    473:        /* if the cost is infinite, try rewriting */
                    474: 
                    475:        c = p->in.cst[i];
                    476:        o = p->tn.op;
                    477: 
                    478: #ifndef NODBG
                    479:        if( odebug>1 ) printf( "insout(%d,%d), cost %d\n", p-node,i,c );
                    480: #endif
                    481:        if( c >= INFINITY ){
                    482:                cerror( "missing table entry, op %s", opst[p->tn.op] );
                    483:        }
                    484: 
                    485:        /* handle COMOP specially */
                    486:        if( o == COMOP ) {
                    487:                q = match( p, (OPTAB *)0 );  /* had better match */
                    488:                if( !q ) cerror( "COMOP match fails" );
                    489:                bprt( p, q, i );
                    490:                return;
                    491:        }
                    492: 
                    493:        /* want to force bcost to do some work */
                    494:        /* this is because the strbc, etc., arrays, set by bcost, are used
                    495:        /* by bprt */
                    496: 
                    497:        for( j=0; j<NCOSTS; ++j ) ++p->in.cst[j];
                    498:        for( q=0; q = match( p, q ); ){
                    499:                if( i != CEFF ) {
                    500:                        if( q->rewrite & RLEFT ) restrip( sha[0] );
                    501:                        if( q->rewrite & RRIGHT ) restrip( sha[1] );
                    502:                }
                    503:                bcost( p, q );
                    504:                if( p->tn.cst[i] == c ) {  /* we have found it */
                    505:                        if( strbc[i]&STORE ) bprt( p, q, CTEMP );
                    506:                        else bprt( p, q, i );
                    507:                        return;
                    508:                }
                    509:        }
                    510: 
                    511:        /* commuting must be in order here */
                    512:        /* if fast flag is on, we can only fail, but it's ok to try */
                    513: 
                    514:        if( o != PLUS  &&  o != MUL  &&  o != AND  &&  o != OR  &&  o != ER ) {
                    515:                e2print( p );
                    516:                cerror( "commute??, op[%d] == %s", o, opst[o] );
                    517:        }
                    518:        commute( p );  /* this is the payoff; don't need to commute back */
                    519:        for( q=0; q = match( p, q ); ){
                    520:                if( i != CEFF ) {
                    521:                        if( q->rewrite & RLEFT ) restrip( sha[0] );
                    522:                        if( q->rewrite & RRIGHT ) restrip( sha[1] );
                    523:                }
                    524:                bcost( p, q );
                    525:                if( p->tn.cst[i] == c ) { /* we found it */
                    526:                        bprt( p, q, i );
                    527:                        return;
                    528:                }
                    529:        }
                    530: 
                    531:        cerror( "insout returns without a match" );
                    532:        /* NOTREACHED */
                    533: 
                    534: }
                    535: 
                    536: bprt( p, q, i )
                    537: NODE *p;
                    538: OPTAB *q;
                    539: {
                    540:        /* this routine is called to print out the actual instructions */
                    541:        /* it is called with a tree node p, a template q, and a goal i */
                    542:        /* bprt calls bcost, and then captures the left and right shapes */
                    543:        /* it then uses findsub to determine the preconditions and goals */
                    544:        /* a local copy of this information must be made, since bprt can be
                    545:        /* called recursively */
                    546:        /* then, bprt calls insout to output the instructions that establish
                    547:        /* the preconditions.  Finally, it can output its own instruction */
                    548: 
                    549:        int j, j1, s, o, k;
                    550:        NODE *l, *r;
                    551:        SHAPE *ls, *rs;
                    552:        int nn;
                    553:        int mygoal[NSUBTREES];
                    554:        NODE *mysubs[NSUBTREES];
                    555: 
                    556:        /* sets j as well */
                    557:        if( i < NRGS ) j = i;
                    558:        else j = NRGS;
                    559:        l = getl( p );
                    560:        r = getr( p );
                    561:        if (q->rshape && !q->lshape)
                    562:                r = p;
                    563:        s = strbc[i];
                    564:        ls = lshbc[i];
                    565:        rs = rshbc[i];
                    566:        o = p->tn.op;
                    567: # ifndef NODBG
                    568:        if( odebug>1 ) {
                    569:                printf( "       matches %d, ls = %d(%s), rs = %d(%s),  s= ",
                    570:                        q->stinline, ls-shapes, ls?opst[ls->op]:"SHNL",
                    571:                        rs-shapes, rs?opst[rs->op]:"SHNL" );
                    572:                pstrat( s );
                    573:                printf( "\n" );
                    574:                }
                    575: # endif
                    576: 
                    577:        /* handle COMOP differently; this has more to do with the register
                    578:        /* allocation than the ordering */
                    579: 
                    580:        if( o == COMOP ) {
                    581:                insout( l, CEFF );
                    582:                insout( r, i );
                    583:                goto generate;
                    584:        }
                    585: 
                    586:        nsubtree = 0;
                    587:        if(rs && (s&RTOL) ) findsub( r, rs );
                    588:        if( ls ) {
                    589:                findsub( l, ls );
                    590:                if( l->tn.op==REG && ls->op==REG && asgop(q->op) &&
                    591:                                !asgop(o) ) {
                    592:                        /* we must arrange to copy a reg variable on the lhs
                    593:                        /* of a binary op, in some cases (cf. bcost) */
                    594:                        subtree[nsubtree] = l;
                    595:                        subgoal[nsubtree] = NRGS;
                    596:                        ++nsubtree;
                    597:                        }
                    598:                }
                    599:        if(rs && (s&LTOR) ) findsub( r, rs );
                    600:        nn = nsubtree;
                    601: 
                    602:        /* make a local copy */
                    603:        for( k=0; k<nn; ++k ) {
                    604:                mygoal[k] = subgoal[k];
                    605:                mysubs[k] = subtree[k];
                    606:                }
                    607: 
                    608: # ifndef NODBG
                    609:        if( odebug>1 ) {  /* subtree matches are: */
                    610:                printf( "\t\t%d matches\n", nn );
                    611:                for( k=0; k<nn; ++k ) {
                    612:                        printf( "\t\tnode %d, goal %d\n",mysubs[k]-node,
                    613:                                mygoal[k] );
                    614:                        }
                    615:                }
                    616: # endif
                    617: 
                    618:        /* do the subtrees */
                    619:        /* someday, rewrite the temps right here and now */
                    620: 
                    621:        j1 = j;
                    622:        for( k=0; k<nn; ++k ) {
                    623: # ifndef NODBG
                    624:                if( odebug>2 )
                    625:                        printf( "\t\tcalling insout(%d,%d)\n", mysubs[k]-node,
                    626:                                        j1 );
                    627: # endif
                    628:                if( mygoal[k] == NRGS ) {
                    629:                        insout( mysubs[k], j1 );
                    630:                        j1 -= szty( mysubs[k]->tn.type );
                    631:                        }
                    632:                else {
                    633:                        insout( mysubs[k], mygoal[k] );
                    634:                        }               
                    635:                }
                    636:        /* put onto the instruction string the info about the instruction */
                    637:     generate:
                    638:        if( nins >= NINS ) cerror( "too many instructions generated" );
                    639:        inst[nins].p = p;
                    640:        inst[nins].q = q;
                    641:        inst[nins].goal = i;
                    642:        /* a special case: REG op= xxx, should be done as early as possible */
                    643:        if( asgop(o) && p->in.left->tn.op == REG && o != INCR && o != DECR
                    644:                        && i!=CEFF && i!=CCC && !istreg(p->in.left->tn.rval)){
                    645:                /* "istreg" guards against rewriting returns, switches, etc. */
                    646:                inst[nins].goal = CTEMP;
                    647:        }
                    648:        ++nins;
                    649: }
                    650: 
                    651: findsub( p, s )
                    652: NODE *p;
                    653: SHAPE *s;
                    654: {
                    655:        /* account for the costs of matching the shape s with the tree j */
                    656: 
                    657:        if( !s )
                    658:                return;
                    659: 
                    660: # ifndef NODBG
                    661:        if( e2debug>1 ) {
                    662:                printf( "\t\tfindsub( %d, %d )\n", p-node, s-shapes );
                    663:                }
                    664: # endif
                    665: 
                    666:        switch( s->op ) {
                    667: 
                    668:        case TEMP:
                    669:                /* leave j unchanged */
                    670:                if( p->tn.op == TEMP ) return;
                    671:                subtree[nsubtree] = p;
                    672:                subgoal[nsubtree] = CTEMP;
                    673:                ++nsubtree;
                    674:                return;
                    675: 
                    676:        case FREE:
                    677:                subtree[nsubtree] = p;
                    678:                subgoal[nsubtree] = CEFF;
                    679:                ++nsubtree;
                    680:                return;
                    681: 
                    682:        case CCODES:
                    683:                subtree[nsubtree] = p;
                    684:                subgoal[nsubtree] = CCC;
                    685:                ++nsubtree;
                    686:                return;
                    687: 
                    688:        case REG:
                    689:                if( p->tn.op == REG ) return;  /* exact match */
                    690: 
                    691:                /* in general, look beneath */
                    692:                /* also, look here if a REG and rcst is 1 */
                    693: 
                    694:                subtree[nsubtree] = p;
                    695:                subgoal[nsubtree] = NRGS;
                    696:                ++nsubtree;
                    697:                return;
                    698:                }
                    699: 
                    700:        if( s->op == p->tn.op ) {
                    701: 
                    702:                /* look at subtrees */
                    703:                if( s->sl ) findsub( getl(p), s->sl );
                    704:                if( s->sr ) findsub( getr(p), s->sr );
                    705:                return;
                    706:                }
                    707:        }
                    708: 
                    709: costs( p ) register NODE *p; {
                    710:        register OPTAB *q;
                    711:        int i, o, ty;
                    712:        register *pc;
                    713: 
                    714:        /* compute the costs for p */
                    715:        /* the goal is either NRGS (into a reg. or temp), CCC, or CEFF */
                    716: 
                    717:        /* in a stack machine, this will probably look very different.
                    718:        /* it is possible that seting szty() to be 0 will deal with the
                    719:        /* stack machine problems; if not, we will need to put some special
                    720:        /* code in here under control of ifdef STACK
                    721:        /* the stack machine issue is that the "register" use on the left does
                    722:        /* not limit the computations on the right, and conversely */
                    723:     again:
                    724:        ty = optype( o = p->tn.op );
                    725:        if (ty == LTYPE && get_leaf(p) ) return(0);
                    726:        pc = p->in.cst;
                    727:        for( i=0; i<NCOSTS; ++i ) {
                    728:                pc[i] = INFINITY;
                    729:                strbc[i] = 0;
                    730:                lshbc[i] = rshbc[i] = (SHAPE *)0;
                    731:        }
                    732: 
                    733: # ifndef NODBG
                    734:        if( udebug ) {
                    735:                printf( "costs( %d, %d ), op = %s\n", p-node,
                    736:                        p->tn.goal, opst[o] );
                    737:                }
                    738: # endif
                    739: 
                    740:        if( ty != LTYPE ) if( costs( p->in.left ) ) return(1);
                    741:        if( ty == BITYPE ) if( costs( p->in.right ) ) return(1);
                    742: 
                    743:        pc = p->in.cst;
                    744: 
                    745:        /* now, compute the costs based on matches */
                    746:        /* handle COMOP specially */
                    747:        if( o == COMOP ) {
                    748:                int cc = p->in.left->in.cst[CEFF];
                    749:                for( i=NRGS; i<NCOSTS; ++i ) {
                    750:                        pc[i] = cc + p->in.right->in.cst[i];
                    751:                        if( pc[i] > INFINITY ) pc[i] = INFINITY;
                    752:                }
                    753:                return(0);
                    754:        }
                    755: 
                    756:        for( q=0; q = match(p,q); ){
                    757:                if( p->tn.goal != CEFF ) {
                    758:                        if( q->rewrite & RLEFT ) restrip( sha[0] );
                    759:                        if( q->rewrite & RRIGHT ) restrip( sha[1] );
                    760:                }
                    761:                bcost( p, q );
                    762: # ifndef NODBG
                    763:                if( udebug ) {
                    764:                        printf( "bcost( %d, %d )\n", p-node, q->stinline);
                    765:                        e222print( 1, p, "T" );
                    766:                }
                    767: # endif
                    768:        }
                    769: 
                    770: #ifndef NOCOMMUTE
                    771:        /* don't commute if we are trying to be fast */
                    772:        if( !fast && (o==PLUS||o==MUL||o==AND||o==OR||o==ER) ){
                    773: # ifndef NODBG
                    774:                if( udebug ) {
                    775:                        printf( "COMMUTE %d *******\n", p-node );
                    776:                }
                    777: # endif
                    778:                commute( p );
                    779:                for( q=0; q = match(p,q); ){
                    780:                if( p->tn.goal != CEFF ) {
                    781:                        if( q->rewrite & RLEFT ) restrip( sha[0] );
                    782:                        if( q->rewrite & RRIGHT ) restrip( sha[1] );
                    783:                }
                    784:                        bcost( p, q );
                    785: # ifndef NODBG
                    786:                        if( udebug ) {
                    787:                                printf( "bcost( %d, %d )\n", p-node, q->stinline);
                    788:                                e222print( 1, p, "T" );
                    789:                        }
                    790: # endif
                    791:                }
                    792:                commute( p );
                    793: # ifndef NODBG
                    794:                if( udebug ) {
                    795:                        printf( "END OF COMMUTE %d *******\n", p-node );
                    796:                }
                    797: # endif
                    798:                }
                    799: 
                    800: /*     END OF COMMUTE CODE *****  */
                    801: # endif
                    802: 
                    803:        /* here is a big worry; when do we do this rewriting?
                    804:        /* if we do it too early, we may miss some neat possibilities */
                    805:        /* if we do it too late, we may have miscomputed some earlier things */
                    806: 
                    807:        if( pc[p->tn.goal]>=INFINITY ){
                    808:                if( p->fn.type == TSTRUCT ) return(0);
                    809:                if( optype( o ) == LTYPE ) return( 0 );
                    810:                if( rewass( p ) ) return( 1 );  /* major rewrite */
                    811:                goto again;  /* minor rewrite: restart here */
                    812:                }
                    813:        if (ty == LTYPE)
                    814:                save_leaf(p);
                    815:        return( 0 );
                    816:        }
                    817: 
                    818: /* static              let me profile */
                    819: get_leaf(p)
                    820: register NODE *p;
                    821: {
                    822:        register struct leaf *lf;
                    823:        register unsigned long key =
                    824:            (p->tn.goal<<26) | (p->tn.type<<9) | p->tn.op;
                    825:                        /*see if this leaf/type/goal triple is in the tables*/
                    826:        if (p->tn.op == ICON) return (0);       /* no ICONs here */
                    827:        recost_leaf=0;
                    828:        for (lf=leafcosts;lf < leaf_ptr; lf++)
                    829:        {
                    830: /*             if (lf->op == p->tn.op && lf->type == p->tn.type &&
                    831: /*                 lf->goal == p->tn.goal)
                    832: */
                    833:                if (lf->key == key)
                    834:                {
                    835:                        /*if the saved cost was infinite, we will have
                    836:                          to recost the leaf anyway*/
                    837:                        if (lf->cst[p->tn.goal] >= INFINITY)
                    838:                        {
                    839:                                recost_leaf = lf;
                    840:                                return(0);
                    841:                        }
                    842:                        /*else, load the costs and leave*/
                    843:                        memcpy(p->tn.cst,lf->cst,sizeof(int)*NCOSTS);
                    844:                        return(1);
                    845:                }
                    846:        } /*end for*/
                    847:        return(0);
                    848: } /*end get_leaf*/
                    849: 
                    850: /* static      let me profile */
                    851: save_leaf(p)
                    852: register NODE *p;
                    853: {
                    854:                /*save the costs of this leaf for future reference.
                    855:                  if recost_leaf is non-zero, it is already in the table*/
                    856:                /* have to be careful with constants: different constant
                    857:                   shapes may have different costs and we'll be unable
                    858:                   to find a template that gives us the purported cost */
                    859:                /* for now, just chuck ICONs */
                    860:                /* I also seem to be getting hung up on changing costs
                    861:                   based on evaluation context. Let's see if adding the
                    862:                   goal to the shape helps */
                    863:        register struct leaf *lf;
                    864: 
                    865:        if ( !recost_leaf && (leaf_ptr >= leafcosts + LSAVED) ) return;
                    866:        if (p->tn.op == ICON) return;           /* sorry */
                    867:        lf = recost_leaf ? recost_leaf : leaf_ptr++;
                    868: /*     lf->op = p->tn.op;
                    869: /*     lf->type = p->tn.type;
                    870: /*     lf->goal = p->tn.goal;
                    871: */
                    872:        lf->key = (p->tn.goal<<26) | (p->tn.type<<9) | p->tn.op;
                    873:        memcpy(lf->cst,p->tn.cst,sizeof(int)*NCOSTS);
                    874:        recost_leaf=0;
                    875: }
                    876: 

unix.superglobalmegacorp.com

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