|
|
1.1 root 1: /* @(#) allo.c: 1.7 6/26/84 */
2:
3: # include "mfile2.h"
4:
5: NODE resc[NRGS];
6:
7: int busy[NRGS];
8:
9: # define TBUSY 0100
10:
11: allo0()
12: {
13: /* free everything */
14: register i;
15:
16: for( i=0; i<NRGS; ++i )
17: {
18: busy[i] = 0;
19: }
20: }
21:
22: allo( p, q )
23: register NODE *p;
24: register struct optab *q;
25: {
26: register n, i, j;
27: register NODE *presc;
28:
29: n = q->needs;
30: i = 0;
31: /* This code assumes a double reg counts 1 */
32: while( n & NCOUNT )
33: {
34: if( n&NPAIR )
35: {
36: j = freepair( p, n&NMASK );
37: busy[j] |= TBUSY;
38: busy[j+1] |= TBUSY;
39: #if defined(M32B) && defined(IMPREGAL)
40: radbl(); /* inform optimizer double reg used */
41: #endif
42: }
43: else
44: {
45: j = freereg( p, n&NMASK );
46: busy[j] |= TBUSY;
47: }
48: n -= NREG;
49: presc = &resc[i];
50: presc->in.op = REG;
51: presc->tn.rval = j;
52: presc->tn.type = p->tn.type;
53: presc->tn.lval = 0;
54: presc->in.name = (char *) 0;
55: ++i;
56: }
57:
58: /* turn off "temporarily busy" bit */
59: for( j=0; j<NRGS; ++j )
60: {
61: busy[j] &= ~TBUSY;
62: }
63: #ifndef NODBG
64: if( rdebug > 1 )
65: {
66: printf( "allo( %d, %d ), %o", p-node, q->stinline, q->needs );
67: for( j=0; j<i; ++j )
68: {
69: if( resc[j].tn.op == REG )
70: printf( ", REG(%d)", resc[j].tn.rval );
71: else
72: printf( ", TEMP(%ld)", resc[j].tn.lval );
73: }
74: putchar( '\n' );
75: prbusy( "busy:" );
76: }
77: #endif
78: }
79:
80: int tmpoff; /* offset of next temp to be allocated */
81:
82: int rdebug = 0;
83:
84: freetemp( k )
85: register k;
86: {
87: /* allocate k integers worth of temp space
88: ** we also make the convention that, if the number of words is more than 1,
89: ** it must be aligned for storing doubles...
90: */
91:
92: # ifndef BACKTEMP
93: int t;
94:
95: if( k>1 )
96: {
97: SETOFF( tmpoff, ALDOUBLE );
98: }
99:
100: t = tmpoff;
101: tmpoff += k*SZINT;
102: if( tmpoff > maxtemp ) maxtemp = tmpoff;
103: return(t);
104:
105: # else
106: tmpoff += k*SZINT;
107: if( k>1 )
108: {
109: SETOFF( tmpoff, ALDOUBLE );
110: }
111: if( tmpoff > maxtemp ) maxtemp = tmpoff;
112: return( -tmpoff );
113: # endif
114: }
115:
116: # ifdef STACK
117: /* for stack machines, totally disable the register allocation */
118: freereg( p, n )
119: NODE *p;
120: {
121: return( 0 );
122: }
123:
124: freepair( p, n )
125: NODE *p;
126: {
127: cerror( "pairs on a stack machine?" );
128: }
129:
130: rbusy( r, t )
131: TWORD t;
132: {
133: }
134: rfree( r, t )
135: TWORD t;
136: {
137: }
138:
139: regrcl( p )
140: NODE *p;
141: {
142: }
143: # else
144: freepair( p, n )
145: register NODE *p;
146: register n;
147: {
148: /* allocate a register pair */
149: /* p gives the type */
150:
151: #ifdef MYPAIR
152: return (mypair(p, n));
153: #else
154: register j;
155:
156: if( callop(p->in.op) )
157: {
158: j = callreg(p);
159: if( j&1 ) cerror( "callreg returns bad pair" );
160: if( usable( p, n, j ) ) return( j );
161: /* have allocated callreg first */
162: }
163: if( n&NMASK )
164: {
165: #ifdef ODDPAIR /* if pair may start on odd reg. */
166: for( j=0; j<NRGS; j++ )
167: #else
168: for( j=0; j<NRGS; j+=2 )
169: #endif
170: if( usable(p,n,j) && usable(p,n,j+1))
171: return( j );
172: }
173: cerror( "allocation fails, op %s", opst[p->tn.op] );
174: /* NOTREACHED */
175: #endif
176: }
177:
178: freereg( p, n )
179: register NODE *p;
180: register n;
181: {
182: /* allocate a register */
183: /* p gives the type */
184:
185: register j;
186: register int t = optype( p->tn.op );
187:
188: if( callop(p->in.op) )
189: {
190: j = callreg(p);
191: if( usable( p, n, j ) ) return( j );
192: /* have allocated callreg first */
193: }
194: if( n&NMASK )
195: {
196: if( (n&LPREF) && (j = shared( getlt( p, t ) ) ) >= 0 &&
197: usable( p, n, j ) ) return( j );
198: if( (n&RPREF) && (j = shared( getrt( p, t ) ) ) >= 0 &&
199: usable( p, n, j ) ) return( j );
200: for( j=0; j<NRGS; ++j ) if( usable(p,n,j) ) return( j );
201: }
202: cerror( "allocation fails, op %s", opst[p->tn.op] );
203: /* NOTREACHED */
204: }
205:
206: shared( p )
207: register NODE *p;
208: {
209: /* simple, at present */
210: /* try to find a single register to share */
211: register r, o;
212: #ifndef NODBG
213: if( rdebug )
214: {
215: printf( "shared called on:\n" );
216: e2print( p );
217: }
218: #endif
219: if( (o=p->tn.op) == REG )
220: {
221: r = p->tn.rval;
222: if (r >= NRGS) return ( -1 );
223: #ifndef NODBG
224: if( rdebug )
225: {
226: printf( "preference for %s\n", rnames[r] );
227: }
228: #endif
229: return( r );
230: }
231: /* we look for shared regs under unary-like ops */
232: switch( optype( o ) )
233: {
234:
235: case BITYPE:
236: /* look for simple cases */
237: /* look only on the left */
238: case UTYPE:
239: return( shared( p->in.left ) );
240: }
241: return( -1 );
242: }
243:
244: usable( p, n, r )
245: register NODE *p;
246: register n,r;
247: {
248: /* decide if register r is usable in tree p to satisfy need n */
249: /* this does not concern itself with pairs */
250:
251: if( r>= NRGS || (busy[r] & TBUSY) ) return( 0 );
252: if( busy[r] > 1 )
253: {
254: /*
255: ** uerror( "register %d too busy", r );
256: */
257: return( 0 );
258: }
259: if( busy[r] == 0 ) {
260: return(1);
261: }
262:
263: /* busy[r] is 1: is there chance for sharing */
264: return( shareit( p, r, n ) );
265:
266: }
267:
268: shareit( p, r, n )
269: register NODE *p;
270: register r;
271: int n;
272: {
273: /* can we make register r available by sharing from p
274: ** given that the need is n
275: */
276: register NODE *sub;
277: register int t = optype(p->tn.op);
278:
279: sub = getlt( p, t );
280: if( (n&LSHARE) && ushare( sub, r ) ) {
281: return 1;
282: }
283: sub = getrt( p, t );
284: if( (n&RSHARE) && ushare( sub, r ) ) {
285: return(1);
286: }
287: return(0);
288: }
289:
290: ushare( p, r )
291: register NODE *p;
292: register r;
293: {
294: /* can we find register r to share in p */
295: if( p->in.op == REG )
296: {
297: if( szty( p->tn.type ) == 2 && r==(p->tn.rval+1) ) return( 1 );
298: return( r == p->tn.rval );
299: }
300: switch( optype( p->tn.op ) )
301: {
302: case BITYPE:
303: if( ushare( p->in.right, r ) ) return( 1 );
304: case UTYPE:
305: if( ushare( p->in.left, r ) ) return( 1 );
306: }
307: return(0);
308: }
309:
310: regrcl( p )
311: register NODE *p;
312: {
313: /* free registers in the tree (or fragment) p */
314: register r;
315: if( !p ) return;
316: r = p->tn.rval;
317: if( p->in.op == REG ) rfree( r, p->in.type );
318: switch( optype( p->tn.op ) )
319: {
320: case BITYPE:
321: regrcl( p->in.right );
322: /* explict assignment to regs not accounted for */
323: if( asgop(p->tn.op) && p->in.left->tn.op == REG ) break;
324: case UTYPE:
325: regrcl( p->in.left );
326: }
327: }
328:
329: rfree( r, t )
330: register TWORD t;
331: register r;
332: {
333: /* mark register r free, if it is legal to do so */
334: /* t is the type */
335:
336: #ifndef NODBG
337: if( rdebug )
338: {
339: printf( "rfree( %s, ", rnames[r] );
340: t2print( t );
341: printf( " )\n" );
342: }
343: #endif
344: if( istreg(r) )
345: {
346: if( --busy[r] < 0 ) cerror( "register overfreed");
347: if( szty( t ) > 1 )
348: {
349: if( !istreg(r+1) ) cerror( "big register" );
350: if( --busy[r+1] < 0 ) cerror( "register overfreed" );
351: }
352: }
353: }
354:
355: rbusy(r, t )
356: register r;
357: register TWORD t;
358: {
359: /* mark register r busy */
360:
361: #ifndef NODBG
362: if( rdebug )
363: {
364: printf( "rbusy( %s, ", rnames[r] );
365: t2print( t );
366: printf( " )\n" );
367: }
368: #endif
369: if( istreg(r) )
370: {
371: ++busy[r];
372: if( szty( t ) > 1 )
373: {
374: if( !istreg(r+1) ) cerror( "big register" );
375: ++busy[r+1];
376: }
377: }
378: }
379:
380: prbusy( s )
381: char *s;
382: {
383: /* print out the busy[] array */
384: int i;
385: printf( "%s [", s );
386: for( i=0; i<NRGS-1; ++i ) printf( "%d,", busy[i] );
387: printf( "%d]\n", busy[NRGS-1] );
388: }
389:
390: # endif
391:
392: rwprint( rw )
393: register rw;
394: {
395: /* print rewriting rule */
396: register i, flag;
397: static char * rwnames[] =
398: {
399: "RLEFT",
400: "RRIGHT",
401: "RESC1",
402: "RESC2",
403: "RESC3",
404: "RESCC",
405: "RNOP",
406: 0,
407: };
408: if( rw == RNULL )
409: {
410: printf( "RNULL" );
411: return;
412: }
413: flag = 0;
414: for( i=0; rwnames[i]; ++i )
415: {
416: if( rw & (1<<i) )
417: {
418: if( flag ) printf( "|" );
419: ++flag;
420: printf( rwnames[i] );
421: }
422: }
423: if( !flag ) printf( "?%o", rw );
424: }
425:
426: reclaim( p, rw, goal )
427: register NODE *p;
428: register rw, goal;
429: {
430: register NODE *q;
431: register o;
432:
433: /* get back stuff */
434: #ifndef NODBG
435: if( rdebug )
436: {
437: printf( "reclaim( %d, ", p-node );
438: rwprint( rw );
439: printf( ", " );
440: prgoal( goal );
441: printf( " )\n" );
442: }
443: #endif
444: if( !p ) return;
445: /* special cases... */
446: if( (o=p->tn.op) == COMOP )
447: {
448: /* LHS has already been freed; don't free again */
449: regrcl( p->in.right );
450: }
451: else regrcl( p );
452: if( (o==FREE && rw==RNULL) || rw==RNOP ) return;
453: if( callop(o) )
454: {
455: /* check that all scratch regs are free */
456: callchk(p); /* ordinarily, this is the same as allchk() */
457: }
458: if( rw == RNULL || (goal&FOREFF) )
459: {
460: /* totally clobber, leave nothing */
461: tfree(p);
462: return;
463: }
464: /* handle condition codes specially */
465: if( (goal & FORCC) && (rw&RESCC))
466: {
467: /* result is CC register */
468: tfree(p);
469: p->in.op = CCODES;
470: p->tn.lval = 0;
471: p->tn.rval = 0;
472: return;
473: }
474: q = 0;
475: if( rw&RLEFT) q = getl( p );
476: else if( rw&RRIGHT ) q = getr( p );
477: else if( rw&RESC1 ) q = &resc[0];
478: else if( rw&RESC2 ) q = &resc[1];
479: else if( rw&RESC3 ) q = &resc[2];
480: else
481: {
482: cerror( "illegal reclaim, op %s", opst[p->tn.op]);
483: }
484: if( o == STARG ) p = p->in.left; /* STARGs are still STARGS */
485: q = tcopy(q);
486: tfree(p);
487: *p = *q; /* make the result replace the original */
488: q->in.op = FREE;
489: }
490:
491: NODE *
492: tcopy( p )
493: register NODE *p;
494: {
495: /* make a fresh copy of p */
496: register NODE *q;
497: register r;
498:
499: q=talloc();
500: *q = *p;
501: r = p->tn.rval;
502: if( p->in.op == REG ) rbusy( r, p->in.type );
503: switch( optype(q->in.op) )
504: {
505: case BITYPE:
506: q->in.right = tcopy(p->in.right);
507: case UTYPE:
508: q->in.left = tcopy(p->in.left);
509: }
510: return(q);
511: }
512:
513: allchk()
514: {
515: /* check to ensure that all register are free */
516: register i;
517:
518: for( i=0; i<NRGS; ++i )
519: {
520: if( busy[i] )
521: {
522: cerror( "register allocation error");
523: }
524: }
525: }
526:
527: /* this may not be the best place for this routine... */
528: argsize( p )
529: register NODE *p;
530: {
531: /* size of the arguments */
532: register t;
533: t = 0;
534: if( p->tn.op == CM )
535: {
536: t = argsize( p->in.left );
537: p = p->in.right;
538: }
539: if( p->tn.type & (TDOUBLE|TFLOAT) )
540: {
541: SETOFF( t, ALDOUBLE );
542: t += SZDOUBLE;
543: }
544: else if( p->tn.type & (TLONG|TULONG) )
545: {
546: SETOFF( t, ALLONG );
547: t += SZLONG;
548: }
549: else if( p->tn.type & TPOINT )
550: {
551: SETOFF( t, ALPOINT );
552: t += SZPOINT;
553: }
554: else if( p->tn.type & TSTRUCT )
555: {
556: SETOFF( t, p->stn.stalign ); /* alignment */
557: t += p->stn.stsize; /* size */
558: }
559: else
560: {
561: SETOFF( t, ALINT );
562: t += SZINT;
563: }
564: return( t );
565: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.