Annotation of coherent/d/bin/cc/c/n1/sel1.c, revision 1.1.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.