|
|
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®[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]<ype) == 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.