|
|
1.1 root 1: /* @(#) allo.c: 1.6 2/23/84 */
2:
3: # include "mfile2.h"
4:
5: extern NODE resc[];
6:
7: extern int busy[];
8:
9: # define TBUSY 0100
10:
11: allo( p, q )
12: register NODE *p;
13: register struct optab *q;
14: {
15: register n, i, j;
16: register NODE *presc;
17:
18: n = q->needs;
19: i = 0;
20: /* This code assumes a double reg counts 1 */
21: while( n & NCOUNT )
22: {
23: if( n&NPAIR )
24: {
25: j = freepair( p, n&NMASK );
26: busy[j] |= TBUSY;
27: busy[j+1] |= TBUSY;
28: }
29: else
30: {
31: j = freereg( p, n&NMASK );
32: busy[j] |= TBUSY;
33: }
34: n -= NREG;
35: presc = &resc[i];
36: presc->in.op = REG;
37: presc->tn.rval = j;
38: presc->tn.type = p->tn.type;
39: presc->tn.lval = 0;
40: presc->in.name = (char *) 0;
41: ++i;
42: }
43:
44: /* turn off "temporarily busy" bit */
45: for( j=0; j<NRGS; ++j )
46: {
47: busy[j] &= ~TBUSY;
48: }
49: #ifndef NODBG
50: if( rdebug > 1 )
51: {
52: printf( "allo( %d, %d ), %o", p-node, q->stinline, q->needs );
53: for( j=0; j<i; ++j )
54: {
55: if( resc[j].tn.op == REG )
56: printf( ", REG(%d)", resc[j].tn.rval );
57: else
58: printf( ", TEMP(%ld)", resc[j].tn.lval );
59: }
60: putchar( '\n' );
61: prbusy( "busy:" );
62: }
63: #endif
64: }
65:
66: # ifdef STACK
67: /* for stack machines, totally disable the register allocation */
68: freereg( p, n )
69: NODE *p;
70: {
71: return( 0 );
72: }
73:
74: freepair( p, n )
75: NODE *p;
76: {
77: cerror( "pairs on a stack machine?" );
78: }
79:
80: rbusy( r, t )
81: TWORD t;
82: {
83: }
84: rfree( r, t )
85: TWORD t;
86: {
87: }
88:
89: regrcl( p )
90: NODE *p;
91: {
92: }
93: # else
94: freepair( p, n )
95: register NODE *p;
96: register n;
97: {
98: /* allocate a register pair */
99: /* p gives the type */
100:
101: #ifdef MYPAIR
102: return (mypair(p, n));
103: #else
104: register j;
105:
106: if( callop(p->in.op) )
107: {
108: j = callreg(p);
109: if( j&1 ) cerror( "callreg returns bad pair" );
110: if( usable( p, n, j ) ) return( j );
111: /* have allocated callreg first */
112: }
113: if( n&NMASK )
114: {
115: #ifdef ODDPAIR /* if pair may start on odd reg. */
116: for( j=0; j<NRGS; j++ )
117: #else
118: for( j=0; j<NRGS; j+=2 )
119: #endif
120: if( usable(p,n,j) && usable(p,n,j+1))
121: return( j );
122: }
123: cerror( "freepair allocation fails, op %s", opst[p->tn.op] );
124: /* NOTREACHED */
125: #endif
126: }
127:
128: freereg( p, n )
129: register NODE *p;
130: register n;
131: {
132: /* allocate a register */
133: /* p gives the type */
134:
135: register j;
136: register int t = optype( p->tn.op );
137:
138: if( callop(p->in.op) )
139: {
140: j = callreg(p);
141: if( usable( p, n, j ) ) return( j );
142: /* have allocated callreg first */
143: }
144: if( n&NMASK )
145: {
146: if( (n&LPREF) && (j = shared( getlt( p, t ) ) ) >= 0 &&
147: usable( p, n, j ) ) return( j );
148: if( (n&RPREF) && (j = shared( getrt( p, t ) ) ) >= 0 &&
149: usable( p, n, j ) ) return( j );
150: for( j=0; j<NRGS; ++j ) if( usable(p,n,j) ) return( j );
151: }
152: cerror( "freereg allocation fails, op %s", opst[p->tn.op] );
153: /* NOTREACHED */
154: }
155:
156: shared( p )
157: register NODE *p;
158: {
159: /* simple, at present */
160: /* try to find a single register to share */
161: register r, o;
162: #ifndef NODBG
163: if( rdebug )
164: {
165: printf( "shared called on:\n" );
166: e2print( p );
167: }
168: #endif
169: if( (o=p->tn.op) == REG )
170: {
171: r = p->tn.rval;
172: if (r >= NRGS) return ( -1 );
173: #ifndef NODBG
174: if( rdebug )
175: {
176: printf( "preference for %s\n", rnames[r] );
177: }
178: #endif
179: return( r );
180: }
181: /* we look for shared regs under unary-like ops */
182: switch( optype( o ) )
183: {
184:
185: case BITYPE:
186: /* look for simple cases */
187: /* look only on the left */
188: case UTYPE:
189: return( shared( p->in.left ) );
190: }
191: return( -1 );
192: }
193:
194: usable( p, n, r )
195: register NODE *p;
196: register n,r;
197: {
198: /* decide if register r is usable in tree p to satisfy need n */
199: /* this does not concern itself with pairs */
200:
201: if( r>= NRGS || (busy[r] & TBUSY) ) return( 0 );
202: if( busy[r] > 1 )
203: {
204: /*
205: ** uerror( "register %d too busy", r );
206: */
207: return( 0 );
208: }
209: if( busy[r] == 0 ) {
210: return(1);
211: }
212:
213: /* busy[r] is 1: is there chance for sharing */
214: return( shareit( p, r, n ) );
215:
216: }
217:
218: shareit( p, r, n )
219: register NODE *p;
220: register r;
221: int n;
222: {
223: /* can we make register r available by sharing from p
224: ** given that the need is n
225: */
226: register NODE *sub;
227: register int t = optype(p->tn.op);
228:
229: sub = getlt( p, t );
230: if( (n&LSHARE) && ushare( sub, r ) ) {
231: return 1;
232: }
233: sub = getrt( p, t );
234: if( (n&RSHARE) && ushare( sub, r ) ) {
235: return(1);
236: }
237: return(0);
238: }
239:
240: ushare( p, r )
241: register NODE *p;
242: register r;
243: {
244: /* can we find register r to share in p */
245: if( p->in.op == REG )
246: {
247: if( szty( p->tn.type ) == 2 && r==(p->tn.rval+1) ) return( 1 );
248: return( r == p->tn.rval );
249: }
250: switch( optype( p->tn.op ) )
251: {
252: case BITYPE:
253: if( ushare( p->in.right, r ) ) return( 1 );
254: case UTYPE:
255: if( ushare( p->in.left, r ) ) return( 1 );
256: }
257: return(0);
258: }
259:
260: regrcl( p )
261: register NODE *p;
262: {
263: /* free registers in the tree (or fragment) p */
264: register r;
265: if( !p ) return;
266: r = p->tn.rval;
267: if( p->in.op == REG ) rfree( r, p->in.type );
268: switch( optype( p->tn.op ) )
269: {
270: case BITYPE:
271: regrcl( p->in.right );
272: /* explict assignment to regs not accounted for */
273: if( asgop(p->tn.op) && p->in.left->tn.op == REG ) break;
274: case UTYPE:
275: regrcl( p->in.left );
276: }
277: }
278:
279: rfree( r, t )
280: register TWORD t;
281: register r;
282: {
283: /* mark register r free, if it is legal to do so */
284: /* t is the type */
285:
286: #ifndef NODBG
287: if( rdebug )
288: {
289: printf( "rfree( %s, ", rnames[r] );
290: t2print( t );
291: printf( " )\n" );
292: }
293: #endif
294: if( istreg(r) )
295: {
296: if( --busy[r] < 0 ) cerror( "register overfreed");
297: if( szty( t ) > 1 )
298: {
299: if( !istreg(r+1) ) cerror( "big register" );
300: if( --busy[r+1] < 0 ) cerror( "register overfreed" );
301: }
302: }
303: }
304:
305: prbusy( s )
306: char *s;
307: {
308: /* print out the busy[] array */
309: int i;
310: printf( "%s [", s );
311: for( i=0; i<NRGS-1; ++i ) printf( "%d,", busy[i] );
312: printf( "%d]\n", busy[NRGS-1] );
313: }
314:
315: # endif
316:
317: rwprint( rw )
318: register rw;
319: {
320: /* print rewriting rule */
321: register i, flag;
322: static char * rwnames[] =
323: {
324: "RLEFT",
325: "RRIGHT",
326: "RESC1",
327: "RESC2",
328: "RESC3",
329: "RESCC",
330: "RNOP",
331: 0,
332: };
333: if( rw == RNULL )
334: {
335: printf( "RNULL" );
336: return;
337: }
338: flag = 0;
339: for( i=0; rwnames[i]; ++i )
340: {
341: if( rw & (1<<i) )
342: {
343: if( flag ) printf( "|" );
344: ++flag;
345: printf( rwnames[i] );
346: }
347: }
348: if( !flag ) printf( "?%o", rw );
349: }
350:
351: reclaim( p, rw, goal )
352: register NODE *p;
353: register rw, goal;
354: {
355: register NODE *q;
356: register o;
357:
358: /* get back stuff */
359: #ifndef NODBG
360: if( rdebug )
361: {
362: printf( "reclaim( %d, ", p-node );
363: rwprint( rw );
364: printf( ", " );
365: prgoal( goal );
366: printf( " )\n" );
367: }
368: #endif
369: if( !p ) return;
370: /* special cases... */
371: if( (o=p->tn.op) == COMOP )
372: {
373: /* LHS has already been freed; don't free again */
374: regrcl( p->in.right );
375: }
376: else regrcl( p );
377: if( (o==FREE && rw==RNULL) || rw==RNOP ) return;
378: if( callop(o) )
379: {
380: /* check that all scratch regs are free */
381: callchk(p); /* ordinarily, this is the same as allchk() */
382: }
383: if( rw == RNULL || (goal&FOREFF) )
384: {
385: /* totally clobber, leave nothing */
386: tfree(p);
387: return;
388: }
389: /* handle condition codes specially */
390: if( (goal & FORCC) && (rw&RESCC))
391: {
392: /* result is CC register */
393: tfree(p);
394: p->in.op = CCODES;
395: p->tn.lval = 0;
396: p->tn.rval = 0;
397: return;
398: }
399: q = 0;
400: if( rw&RLEFT) q = getl( p );
401: else if( rw&RRIGHT ) q = getr( p );
402: else if( rw&RESC1 ) q = &resc[0];
403: else if( rw&RESC2 ) q = &resc[1];
404: else if( rw&RESC3 ) q = &resc[2];
405: else
406: {
407: cerror( "illegal reclaim, op %s", opst[p->tn.op]);
408: }
409: if( o == STARG ) p = p->in.left; /* STARGs are still STARGS */
410: q = tcopy(q, 1);
411: tfree(p);
412: *p = *q; /* make the result replace the original */
413: q->in.op = FREE;
414: }
415:
416: NODE *
417: tcopy( p, busyregs )
418: register NODE *p;
419: int busyregs;
420: {
421: /* make a fresh copy of p */
422: register NODE *q;
423: register r;
424:
425: q=talloc();
426: *q = *p;
427: r = p->tn.rval;
428: if( p->in.op == REG && busyregs) rbusy( r, p->in.type );
429: switch( optype(q->in.op) )
430: {
431: case BITYPE:
432: q->in.right = tcopy(p->in.right, busyregs);
433: case UTYPE:
434: q->in.left = tcopy(p->in.left, busyregs);
435: }
436: return(q);
437: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.