Annotation of researchv9/cmd/sun/c2/branch.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static char sccsid[] = "@(#)branch.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 "as.h"
        !            10: #include "c2.h"
        !            11: 
        !            12: char *unbranch[] = { 
        !            13:      "jne", "jeq", "jgt", "jlt", "jge", "jle", 
        !            14:      "jhi", "jls", "jpl", "jmi", "jf", 
        !            15:      "jcc", "jcs", "jvc", "jvs", "jra",
        !            16:      "jfneq", "jfeq", "jfnlt", "jflt",
        !            17:      "jfnle", "jfle", "jfngt", "jfgt",
        !            18:      "jfnge", "jfge",
        !            19:      "fjneq", "fjeq", "fjngt", "fjgt", "fjnge", "fjge",
        !            20:      "fjnlt", "fjlt", "fjnle", "fjle", "fjngl", "fjgl",
        !            21:      "fjngle", "fjgle", "fjule", "fjogt", "fjult", "fjoge",
        !            22:      "fjuge", "fjolt", "fjugt", "fjole", "fjueq", "fjogl",
        !            23:      "fjun", "fjor", "fjst", "fjsf", "fjsneq", "fjseq"
        !            24: };
        !            25: extern NODE *deletenode();
        !            26: 
        !            27: NODE *
        !            28: insert_label( p ) 
        !            29:     register NODE *p;
        !            30: {
        !            31:     static int newlabno = 0;
        !            32:     register NODE *l;
        !            33:     register struct sym_bkt *s;
        !            34:     char labname[20];
        !            35: 
        !            36:     l = new();
        !            37:     l->op = OP_LABEL;
        !            38:     l->nref = 0;
        !            39:     sprintf( labname, "LY%05d", newlabno++ );
        !            40:     l->name = s = lookup(labname);
        !            41:     s->attr_s |= S_DEF|S_DEC;
        !            42:     s->csect_s = C_TEXT;
        !            43:     s->where_s = l;
        !            44:     l->forw = p;
        !            45:     l->back = p->back;
        !            46:     l->back->forw = l;
        !            47:     p->back = l;
        !            48:     l->ruse = l->rset = regmask0;
        !            49:     l->rlive = l->forw->rlive;
        !            50:     return l;
        !            51: }
        !            52: 
        !            53: NODE *
        !            54: merge_labels( to, from )
        !            55:     register NODE * to, *from ;
        !            56: {
        !            57:     /*
        !            58:      * there are two kinds of labels:
        !            59:      * those all of whose references we can find, and
        !            60:      * the others.
        !            61:      * In the latter case, we will want to move the label,
        !            62:      * and let someone smarter than us drop the equate.
        !            63:      */
        !            64:     register refs = 0;
        !            65:     register NODE *luse;
        !            66:     if (from->luse!=NULL){
        !            67:        for ( luse=from->luse; ; luse=luse->lnext ){
        !            68:            luse->luse = to;
        !            69:            refs++;
        !            70:            if (luse->lnext==NULL) break;
        !            71:        }
        !            72:        luse->lnext=to->luse;
        !            73:        to->luse =from->luse;
        !            74:     }
        !            75:     if (refs == from->nref){
        !            76:        from = deletenode( from )->forw;
        !            77:        meter.nrlab++;
        !            78:     } else {
        !            79:        /*
        !            80:         * at this point there are not references on our list, but
        !            81:         * still references to this label somewhere out there
        !            82:         * move the damn thing 
        !            83:         * and null out the use list
        !            84:         */
        !            85:        NODE *temp;
        !            86:        from->nref -= refs;
        !            87:        from->luse = NULL;
        !            88:        temp = from->forw;
        !            89:        from->back->forw = from->forw;
        !            90:        from->forw->back = from->back;
        !            91:        from->forw = to->forw;
        !            92:        from->forw->back = from;
        !            93:        from->back = to;
        !            94:        to->forw = from;
        !            95:        from = temp;
        !            96:     }
        !            97:     to->nref += refs;
        !            98:     return from;
        !            99: }
        !           100: 
        !           101: int
        !           102: fallthrough( t )
        !           103:     register NODE *t;
        !           104: {
        !           105:     /*
        !           106:      * return 0 if t is a node that cannot "fall through" to the
        !           107:      * next instruction, such as an unconditional jump or code-
        !           108:      * emitting pseudo-instruction
        !           109:      * return 1 if this is not the case.
        !           110:      */
        !           111:     if (ISDIRECTIVE(t->op) ) return 1;
        !           112:     else if (ISPSEUDO(t->op) ) return 0;
        !           113:     else switch (t->op){
        !           114:        case OP_CSWITCH:
        !           115:        case OP_FIRST:
        !           116:        case OP_EXIT:
        !           117:            return 0;
        !           118:        case OP_BRANCH:
        !           119:        case OP_JUMP:
        !           120:            return  t->subop!=JALL;
        !           121:        default:
        !           122:            return 1;
        !           123:     }
        !           124:     /* NOTREACHED */
        !           125: }
        !           126: 
        !           127: 
        !           128: # define nexti( t ) while( t->op==OP_LABEL ) t=t->forw
        !           129: tangle()
        !           130: {
        !           131:     /*
        !           132:      * remove:
        !           133:      *   trivial jumps
        !           134:      *   jumps to jumps
        !           135:      *   jumps around jumps
        !           136:      */
        !           137:     
        !           138:     int changed = 1;
        !           139:     int niter=0;
        !           140:     register NODE *p, *t, *u;
        !           141:     NODE *j, *jdest, *savelabel;
        !           142: 
        !           143:     while (changed){
        !           144:        changed=0;
        !           145:        for (p=first.forw; p!=&first; p=p->forw){
        !           146:            if ((p->op==OP_JUMP&&p->subop!=JIND)||p->op==OP_CSWITCH){
        !           147:                t = p->luse;
        !           148:                nexti( t );
        !           149:                if (t==p){
        !           150:                    /* selfloop */
        !           151:                    if (p->luse->nref==1 && !fallthrough(p->back)){
        !           152:                        /* unreachable */
        !           153:                        unreference( p->luse, p);
        !           154:                        p = deletenode( p );
        !           155:                        meter.nbrbr++;
        !           156:                        changed++;
        !           157:                    }
        !           158:                    continue;
        !           159:                }
        !           160:                if (t->op==p->op && (t->subop==JALL || t->subop==p->subop)){
        !           161:                    /* jump-to-jump -- remove the middle reference */
        !           162:                    if (p->luse==t->luse){
        !           163:                        /* jump into selfloop */
        !           164:                        continue;
        !           165:                    }
        !           166:                    unreference( p->luse, p);
        !           167:                    newreference( t->luse, p);
        !           168:                    t = p->luse;
        !           169:                    nexti( t );
        !           170:                    meter.nbrbr++;
        !           171:                    changed++;
        !           172:                }
        !           173:                if (p->op==OP_CSWITCH ) continue;
        !           174:                if (p->luse==p->forw){
        !           175:                    /* trivial jump */
        !           176:                    unreference( p->luse, p);
        !           177:                    p = deletenode( p );
        !           178:                    changed++;
        !           179:                    meter.njp1++;
        !           180:                    continue;
        !           181:                }
        !           182:                if (p->subop == JALL){
        !           183:                    u = (t=p->luse)->back;
        !           184:                    /* find the non-pseudo-op before the destination */
        !           185:                    while (ISDIRECTIVE(u->op))
        !           186:                        u = u->back;
        !           187:                    if ( t->nref==1 && ( u->op==OP_FIRST ||
        !           188:                    ((u->op==OP_JUMP&&u->subop==JALL)|| u->op==OP_EXIT))){
        !           189:                        /*
        !           190:                         * this piece of code is reachable from p but not by
        !           191:                         * fall through. move it to after p and delete 
        !           192:                         * the jump. stop moving after a cswitch 
        !           193:                         * or unconditional goto or return.
        !           194:                         */
        !           195:                        jdest = u->luse;
        !           196:                        savelabel = 0;
        !           197:                        u = t;
        !           198:                        while ((u=u->forw)->op!= OP_FIRST){
        !           199:                            if (u->op==OP_LABEL ){
        !           200:                                if ( u->back->op==OP_CSWITCH )
        !           201:                                    break;
        !           202:                                else if (savelabel != jdest 
        !           203:                                && !(u->forw->op==OP_CSWITCH ) )
        !           204:                                    savelabel = u;
        !           205:                            }else if ((u->op==OP_JUMP && u->subop==JALL)
        !           206:                            || u->op==OP_EXIT ){
        !           207:                                u = u->forw;
        !           208:                                break;
        !           209:                            }
        !           210:                        }
        !           211:                        /* t points to the first node to move, and    */
        !           212:                        /* u points to the first node not to move.    */
        !           213:                        j = u->back;
        !           214:                        if (j==p){
        !           215:                            /*
        !           216:                             * oh, my... a loop. It may be without any 
        !           217:                             * way in, but I'm too 'fraid to try deleteing
        !           218:                             * it. Lets try pivoting around an appropriate
        !           219:                             * label in the loop.
        !           220:                             */
        !           221:                             if (savelabel){
        !           222:                                u = savelabel;
        !           223:                                j = u->back;
        !           224:                            } else
        !           225:                                 continue;
        !           226:                        }
        !           227:                        if (j->op != OP_CSWITCH 
        !           228:                        && !(j->op==OP_JUMP && j->subop==JALL)
        !           229:                        && j->op != OP_EXIT
        !           230:                        && u->op==OP_LABEL){
        !           231:                            /* add unconditional branch here */
        !           232:                            j->forw = new();
        !           233:                            j->forw->back = j;
        !           234:                            j = j->forw;
        !           235:                            cannibalize( j, "jra" );
        !           236:                            j->op = OP_JUMP; /* rather than OP_BRANCH */
        !           237:                            newreference( u, j);
        !           238:                        }
        !           239:                        u->back = t->back;
        !           240:                        t->back->forw = u;
        !           241:                        t->back = p;
        !           242:                        j->forw = p->forw;
        !           243:                        p->forw->back = j;
        !           244:                        p->forw = t;
        !           245:                        /* the details will take care of themselves */
        !           246:                        p = p->back;
        !           247:                        changed++;
        !           248:                        meter.ncmot++;
        !           249:                        continue;
        !           250:                    }
        !           251:                    /* delete dead code after unconditional branch */
        !           252:                    /* should do after exits, too */
        !           253:                    u = p->forw;
        !           254:                    while ((t=u)->op!=OP_LABEL && t->op!=OP_FIRST
        !           255:                      && t->op != OP_EXIT){
        !           256:                        u = t->forw;
        !           257:                        if (ISPSEUDO( t->op ))
        !           258:                            continue; /* don't delete pseudoops */
        !           259:                        if (ISBRANCH(t->op))
        !           260:                            unreference( t->luse, t);
        !           261:                        (void)deletenode( t );
        !           262:                        meter.iaftbr++;
        !           263:                        changed++;
        !           264:                    }
        !           265:                } else {
        !           266:                    /* here for conditional branches */
        !           267:                    u = p->forw;
        !           268:                    /* may be no intervening branches here */
        !           269:                    if (u->op==p->op && (u->subop==JALL || u->subop==p->subop)){
        !           270:                        j = u;
        !           271:                        u = u->forw;
        !           272:                        nexti( u );
        !           273:                        if (u==t){
        !           274:                            /* jump-around-jump -- reverse condition, go directly */
        !           275:                            cannibalize( j, unbranch[(int)(p->subop)-(int)JEQ] );
        !           276:                            j->op = OP_JUMP; /* cannibalize makes an OP_BRANCH*/
        !           277:                            unreference( p->luse, p );
        !           278:                            p = deletenode( p );
        !           279:                            meter.nrevbr++;
        !           280:                            changed++;
        !           281:                        }
        !           282:                    } else if ( (int)p->subop <= (int)JNONE && u->op==OP_DJMP && u->subop==JNONE){
        !           283:                        /*
        !           284:                         *     jXX Y
        !           285:                         *     dbra dZ,W
        !           286:                         * should be changed to:
        !           287:                         *     dbXX dZ,W
        !           288:                         *     jXX  Y
        !           289:                         * because its faster. If label Y directly follows 
        !           290:                         * the dbra, the jump can be deleted entirely!
        !           291:                         */
        !           292:                        static char dbname[5] = {'d', 'b', '\0', '\0', '\0'};
        !           293:                        /* 
        !           294:                         * since we cannot search for the correct instruction
        !           295:                         * indexed by op and subop, we need to synthesize the
        !           296:                         * new name and call cannibalize.
        !           297:                         * jump instruction is of form [jb]CC[ls].
        !           298:                         */
        !           299:                        dbname[2] = p->instr->text_i[1];
        !           300:                        dbname[3] = p->instr->text_i[2];
        !           301:                        cannibalize( u, dbname );
        !           302:                        u->op = OP_DJMP;
        !           303: 
        !           304:                        /*
        !           305:                         * unhook p from the list, reinsert it later
        !           306:                         */
        !           307:                        u = u->forw;
        !           308:                        nexti( u );
        !           309:                        if (u==t){
        !           310:                            unreference( p->luse, p );
        !           311:                            deletenode(p);
        !           312:                            meter.nskip++;
        !           313:                        } else {
        !           314:                            p->back->forw = p->forw;
        !           315:                            p->forw->back = p->back;
        !           316:                            p->forw = p->back = 0;
        !           317:                            insert( p, u->back );
        !           318:                            meter.ndbrarev++;
        !           319:                        }
        !           320:                        p = u->back;
        !           321:                        changed++;
        !           322:                    }
        !           323:                }
        !           324:            }
        !           325:        }
        !           326:        if (++niter > 1000) sys_error("Tangled control-flow logic");
        !           327:     }
        !           328:     return niter-1;
        !           329: }
        !           330: 
        !           331: zipper()
        !           332: {
        !           333:     /*
        !           334:      * For each label: look at all the jumps to that label:
        !           335:      *    for those that are unconditional:
        !           336:      *        compare the instructions preceeding to the
        !           337:      *        instructions preceeding the label. The unconditional
        !           338:      *        jump could jump to an earlier point in the "fall through"
        !           339:      *        flow.
        !           340:      */
        !           341:     
        !           342:     register NODE *l, *u, *prec, *uprec, *luse;
        !           343:     NODE *pr, *upr;
        !           344:     int refs;
        !           345:     int nchange=0, didchange;
        !           346: 
        !           347:     for (l=first.forw; l!= &first; l=l->forw){
        !           348:        if (l->op!=OP_LABEL) continue;
        !           349:        prec = l->back;
        !           350:        /* skip over stabs */
        !           351:        while (ISDIRECTIVE(prec->op) )
        !           352:            prec=prec->back;
        !           353:        if (!ISINSTRUC(prec->op))
        !           354:            continue;
        !           355:        if (prec->op==OP_CSWITCH ) continue;
        !           356:        if ((prec->op==OP_BRANCH || prec->op==OP_JUMP) && prec->subop==JALL)
        !           357:            continue;
        !           358:        pr = prec;
        !           359:        for (u = l->luse; u!=NULL; u=upr, prec=pr){
        !           360:            upr = u->lnext;
        !           361:            uprec = u->back;
        !           362:            didchange=0;
        !           363:            if (u->op!=OP_JUMP || u->subop!=JALL) continue;
        !           364:            while (ISDIRECTIVE(uprec->op) )
        !           365:                uprec=uprec->back;
        !           366:            if (uprec->op==OP_FIRST) continue;
        !           367:            while(1){
        !           368:                if (uprec->op != prec->op ){
        !           369:                    if (prec->op==OP_LABEL){
        !           370:                        /* skip it */
        !           371:                        prec=prec->back;
        !           372:                        continue;
        !           373:                    }else 
        !           374:                        break;
        !           375:                }
        !           376:                if (prec==uprec || prec==u || uprec==upr) break;
        !           377:                if  (prec->op == OP_LABEL ){
        !           378:                    uprec = merge_labels( prec, uprec );
        !           379:                    didchange++;
        !           380:                } else{
        !           381:                    if (ISPSEUDO( prec->op )) goto endzip;
        !           382:                    if (!sameins( prec, uprec) ) goto endzip;
        !           383:                    if (ISBRANCH(prec->op))
        !           384:                        if (prec->luse != uprec->luse)
        !           385:                            goto endzip;
        !           386:                        else
        !           387:                            unreference( uprec->luse, uprec);
        !           388:                    uprec = deletenode( uprec )->forw;
        !           389:                    didchange++;
        !           390:                }
        !           391:                prec=prec->back;
        !           392:                uprec=uprec->back;
        !           393:            }
        !           394: endzip:
        !           395:            if (didchange){
        !           396:                /*
        !           397:                 * we may have done something here.
        !           398:                 * uprec addresses the first NON-common node we found.
        !           399:                 * put the jump after it.
        !           400:                 */
        !           401:                if ( uprec->forw != u ){
        !           402:                    uprec->forw->back = u;
        !           403:                    u->back->forw = u->forw;
        !           404:                    u->forw->back = u->back;
        !           405:                    u->forw = uprec->forw;
        !           406:                    uprec->forw = u;
        !           407:                    u->back = uprec;
        !           408:                }
        !           409:                if (prec->op!=OP_LABEL)
        !           410:                    prec = insert_label( prec->forw );
        !           411:                unreference( u->luse, u);
        !           412:                newreference( prec, u);
        !           413:                u->rlive = u->luse->rlive;
        !           414:                nchange++;
        !           415:            }
        !           416:        }
        !           417:     }
        !           418:     meter.ncomj += nchange;
        !           419:     return nchange;
        !           420: }
        !           421: 
        !           422: int
        !           423: tmerge()
        !           424: {
        !           425:     /*
        !           426:      * For each label, z,  in the program, try to find commonality
        !           427:      * amoung the pieces of code that end up at that label.
        !           428:      * We are very cautious.
        !           429:      * We are looking for the forms:
        !           430:      *            jra  elsewhere
        !           431:      *   L: X
        !           432:      *      X
        !           433:      *     jra  z
        !           434:      * and
        !           435:      *     jYY L
        !           436:      *     X
        !           437:      *    X
        !           438:      *    jra  z
        !           439:      *  L:
        !           440:      * which we can combine for smaller and no-slower code.
        !           441:      */
        !           442:     
        !           443:     NODE *z;
        !           444:     register NODE *a, *b;
        !           445:     NODE *ajmp;
        !           446:     NODE *bnext, *anext, *t;
        !           447:     NODE *bforw, *aforw;
        !           448:     int nchanged = 0;
        !           449: 
        !           450:     for (z=first.forw; z!=&first; z=z->forw){
        !           451:        if (z->op != OP_LABEL) continue;
        !           452:        for (ajmp=z->luse; ajmp!=NULL; ajmp=anext){
        !           453:            anext=ajmp->lnext;
        !           454:            if (ajmp->op != OP_JUMP || ajmp->subop != JALL) continue;
        !           455:            for (b=ajmp->lnext; b!=NULL; b=bnext){
        !           456:                bnext=b->lnext;
        !           457:                if (b->op != OP_JUMP || b->subop != JALL) continue;
        !           458:                bforw = b->forw;
        !           459:                a = ajmp;
        !           460:                aforw = a->forw;
        !           461:                /*
        !           462:                 * compare backwards until:
        !           463:                 * -- we hit a non-equality, or
        !           464:                 * -- we hit a label, or
        !           465:                 * -- we hit a jump
        !           466:                 */
        !           467:                for ( a=a->back, b=b->back;
        !           468:                    a->op!=OP_FIRST && b->op!=OP_FIRST;
        !           469:                    a=a->back, b=b->back){
        !           470: 
        !           471:                    while (ISDIRECTIVE( a->op ))
        !           472:                        a=a->back;
        !           473:                    while (ISDIRECTIVE( b->op ))
        !           474:                        b=b->back;
        !           475:                    switch (a->op){
        !           476:                    default:   /*            |   */
        !           477:                        if ( ISPSEUDO(a->op) || !sameins( a, b ) ) break;
        !           478:                        continue;
        !           479:                    case OP_JUMP:
        !           480:                    case OP_LABEL:
        !           481:                    case OP_CSWITCH:
        !           482:                        break; /* to outer break */
        !           483:                    }/* +--------------------+   */
        !           484:                     /* v                        */
        !           485:                    break; /* out of for loop */
        !           486:                }/* +---------------------+   */
        !           487:                /*  v
        !           488:                 * we have now compared just a little too far:
        !           489:                 * either *a != *b , or they are both pseudo-ops,
        !           490:                 * jumps, labels, or something else unspeakable.
        !           491:                 */
        !           492:                a = a->forw;
        !           493:                b = b->forw;
        !           494:                if (a == ajmp)
        !           495:                    /* no equal sequences */
        !           496:                    continue;
        !           497:                /* look for preceeding label, preceeded by unconditional jump */
        !           498:                if (b->back->op == OP_LABEL && (fallthrough(b->back->back) 
        !           499:                || (a->back->op == OP_JUMP && a->back->luse == aforw)) ){
        !           500:                    /* want to merge into "b" -- exchange */
        !           501:                    t = b; b = a; a = t;
        !           502:                    t = bforw; bforw = aforw; aforw = t;
        !           503:                    /* and fall through into "a" test, which will succeed */
        !           504:                }
        !           505:                if (a->back->op == OP_LABEL){
        !           506:                    if ( (t=b->back)->op == OP_LABEL && !fallthrough(t->back)){
        !           507:                        /* merge into "a" */
        !           508:                        (void)merge_labels( a->back, t);
        !           509:                        /* cream junk trailing merged-out code */
        !           510:                        if (anext == bforw->back)
        !           511:                            anext = NULL;
        !           512:                        while ( b!=bforw ){
        !           513:                            if (ISBRANCH(b->op))
        !           514:                                unreference( b->luse, b );
        !           515:                            b = deletenode( b )->forw;
        !           516:                        }
        !           517:                        nchanged++;
        !           518:                        break;
        !           519:                    } else if (t->op == OP_JUMP && t->luse == bforw ){
        !           520:                        a = a->back; /* "a" now addresses label */
        !           521:            cond_jumparound:
        !           522:                        /* 
        !           523:                         * delete "b" code, complement branch condition,
        !           524:                         * change branch target to "a" 
        !           525:                         */
        !           526:                        if (anext == bforw->back)
        !           527:                            anext = NULL;
        !           528:                        while ( b!=bforw ){
        !           529:                            if (ISBRANCH(b->op))
        !           530:                                unreference( b->luse, b );
        !           531:                            b = deletenode( b )->forw;
        !           532:                        }
        !           533:                        unreference( t->luse, t);
        !           534:                        newreference( a, t);
        !           535:                        cannibalize( t, unbranch[(int)(t->subop)-(int)JEQ] );
        !           536:                        t->op = OP_JUMP; /* not BRANCH */
        !           537:                        nchanged++;
        !           538:                        break;
        !           539:                    } else if (!fallthrough( a->back->back) ){
        !           540:                        /*
        !           541:                         * we can just move label "a" to before "b"
        !           542:                         * and delete the rest of the "a" code
        !           543:                         */
        !           544:                        while (a != aforw ){
        !           545:                            if (ISBRANCH(a->op))
        !           546:                                unreference( a->luse, a );
        !           547:                            a = deletenode( a )->forw;
        !           548:                        }
        !           549:                        a->back->back->forw = a;
        !           550:                        a->back->forw = b;
        !           551:                        t->forw = a->back;
        !           552:                        a->back = a->back->back;
        !           553:                        t->forw->back = t;
        !           554:                        b->back = t->forw;
        !           555:                        nchanged++;
        !           556:                        break;
        !           557:                    }
        !           558:                    /* else out of luck */
        !           559:                } else if (a->back->op == OP_JUMP && a->back->luse == aforw
        !           560:                && b->back->op == OP_JUMP && b->back->luse == bforw ){
        !           561:                    /* 
        !           562:                     * must insert new label, then treat like one of
        !           563:                     * the labelled cases above.
        !           564:                     */
        !           565:                    a = insert_label( a );
        !           566:                    t = b->back;
        !           567:                    goto cond_jumparound;
        !           568:                }
        !           569:            }
        !           570:        }
        !           571:     }
        !           572:     meter.ncomj += nchanged;
        !           573:     return nchanged;
        !           574: }
        !           575: 
        !           576: /*
        !           577:  * assign a sequential node number to each node.
        !           578:  * Sequence is used to detect backwards edges.
        !           579:  */
        !           580: order_nodes()
        !           581: {
        !           582:     register NODE *n;
        !           583:     register nodenumber;
        !           584: 
        !           585:     nodenumber = 0;
        !           586:     for (n = first.forw; n != &first; n = n->forw) {
        !           587:        n->lineno = nodenumber++;
        !           588:     }
        !           589: }
        !           590: 
        !           591: /*
        !           592:  * change test-at-the-top loops to test-at-the-bottom
        !           593:  * with a jump to the test at the front.
        !           594:  * In order that we not get confused and loop forever moving the test
        !           595:  * back and forth, we will recompute the node ordering every time a
        !           596:  * loop is inverted.
        !           597:  */
        !           598: int
        !           599: invloop()
        !           600: {
        !           601:     int nchanged;
        !           602:     register NODE *n;
        !           603:     register nodenumber;
        !           604:     register NODE *headlabel, *taillabel;
        !           605:     NODE *jump, *newlabel;
        !           606: 
        !           607:     nchanged = 0;
        !           608:     order_nodes();
        !           609:     for (n = first.forw; n != &first; n = n->forw){
        !           610:        /*
        !           611:         * look for this configuaration:
        !           612:         * headlabel -> Lx:
        !           613:         *                  <some instructions ( the test )>
        !           614:         * n         ->      conditional jump to Ly
        !           615:         *                  <some more instructions ( the loop body )>
        !           616:         * jump      ->     jra Lx
        !           617:         * taillabel -> Ly:
        !           618:         * If there are many conditional jumps (as in the case of 
        !           619:         * while( xx && yy)) then we can key off of any of the jumps, 
        !           620:         * but the first one makes the most sense, since it will be 
        !           621:         * executed the most frequently.
        !           622:         */
        !           623:        if (n->op == OP_JUMP && n->subop != JALL && 
        !           624:        (taillabel = n->luse)->lineno > n->lineno){
        !           625:            jump = taillabel->back;
        !           626:            if (jump->op == OP_JUMP && jump->subop == JALL &&
        !           627:            (headlabel = jump->luse)->lineno < n->lineno){
        !           628:                /* 
        !           629:                 * Got it: now reorganize as:
        !           630:                 * Lx:
        !           631:                 *      jmp Lnew2
        !           632:                 * Lnew1:
        !           633:                 *      < some instructions ( the loop body ) >
        !           634:                 * Lnew2:
        !           635:                 *      < some more instructions ( the test ) >
        !           636:                 *      conditional jump to Lnew1 ( reversed conditions )
        !           637:                 * Ly:
        !           638:                 * in the simple cases, Lx and Ly will become unused at this
        !           639:                 * point.
        !           640:                 */
        !           641:                /* move test & jmp code to after the jump */
        !           642:                unreference( headlabel, jump );
        !           643:                jump->forw = headlabel->forw;
        !           644:                headlabel->forw = n->forw;
        !           645:                n->forw->back = headlabel;
        !           646:                n->forw = taillabel;
        !           647:                taillabel->back = n;
        !           648:                jump->forw->back = jump;
        !           649:                /* delete the jump, replace by a label */
        !           650:                newlabel = insert_label( deletenode( jump )->forw );
        !           651:                /* insert new jump to new label at head of loop */
        !           652:                jump = new();
        !           653:                jump->forw = headlabel->forw;
        !           654:                headlabel->forw = jump;
        !           655:                jump->back = headlabel;
        !           656:                jump->forw->back = jump;
        !           657:                cannibalize( jump, "jra" );
        !           658:                jump->op = OP_JUMP; /* rather than OP_BRANCH */
        !           659:                newreference( newlabel, jump );
        !           660:                /* add another new label after the new jump */
        !           661:                newlabel = insert_label( jump->forw );
        !           662:                /* flip condition on conditional, point it at the new label */
        !           663:                cannibalize( n, unbranch[(int)(n->subop)-(int)JEQ] );
        !           664:                n->op = OP_JUMP; /* rather than OP_BRANCH */
        !           665:                unreference( taillabel, n );
        !           666:                newreference( newlabel, n );
        !           667:                order_nodes();
        !           668:                n = taillabel->back;
        !           669:                /* if either of the old labels is superfluous, delete it */
        !           670:                if (headlabel->nref == 0 ) (void)deletenode(headlabel);
        !           671:                if (taillabel->nref == 0 ) (void)deletenode(taillabel);
        !           672:                nchanged++;
        !           673:                meter.loopiv++;
        !           674:            }
        !           675:        }
        !           676:     }
        !           677:     return nchanged;
        !           678: }
        !           679: 
        !           680: chase(n,tail)
        !           681:     register NODE *n, *tail;
        !           682: {
        !           683:     register NODE *p;
        !           684:     if (n == tail)
        !           685:        return;
        !           686:     for (p = n->forw; p != n; p = p->forw) {
        !           687:        if (p == tail)
        !           688:            return;
        !           689:     }
        !           690:     printf("lost track of node %s\n", tail);
        !           691: }

unix.superglobalmegacorp.com

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