Annotation of coherent/d/bin/cc/c/n1/sel1.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * C compiler.
        !             3:  * Pattern selection.
        !             4:  */
        !             5: #ifdef   vax
        !             6: #include "INC$LIB:cc1.h"
        !             7: #else
        !             8: #include "cc1.h"
        !             9: #endif
        !            10: 
        !            11: #if !TINY
        !            12: #define consnap(x, p)          if (sflag>x) snapf(p)
        !            13: #define consnapv(x, p, v)      if (sflag>x) snapf(p, v)
        !            14: #else
        !            15: #define consnap(x, p)          /* consnap */
        !            16: #define consnapv(x, p, v)      /* consnapv */
        !            17: #endif
        !            18: extern TREE *ripout();
        !            19: 
        !            20: /*
        !            21:  * This table, indexed by a context name,
        !            22:  * returns the appropriate bit set used in the pattern match.
        !            23:  */
        !            24: static PATFLAG nflagtab[] = {
        !            25:        PEFFECT,
        !            26:        PLVALUE,
        !            27:        PRVALUE,
        !            28:        PFNARG,
        !            29:        0,
        !            30:        0,
        !            31:        0,
        !            32:        0,
        !            33:        0,
        !            34:        0,
        !            35:        0,
        !            36:        0,
        !            37:        0,
        !            38:        PEQ,
        !            39:        PNE,
        !            40:        PGT,
        !            41:        PGE,
        !            42:        PLE,
        !            43:        PLT,
        !            44:        PUGT,
        !            45:        PUGE,
        !            46:        PULE,
        !            47:        PULT
        !            48: };
        !            49: 
        !            50: /*
        !            51:  * This routine is the heart of the code selector.
        !            52:  * It looks for a pattern that covers the top level
        !            53:  * operation of tree 'tp' and is in conformance with
        !            54:  * (or can be pulled into conformance with)
        !            55:  * the pattern's shape requirements.
        !            56:  */
        !            57: seltree(tp, c, r)
        !            58: TREE *tp;
        !            59: {
        !            60:        register TREE *lp, *rp;
        !            61:        register PAT  *patp;
        !            62:        PATX *patxp;
        !            63:        TREE *ap;
        !            64:        FLAG lflag, rflag, lpflag, rpflag;
        !            65:        TYPESET ltype, rtype, ntype;
        !            66:        PATFLAG pflag, nflag;
        !            67:        PREGSET savbusy, savxreg;
        !            68:        int ltemp, rtemp, ntemp, stemp, ptemp;
        !            69:        int sgoal;
        !            70:        int clash, h;
        !            71:        int rreg, op, npat, lindex, rindex;
        !            72:        int didstore;
        !            73: 
        !            74:        /* Confirm that the context is consistent
        !            75:         * with the register specified. */
        !            76:        if (c == MLVALUE && isrealreg(r)
        !            77:        && (pertype[tp->t_type].p_kind&reg[r].r_lvalue)==0)
        !            78:                c = MRVALUE;
        !            79:        /* Jump here if the original match was accomplished by coercing a
        !            80:         * subtree into addressibility by a store into an auto temp.
        !            81:         * The tree has been rewritten and must
        !            82:         * be matched again for an earlier ADR|MMX pattern. */
        !            83: rematch:
        !            84: #if !TINY
        !            85:        if (sflag > 1) {
        !            86:                snapf("seltree(%P, %C, ", tp, c);
        !            87:                snapf(c<MFLOW ? "%R" : c<MEQ ? "%d" : "L%d", r);
        !            88:                snapf(") %A curbusy=%M, curxreg=%M\n",
        !            89:                        tp->t_op, curbusy, curxreg);
        !            90:                if (sflag > 2)
        !            91:                        snapf("%W%E%W", "Seltree", tp, NULL);
        !            92:        }
        !            93: #endif
        !            94:        nflag = nflagtab[c];
        !            95:        ntype = pertype[tp->t_type].p_type;
        !            96:        if (tp->t_op < MIOBASE)
        !            97:                return (0);
        !            98:        /* Try for matches with widening conversions deleted.
        !            99:         * Shrink type conversions must remain as
        !           100:         * they may clear or sign extend the operand. */
        !           101:        lp = tp->t_lp;
        !           102:        if (iswiden(lp)) {
        !           103:                ap = lp->t_lp;
        !           104:                if (ap->t_op >= MIOBASE) {
        !           105:                        tp->t_lp = ap;
        !           106:                        if (seltree(tp, c, r))
        !           107:                                return (1);
        !           108:                        tp->t_lp = lp;
        !           109:                }
        !           110:        }
        !           111:        ltype = pertype[lp->t_type].p_type;
        !           112:        if (lp->t_op == FIELD)
        !           113:                lp = lp->t_lp;
        !           114:        lflag = lp->t_flag;
        !           115:        rtype = 0;
        !           116:        rflag = 0;
        !           117:        if ((op = tp->t_op) != FIELD) {
        !           118:                rp = tp->t_rp;
        !           119:                if (rp != NULL) {
        !           120:                        if (iswiden(rp)) {
        !           121:                                ap = rp->t_lp;
        !           122:                                if (ap->t_op >= MIOBASE) {
        !           123:                                        tp->t_rp = ap;
        !           124:                                        if (seltree(tp, c, r))
        !           125:                                                return (1);
        !           126:                                        tp->t_rp = rp;
        !           127:                                }
        !           128:                        }
        !           129:                        rtype = pertype[rp->t_type].p_type;
        !           130:                        rflag = rp->t_flag;
        !           131:                }
        !           132:        }
        !           133:        patxp = &patx[op - MIOBASE];
        !           134:        patp = patxp->px_pp - 1;
        !           135:        npat = patxp->px_npat;
        !           136:        savbusy = curbusy;
        !           137:        savxreg = curxreg;
        !           138:        /* Main search.
        !           139:         * A flying jump to 'again' will try the next pattern.
        !           140:         * The 'patp' is predecremented.
        !           141:         * Yes, this is a bit ugly. */
        !           142: again:
        !           143:        curbusy = savbusy;
        !           144:        curxreg = savxreg;
        !           145:        tp->t_patp = NULL;
        !           146:        if (--npat < 0)
        !           147:                return (0);
        !           148:        ++patp;
        !           149:        consnapv(10, "%I: ", patp);
        !           150:        /* Pattern flag: specifies whether this pattern
        !           151:         * can satisfy the context specified for this tree
        !           152:         * we must have a hit to match. */
        !           153:        pflag = 0;
        !           154:        if (patp->p_flag != 0)
        !           155:                pflag = patcache[patp->p_flag-1];
        !           156:        if ((nflag&pflag) == 0) {
        !           157:                consnap(10, "pflag\n");
        !           158:                goto again;
        !           159:        }
        !           160:        /* Node type: unless pattern specifies no type
        !           161:         * we must have a hit to match. */
        !           162:        if (patp->p_ntype != 0
        !           163:         && (typecache[patp->p_ntype-1]&ntype) == 0) {
        !           164:                consnap(10, "ntype\n");
        !           165:                goto again;
        !           166:        }
        !           167:        /* Left tree type: unless pattern specifies no type
        !           168:         * we must have a hit to match. */
        !           169:        if (patp->p_ltype != 0
        !           170:         && (typecache[patp->p_ltype-1]&ltype) == 0) {
        !           171:                consnap(10, "ltype\n");
        !           172:                goto again;
        !           173:        }
        !           174:        /* Right tree type: unless pattern specifies no type
        !           175:         * we must have a hit to match. */
        !           176:        if (patp->p_rtype != 0
        !           177:         && (typecache[patp->p_rtype-1]&rtype) == 0) {
        !           178:                consnap(10, "rtype\n");
        !           179:                goto again;
        !           180:        }
        !           181:        /* Left tree node type: a mismatch will be coerced
        !           182:         * unless the pattern specifies MMX.
        !           183:         * bytereg(tp) || ... is dgc's kludge to avoid ADR coercion
        !           184:         * of byte oriented operations which actually require a
        !           185:         * register, at least so I (rec) think (thinks). */
        !           186:        lpflag = 0;
        !           187:        if (patp->p_lflag != 0)
        !           188:                lpflag = flagcache[patp->p_lflag-1];
        !           189:        if (lpflag!=0 && (lpflag&lflag)==0
        !           190:        && ((lpflag&T_MMX) != 0
        !           191:        ||  (bytereg(tp) && lflag==0 && (lpflag&T_TREG)==0))) {
        !           192:                consnap(10, "lflag\n");
        !           193:                goto again;
        !           194:        }
        !           195:        /* Right tree node type: a mismatch will be coerced
        !           196:         * unless the pattern rspecifies MMX. */
        !           197:        rpflag = 0;
        !           198:        if (patp->p_rflag != 0)
        !           199:                rpflag = flagcache[patp->p_rflag-1];
        !           200:        if (rpflag!=0 && (rpflag&rflag)==0 && (rpflag&T_MMX)!=0) {
        !           201:                consnap(10, "rflag\n");
        !           202:                goto again;
        !           203:        }
        !           204:        /* This pattern is acceptable.
        !           205:         * The simplest case of a match requires
        !           206:         * only that the pattern pointer be identified.
        !           207:         * The rest of the code in this routine is activated
        !           208:         * by requests for registers, TREG loads, and node type coercion. */
        !           209:        tp->t_patp = patp;
        !           210:        tp->t_used = 0;
        !           211:        /* The pattern may explicitly specify temp
        !           212:         * registers for a subtrees, or the
        !           213:         * subtree temp may have to be allocated
        !           214:         * before the other subtree is selected. */
        !           215:        rtemp = NONE;
        !           216:        if ((rpflag&T_TREG) != 0) {
        !           217:                rtemp = patp->p_rtemp;
        !           218:                if (isrealreg(rtemp)) {
        !           219:                        if (isbusy(rtemp)) {
        !           220:                                consnap(10, "rtemp busy\n");
        !           221:                                goto again;
        !           222:                        }
        !           223:                        setused(tp, rtemp);
        !           224:                } else if ((lpflag&T_TREG)!=0 && (pflag&P_SRT)==0) {
        !           225:                        rtemp = rallo(rp, tp->t_used, 0);
        !           226:                        if (rtemp < 0) {
        !           227:                                consnap(10, "rtemp allo\n");
        !           228:                                goto again;
        !           229:                        }
        !           230:                        consnapv(15, "rtemp = %R\n", rtemp);
        !           231:                        setused(tp, rtemp);
        !           232:                }
        !           233:        }
        !           234:        ltemp = NONE;
        !           235:        if ((lpflag&T_TREG) != 0) {
        !           236:                ltemp = patp->p_ltemp;
        !           237:                if (isrealreg(ltemp)) {
        !           238:                        if (isbusy(ltemp)) {
        !           239:                                consnap(10, "ltemp busy\n");
        !           240:                                goto again;
        !           241:                        }
        !           242:                        setused(tp, ltemp);
        !           243:                } else if ((rpflag&T_TREG)!=0 && (pflag&P_SLT)==0) {
        !           244:                        ltemp = rallo(lp, tp->t_used, 0);
        !           245:                        if (ltemp < 0) {
        !           246:                                consnap(10, "ltemp allo\n");
        !           247:                                goto again;
        !           248:                        }
        !           249:                        consnapv(15, "ltemp = %R\n", ltemp);
        !           250:                        setused(tp, ltemp);
        !           251:                }
        !           252:        }
        !           253:        /* The pattern may require a node temp register.
        !           254:         * If the caller cares, use his preference.
        !           255:         * If PAIR, allocate a pair so that the right and left
        !           256:         * preferences (usually LOTEMP) will work out right.
        !           257:         * The ANY specifier stays around for a while. */
        !           258:        ntemp = patp->p_ntemp;
        !           259:        if (isrealreg(ntemp)) {
        !           260:                if (isbusy(ntemp)) {
        !           261:                        consnap(10, "ntemp busy\n");
        !           262:                        goto again;
        !           263:                }
        !           264:        } else if (ntemp != NONE) {
        !           265:                if ((c==MLVALUE || c==MRVALUE) && isrealreg(r)) {
        !           266:                        ptemp = r;
        !           267:                        clash = 0;
        !           268:                        if (ntemp == PAIR) {
        !           269:                                ptemp = enpair(ptemp);
        !           270:                                if ((h=lohalf(ptemp))!=r && isbusy(h))
        !           271:                                        ++clash;
        !           272:                                if ((h=hihalf(ptemp))!=r && isbusy(h))
        !           273:                                        ++clash;
        !           274:                        }
        !           275:                        if (!clash && isusable(tp, c, ptemp))
        !           276:                                ntemp = ptemp;
        !           277:                }
        !           278:                /* Bind only if we must. */
        !           279:                if (!isrealreg(ntemp)) {
        !           280:                        if (ntemp == PAIR
        !           281:                        || (ltemp==LOTEMP || ltemp==HITEMP)
        !           282:                        || (rtemp==LOTEMP || rtemp==HITEMP)) {
        !           283:                                ntemp = regselect(tp, ntemp, 1);
        !           284:                                if (ntemp < 0) {
        !           285:                                        consnap(10, "ntemp select\n");
        !           286:                                        goto again;
        !           287:                                }
        !           288:                        }
        !           289:                }
        !           290:        }
        !           291:        if (isrealreg(ntemp) && rp!=NULL) {
        !           292:                consnapv(15, "ntemp = %R\n", ntemp);
        !           293:                setused(tp, ntemp);
        !           294:        }
        !           295:        /* If the pattern specifies addressible
        !           296:         * subtrees and the subtrees are not directly
        !           297:         * addressible, then index registers will be
        !           298:         * required to hold the offset expression. */
        !           299:        lindex = rindex = -1;
        !           300:        if (ishlvadr(rpflag) && !isadr(rflag)) {
        !           301:                if (!isofs(rflag))
        !           302:                        cbotch("no rofs");
        !           303:                ap = findoffs(rp);
        !           304:                if ((rindex = rallo(ap, tp->t_used, 2)) < 0) {
        !           305:                        consnap(10, "rindex allo\n");
        !           306:                        goto again;
        !           307:                }
        !           308:                consnapv(15, "rindex = %R\n", rindex);
        !           309:                curxreg |= reg[rindex].r_phys;
        !           310:        }
        !           311:        if (ishlvadr(lpflag) && !isadr(lflag)) {
        !           312:                if (!isofs(lflag))
        !           313:                        cbotch("no lofs");
        !           314:                ap = findoffs(lp);
        !           315:                if ((lindex = rallo(ap, tp->t_used, 2)) < 0) {
        !           316:                        consnap(10, "lindex allo\n");
        !           317:                        goto again;
        !           318:                }
        !           319:                consnapv(15, "lindex = %R\n", lindex);
        !           320:                curxreg |= reg[lindex].r_phys;
        !           321:        }
        !           322:        consnap(10, "\n");
        !           323:        /* If the pattern specifies T_TREG, then
        !           324:         * the subtree must be selected. */
        !           325:        if ((rpflag&T_TREG) != 0) {
        !           326:                /* In case two TREG's are specified the ltemp
        !           327:                 * must be identified and setbusy before the rtemp
        !           328:                 * is loaded or ltemp may be clobbered. */
        !           329: 
        !           330:                /* Select an rtemp register based on the share flag,
        !           331:                 * the rtemp preference, and the node preference */
        !           332:                if ((pflag&P_SRT) != 0
        !           333:                && (rtemp==ANYL || rtemp==ANYR)
        !           334:                &&  isrealreg(r)
        !           335:                &&  isusable(tp, c, r))
        !           336:                        stemp = r;
        !           337:                else
        !           338:                        stemp = reguse(rtemp, ntemp);
        !           339:                /* Select the subcontext depending on the register selected
        !           340:                 * or the currently specified context */
        !           341:                sgoal = subgoal(c, stemp);
        !           342:                /* Now load the specified register or preferred type */
        !           343:                if (select(rp, sgoal, stemp) == 0)
        !           344:                        goto again;
        !           345:                tp->t_used |= rp->t_used;
        !           346:                if ((pflag&P_SRT) != 0) {
        !           347:                        if ((ntemp==ANYL || ntemp==ANYR)
        !           348:                        &&   isusable(tp, c, rp->t_rreg))
        !           349:                                ntemp = rp->t_rreg;
        !           350:                        else if (patp->p_ntemp == patp->p_rtemp
        !           351:                         && ntemp != rp->t_rreg) {
        !           352:                                consnap(10, "rtemp share\n");
        !           353:                                goto again;
        !           354:                        }
        !           355:                } else
        !           356:                        setbusy(rp->t_rreg);    /* This is wrong */
        !           357:                        /* Should be set busy after the ltemp load */
        !           358: 
        !           359:                /* If ltemp was setbusy above, it should now be freed */
        !           360:        }
        !           361:        if ((lpflag&T_TREG) != 0) {
        !           362:                if ((pflag&P_SLT) != 0
        !           363:                && (ltemp==ANYL || ltemp==ANYR)
        !           364:                &&  isrealreg(r)
        !           365:                &&  isusable(tp, c, r))
        !           366:                        stemp = r;
        !           367:                else
        !           368:                        stemp = reguse(ltemp, ntemp);
        !           369:                sgoal = subgoal(c, stemp);
        !           370:                if (select(lp, sgoal, stemp) == 0)
        !           371:                        goto again;
        !           372:                tp->t_used |= lp->t_used;
        !           373:                if ((pflag&P_SLT) != 0) {
        !           374:                        if ((ntemp==ANYL || ntemp==ANYR)
        !           375:                        &&   isusable(tp, c, lp->t_rreg))
        !           376:                                ntemp = lp->t_rreg;
        !           377:                        else if (patp->p_ntemp == patp->p_ltemp
        !           378:                         && ntemp != lp->t_rreg) {
        !           379:                                consnap(10, "ltemp share\n");
        !           380:                                goto again;
        !           381:                        }
        !           382:                } else
        !           383:                        setbusy(lp->t_rreg);
        !           384:        }
        !           385:        /* Now bind the node temporary if it hasn't already happened. */
        !           386:        if (!isrealreg(ntemp) && ntemp!=NONE) {
        !           387:                ntemp = regselect(tp, ntemp, 1);
        !           388:                if (ntemp < 0) {
        !           389:                        consnap(10, "ntemp select\n");
        !           390:                        goto again;
        !           391:                }
        !           392:        }
        !           393:        tp->t_treg = ntemp;
        !           394:        /* Keep temps used in node coercion off target path */
        !           395:        if (ntemp!=NONE && rp!=NULL)
        !           396:                setused(tp, ntemp);
        !           397:        /* Force ltemp and rtemp used */
        !           398:        if ((lpflag&T_TREG)==0 && isrealreg(patp->p_ltemp))
        !           399:                setused(tp, patp->p_ltemp);
        !           400:        if ((rpflag&T_TREG)==0 && isrealreg(patp->p_rtemp))
        !           401:                setused(tp, patp->p_rtemp);
        !           402:        /* Now coerce the subtrees into rv or lv addressibility
        !           403:         * if they do not naturally conform. */
        !           404:        didstore = 0;
        !           405:        if (selmiss(rpflag, rflag) && isrvadr(rpflag) && !isadr(rflag))
        !           406:                selrv(tp, 1, &didstore);
        !           407:        if (selmiss(lpflag, lflag) && isrvadr(lpflag) && !isadr(lflag))
        !           408:                selrv(tp, 0, &didstore);
        !           409:        if (selmiss(rpflag, rflag) && islvadr(rpflag) && !isadr(rflag))
        !           410:                sellv(tp, rindex, 1, &didstore);
        !           411:        if (selmiss(lpflag, lflag) && islvadr(lpflag) && !isadr(lflag))
        !           412:                sellv(tp, lindex, 0, &didstore);
        !           413:        /* If coercion generated a stack temp,
        !           414:         * then we must search the table again
        !           415:         * for a simpler pattern, after cleaning
        !           416:         * up any FIXUP's */
        !           417:        if (didstore) {
        !           418:                tp = ripout(tp, 0);
        !           419:                curbusy = savbusy;
        !           420:                curxreg = savxreg;
        !           421:                consnap(1, "Goto rematch\n");
        !           422:                goto rematch;
        !           423:        }
        !           424:        /* Make node temp used */
        !           425:        if (ntemp != NONE)
        !           426:                setused(tp, ntemp);
        !           427:        /* Compute the result register */
        !           428:        if ((rreg = patp->p_result) == TEMP)
        !           429:                rreg = ntemp;
        !           430:        else if (rreg == LOTEMP)
        !           431:                rreg = lohalf(ntemp);
        !           432:        else if (rreg == HITEMP)
        !           433:                rreg = hihalf(ntemp);
        !           434:        tp->t_rreg = rreg;
        !           435:        if (rreg != NONE)
        !           436:                setused(tp, rreg);
        !           437:        curbusy = savbusy;
        !           438:        curxreg = savxreg;
        !           439:        return (1);
        !           440: }

unix.superglobalmegacorp.com

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