|
|
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.