xref: /csrg-svn/old/pcc/mip/allo.c (revision 24400)
1 #ifndef lint
2 static char *sccsid ="@(#)allo.c	4.7 (Berkeley) 08/22/85";
3 #endif lint
4 
5 # include "pass2.h"
6 
7 NODE resc[3];
8 
9 int busy[REGSZ];
10 
11 int maxa, mina, maxb, minb;
12 
13 # ifndef ALLO0
14 allo0(){ /* free everything */
15 
16 	register i;
17 
18 	maxa = maxb = -1;
19 	mina = minb = 0;
20 
21 	REGLOOP(i){
22 		busy[i] = 0;
23 		if( rstatus[i] & STAREG ){
24 			if( maxa<0 ) mina = i;
25 			maxa = i;
26 			}
27 		if( rstatus[i] & STBREG ){
28 			if( maxb<0 ) minb = i;
29 			maxb = i;
30 			}
31 		}
32 	}
33 # endif
34 
35 # ifndef ALLO
36 allo( p, q ) NODE *p; struct optab *q; {
37 
38 	register n, i, j;
39 	int either;
40 
41 	n = q->needs;
42 	either = ( EITHER & n );
43 	i = 0;
44 
45 	while( n & NACOUNT ){
46 		resc[i].in.op = REG;
47 		resc[i].tn.rval = freereg( p, n&NAMASK );
48 		resc[i].tn.lval = 0;
49 #ifdef FLEXNAMES
50 		resc[i].in.name = "";
51 #else
52 		resc[i].in.name[0] = '\0';
53 #endif
54 		n -= NAREG;
55 		++i;
56 		}
57 
58 	if (either) { /* all or nothing at all */
59 		for( j = 0; j < i; j++ )
60 			if( resc[j].tn.rval < 0 ) { /* nothing */
61 				i = 0;
62 				break;
63 				}
64 		if( i != 0 ) goto ok; /* all */
65 		}
66 
67 	while( n & NBCOUNT ){
68 		resc[i].in.op = REG;
69 		resc[i].tn.rval = freereg( p, n&NBMASK );
70 		resc[i].tn.lval = 0;
71 #ifdef FLEXNAMES
72 		resc[i].in.name = "";
73 #else
74 		resc[i].in.name[0] = '\0';
75 #endif
76 		n -= NBREG;
77 		++i;
78 		}
79 	if (either) { /* all or nothing at all */
80 		for( j = 0; j < i; j++ )
81 			if( resc[j].tn.rval < 0 ) { /* nothing */
82 				i = 0;
83 				break;
84 				}
85 		if( i != 0 ) goto ok; /* all */
86 		}
87 
88 	if( n & NTMASK ){
89 		resc[i].in.op = OREG;
90 		resc[i].tn.rval = TMPREG;
91 		if( p->in.op == STCALL || p->in.op == STARG || p->in.op == UNARY STCALL || p->in.op == STASG ){
92 			resc[i].tn.lval = freetemp( (SZCHAR*p->stn.stsize + (SZINT-1))/SZINT );
93 			}
94 		else {
95 			resc[i].tn.lval = freetemp( (n&NTMASK)/NTEMP );
96 			}
97 #ifdef FLEXNAMES
98 		resc[i].in.name = "";
99 #else
100 		resc[i].in.name[0] = '\0';
101 #endif
102 
103 		resc[i].tn.lval = BITOOR(resc[i].tn.lval);
104 		++i;
105 		}
106 
107 	/* turn off "temporarily busy" bit */
108 
109 	ok:
110 	REGLOOP(j){
111 		busy[j] &= ~TBUSY;
112 		}
113 
114 	for( j=0; j<i; ++j ) if( resc[j].tn.rval < 0 ) return(0);
115 	return(1);
116 
117 	}
118 # endif
119 
120 extern unsigned int offsz;
121 freetemp( k ){ /* allocate k integers worth of temp space */
122 	/* we also make the convention that, if the number of words is more than 1,
123 	/* it must be aligned for storing doubles... */
124 
125 # ifndef BACKTEMP
126 	int t;
127 
128 	if( k>1 ){
129 		SETOFF( tmpoff, ALDOUBLE );
130 		}
131 
132 	t = tmpoff;
133 	tmpoff += k*SZINT;
134 	if( tmpoff > maxoff ) maxoff = tmpoff;
135 	if( tmpoff >= offsz )
136 		cerror( "stack overflow" );
137 	if( tmpoff-baseoff > maxtemp ) maxtemp = tmpoff-baseoff;
138 	return(t);
139 
140 # else
141 	tmpoff += k*SZINT;
142 	if( k>1 ) {
143 		SETOFF( tmpoff, ALDOUBLE );
144 		}
145 	if( tmpoff > maxoff ) maxoff = tmpoff;
146 	if( tmpoff >= offsz )
147 		cerror( "stack overflow" );
148 	if( tmpoff-baseoff > maxtemp ) maxtemp = tmpoff-baseoff;
149 	return( -tmpoff );
150 # endif
151 	}
152 
153 freereg( p, n ) NODE *p; {
154 	/* allocate a register of type n */
155 	/* p gives the type, if floating */
156 
157 	register j;
158 
159 	/* not general; means that only one register (the result) OK for call */
160 	if( callop(p->in.op) ){
161 		j = callreg(p);
162 		if( usable( p, n, j ) ) return( j );
163 		/* have allocated callreg first */
164 		}
165 	j = p->in.rall & ~MUSTDO;
166 	if( j!=NOPREF && usable(p,n,j) ){ /* needed and not allocated */
167 		return( j );
168 		}
169 	if( n&NAMASK ){
170 		for( j=mina; j<=maxa; ++j ) if( rstatus[j]&STAREG ){
171 			if( usable(p,n,j) ){
172 				return( j );
173 				}
174 			}
175 		}
176 	else if( n &NBMASK ){
177 		for( j=minb; j<=maxb; ++j ) if( rstatus[j]&STBREG ){
178 			if( usable(p,n,j) ){
179 				return(j);
180 				}
181 			}
182 		}
183 
184 	return( -1 );
185 	}
186 
187 # ifndef USABLE
188 usable( p, n, r ) NODE *p; {
189 	/* decide if register r is usable in tree p to satisfy need n */
190 
191 	/* checks, for the moment */
192 	if( !istreg(r) ) cerror( "usable asked about nontemp register" );
193 
194 	if( busy[r] > 1 ) return(0);
195 	if( isbreg(r) ){
196 		if( n&NAMASK ) return(0);
197 		}
198 	else {
199 		if( n & NBMASK ) return(0);
200 		}
201 	/*
202 	 * Have to check for ==, <=, etc. because the result is type INT
203 	 * but need a register pair temp if either side is real.
204 	 */
205 	if( (n&NAMASK) && (szty(p->in.type) == 2 ||
206 	    logop(p->in.op) && (szty(p->in.left->in.type) == 2 ||
207 	    szty(p->in.right->in.type) == 2)) ){ /* only do the pairing for real regs */
208 #ifndef NOEVENODD
209 		if( r&01 ) return(0);
210 #endif
211 		if( !istreg(r+1) ) return( 0 );
212 		if( busy[r+1] > 1 ) return( 0 );
213 		if( busy[r] == 0 && busy[r+1] == 0  ||
214 		    busy[r+1] == 0 && shareit( p, r, n ) ||
215 		    busy[r] == 0 && shareit( p, r+1, n ) ){
216 			busy[r] |= TBUSY;
217 			busy[r+1] |= TBUSY;
218 			return(1);
219 			}
220 		else return(0);
221 		}
222 	if( busy[r] == 0 ) {
223 		busy[r] |= TBUSY;
224 		return(1);
225 		}
226 
227 	/* busy[r] is 1: is there chance for sharing */
228 	return( shareit( p, r, n ) );
229 
230 	}
231 # endif
232 
233 shareit( p, r, n ) NODE *p; {
234 	/* can we make register r available by sharing from p
235 	   given that the need is n */
236 	if( (n&(NASL|NBSL)) && ushare( p, 'L', r ) ) return(1);
237 	if( (n&(NASR|NBSR)) && ushare( p, 'R', r ) ) return(1);
238 	return(0);
239 	}
240 
241 ushare( p, f, r ) NODE *p; {
242 	/* can we find a register r to share on the left or right
243 		(as f=='L' or 'R', respectively) of p */
244 	p = getlr( p, f );
245 	if( p->in.op == UNARY MUL ) p = p->in.left;
246 	if( p->in.op == OREG ){
247 		if( R2TEST(p->tn.rval) ){
248 			return( r==R2UPK1(p->tn.rval) || r==R2UPK2(p->tn.rval) );
249 			}
250 		else return( r == p->tn.rval );
251 		}
252 	if( p->in.op == REG ){
253 		return( r == p->tn.rval || ( szty(p->in.type) == 2 && r==p->tn.rval+1 ) );
254 		}
255 	return(0);
256 	}
257 
258 recl2( p ) register NODE *p; {
259 	register r = p->tn.rval;
260 #ifndef OLD
261 	int op = p->in.op;
262 	if (op == REG && r >= REGSZ)
263 		op = OREG;
264 	if( op == REG ) rfree( r, p->in.type );
265 	else if( op == OREG ) {
266 		if( R2TEST( r ) ) {
267 			if( R2UPK1( r ) != 100 ) rfree( R2UPK1( r ), PTR+INT );
268 			rfree( R2UPK2( r ), INT );
269 			}
270 		else {
271 			rfree( r, PTR+INT );
272 			}
273 		}
274 #else
275 	if( p->in.op == REG ) rfree( r, p->in.type );
276 	else if( p->in.op == OREG ) {
277 		if( R2TEST( r ) ) {
278 			if( R2UPK1( r ) != 100 ) rfree( R2UPK1( r ), PTR+INT );
279 			rfree( R2UPK2( r ), INT );
280 			}
281 		else {
282 			rfree( r, PTR+INT );
283 			}
284 		}
285 #endif
286 	}
287 
288 int rdebug = 0;
289 
290 # ifndef RFREE
291 rfree( r, t ) TWORD t; {
292 	/* mark register r free, if it is legal to do so */
293 	/* t is the type */
294 
295 # ifndef BUG3
296 	if( rdebug ){
297 		printf( "rfree( %s ), size %d\n", rnames[r], szty(t) );
298 		}
299 # endif
300 
301 	if( istreg(r) ){
302 		if( --busy[r] < 0 ) cerror( "register overfreed");
303 		if( szty(t) == 2 ){
304 #ifdef NOEVENODD
305 			if( istreg(r) ^ istreg(r+1) ) cerror( "illegal free" );
306 #else
307 			if( (r&01) || (istreg(r)^istreg(r+1)) ) cerror( "illegal free" );
308 #endif
309 			if( --busy[r+1] < 0 ) cerror( "register overfreed" );
310 			}
311 		}
312 	}
313 # endif
314 
315 # ifndef RBUSY
316 rbusy(r,t) TWORD t; {
317 	/* mark register r busy */
318 	/* t is the type */
319 
320 # ifndef BUG3
321 	if( rdebug ){
322 		printf( "rbusy( %s ), size %d\n", rnames[r], szty(t) );
323 		}
324 # endif
325 
326 	if( istreg(r) ) ++busy[r];
327 	if( szty(t) == 2 ){
328 		if( istreg(r+1) ) ++busy[r+1];
329 #ifdef NOEVENODD
330 		if( istreg(r) ^ istreg(r+1) ) cerror( "illegal register pair freed" );
331 #else
332 		if( (r&01) || (istreg(r)^istreg(r+1)) ) cerror( "illegal register pair freed" );
333 #endif
334 		}
335 	}
336 # endif
337 
338 # ifndef BUG3
339 rwprint( rw ){ /* print rewriting rule */
340 	register i, flag;
341 	static char * rwnames[] = {
342 
343 		"RLEFT",
344 		"RRIGHT",
345 		"RESC1",
346 		"RESC2",
347 		"RESC3",
348 		0,
349 		};
350 
351 	if( rw == RNULL ){
352 		printf( "RNULL" );
353 		return;
354 		}
355 
356 	if( rw == RNOP ){
357 		printf( "RNOP" );
358 		return;
359 		}
360 
361 	flag = 0;
362 	for( i=0; rwnames[i]; ++i ){
363 		if( rw & (1<<i) ){
364 			if( flag ) printf( "|" );
365 			++flag;
366 			printf( rwnames[i] );
367 			}
368 		}
369 	}
370 # endif
371 
372 reclaim( p, rw, cookie ) NODE *p; {
373 	register NODE **qq;
374 	register NODE *q;
375 	register i;
376 	NODE *recres[5];
377 	struct respref *r;
378 
379 	/* get back stuff */
380 
381 # ifndef BUG3
382 	if( rdebug ){
383 		printf( "reclaim( %o, ", p );
384 		rwprint( rw );
385 		printf( ", " );
386 		prcook( cookie );
387 		printf( " )\n" );
388 		}
389 # endif
390 
391 	if( rw == RNOP || ( p->in.op==FREE && rw==RNULL ) ) return;  /* do nothing */
392 
393 	walkf( p, recl2 );
394 
395 	if( callop(p->in.op) ){
396 		/* check that all scratch regs are free */
397 		callchk(p);  /* ordinarily, this is the same as allchk() */
398 		}
399 
400 	if( rw == RNULL || (cookie&FOREFF) ){ /* totally clobber, leaving nothing */
401 		tfree(p);
402 		return;
403 		}
404 
405 	/* handle condition codes specially */
406 
407 	if( (cookie & FORCC) && (rw&RESCC)) {
408 		/* result is CC register */
409 		tfree(p);
410 		p->in.op = CCODES;
411 		p->tn.lval = 0;
412 		p->tn.rval = 0;
413 		return;
414 		}
415 
416 	/* locate results */
417 
418 	qq = recres;
419 
420 	if( rw&RLEFT) *qq++ = getlr( p, 'L' );;
421 	if( rw&RRIGHT ) *qq++ = getlr( p, 'R' );
422 	if( rw&RESC1 ) *qq++ = &resc[0];
423 	if( rw&RESC2 ) *qq++ = &resc[1];
424 	if( rw&RESC3 ) *qq++ = &resc[2];
425 
426 	if( qq == recres ){
427 		cerror( "illegal reclaim");
428 		}
429 
430 	*qq = NIL;
431 
432 	/* now, select the best result, based on the cookie */
433 
434 	for( r=respref; r->cform; ++r ){
435 		if( cookie & r->cform ){
436 			for( qq=recres; (q= *qq) != NIL; ++qq ){
437 				if( tshape( q, r->mform ) ) goto gotit;
438 				}
439 			}
440 		}
441 
442 	/* we can't do it; die */
443 	cerror( "cannot reclaim");
444 
445 	gotit:
446 
447 	if( p->in.op == STARG ) p = p->in.left;  /* STARGs are still STARGS */
448 
449 	q->in.type = p->in.type;  /* to make multi-register allocations work */
450 		/* maybe there is a better way! */
451 	q = tcopy(q);
452 
453 	tfree(p);
454 
455 	p->in.op = q->in.op;
456 	p->tn.lval = q->tn.lval;
457 	p->tn.rval = q->tn.rval;
458 #ifdef FLEXNAMES
459 	p->in.name = q->in.name;
460 #ifdef ONEPASS
461 	p->in.stalign = q->in.stalign;
462 #endif
463 #else
464 	for( i=0; i<NCHNAM; ++i )
465 		p->in.name[i] = q->in.name[i];
466 #endif
467 
468 	q->in.op = FREE;
469 
470 	/* if the thing is in a register, adjust the type */
471 
472 	switch( p->in.op ){
473 
474 	case REG:
475 		if( !rtyflg ){
476 			/* the C language requires intermediate results to change type */
477 			/* this is inefficient or impossible on some machines */
478 			/* the "T" command in match supresses this type changing */
479 			if( p->in.type == CHAR || p->in.type == SHORT ) p->in.type = INT;
480 			else if( p->in.type == UCHAR || p->in.type == USHORT ) p->in.type = UNSIGNED;
481 #if !defined(FORT) && !defined(SPRECC)
482 			else if( p->in.type == FLOAT ) p->in.type = DOUBLE;
483 #endif
484 			}
485 		if( ! (p->in.rall & MUSTDO ) ) return;  /* unless necessary, ignore it */
486 		i = p->in.rall & ~MUSTDO;
487 		if( i & NOPREF ) return;
488 		if( i != p->tn.rval ){
489 			if( busy[i] || ( szty(p->in.type)==2 && busy[i+1] ) ){
490 				cerror( "faulty register move" );
491 				}
492 			rbusy( i, p->in.type );
493 			rfree( p->tn.rval, p->in.type );
494 			rmove( i, p->tn.rval, p->in.type );
495 			p->tn.rval = i;
496 			}
497 
498 	case OREG:
499 		if( p->in.op == REG || !R2TEST(p->tn.rval) ) {
500 			if( busy[p->tn.rval]>1 && istreg(p->tn.rval) ) cerror( "potential register overwrite");
501 			}
502 		else
503 			if( (R2UPK1(p->tn.rval) != 100 && busy[R2UPK1(p->tn.rval)]>1 && istreg(R2UPK1(p->tn.rval)) )
504 				|| (busy[R2UPK2(p->tn.rval)]>1 && istreg(R2UPK2(p->tn.rval)) ) )
505 			   cerror( "potential register overwrite");
506 		}
507 
508 	}
509 
510 #ifndef ncopy
511 ncopy( q, p ) NODE *p, *q; {
512 	/* copy the contents of p into q, without any feeling for
513 	   the contents */
514 	/* this code assume that copying rval and lval does the job;
515 	   in general, it might be necessary to special case the
516 	   operator types */
517 	register i;
518 
519 	q->in.op = p->in.op;
520 	q->in.rall = p->in.rall;
521 	q->in.type = p->in.type;
522 	q->tn.lval = p->tn.lval;
523 	q->tn.rval = p->tn.rval;
524 #ifdef FLEXNAMES
525 	q->in.name = p->in.name;
526 #ifdef ONEPASS
527 	q->in.stalign = p->in.stalign;
528 #endif
529 #else
530 	for( i=0; i<NCHNAM; ++i ) q->in.name[i]  = p->in.name[i];
531 #endif
532 
533 	}
534 #endif
535 
536 NODE *
537 tcopy( p ) register NODE *p; {
538 	/* make a fresh copy of p */
539 
540 	register NODE *q;
541 	register r;
542 
543 	ncopy( q=talloc(), p );
544 
545 	r = p->tn.rval;
546 	if( p->in.op == REG ) rbusy( r, p->in.type );
547 	else if( p->in.op == OREG ) {
548 		if( R2TEST(r) ){
549 			if( R2UPK1(r) != 100 ) rbusy( R2UPK1(r), PTR+INT );
550 			rbusy( R2UPK2(r), INT );
551 			}
552 		else {
553 			rbusy( r, PTR+INT );
554 			}
555 		}
556 
557 	switch( optype(q->in.op) ){
558 
559 	case BITYPE:
560 		q->in.right = tcopy(p->in.right);
561 	case UTYPE:
562 		q->in.left = tcopy(p->in.left);
563 		}
564 
565 	return(q);
566 	}
567 
568 allchk(){
569 	/* check to ensure that all register are free */
570 
571 	register i;
572 
573 	REGLOOP(i){
574 		if( istreg(i) && busy[i] ){
575 			cerror( "register allocation error");
576 			}
577 		}
578 
579 	}
580