|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char sccsid[] = "@(#)regalloc.c 5.6 (Berkeley) 1/3/88"; ! 9: #endif not lint ! 10: ! 11: /* ! 12: * regalloc.c ! 13: * ! 14: * Register optimization routines for f77 compiler, pass 1 ! 15: * ! 16: * University of Utah CS Dept modification history: ! 17: * ! 18: * $Log: regalloc.c,v $ ! 19: * Revision 5.7 86/04/21 18:23:08 donn ! 20: * Still more hacking with GOTOs and loops! What a mess. This time we ! 21: * complete the illusion that adjacent loops are actually embedded loops. ! 22: * Without this hack, variables which are in one loop but not in another ! 23: * adjacent loop cause severe confusion. A routine varloopset() is added ! 24: * to re-implement the loopset hack; I'm not certain that this is really ! 25: * needed at all, now. ! 26: * ! 27: * Revision 5.6 86/01/04 22:35:44 donn ! 28: * More hacking on GOTOs and loops. Fixed a bug in rev 5.4. Changed ! 29: * regalloc() so that sibling loops behave like nested loops, eliminating ! 30: * problems with GOTOs and different registers used for the same variable. ! 31: * This decreases the flexibility of the allocator quite a bit, but it was ! 32: * doing the job wrong before, so we come out ahead. ! 33: * ! 34: * Revision 5.5 86/01/04 19:54:28 donn ! 35: * Pick up redundant register moves when address registers (STGPREG) are ! 36: * involved. ! 37: * ! 38: * Revision 5.4 86/01/04 18:28:34 donn ! 39: * Patching over some more design problems... If there is a GOTO that jumps ! 40: * from an inner loop into an outer loop and there is a variable which is set ! 41: * in the inner loop and is in register in the outer loop but is not in ! 42: * register in the inner loop (or is in a different register), we get into ! 43: * trouble because the register version of the variable in the outer loop ! 44: * is 'dead' and we don't maintain enough information to be able to restore ! 45: * it. The change causes a variable that is set in an inner loop but is not ! 46: * put in register there to be ineligible for a register in the outer loop. ! 47: * ! 48: * Revision 5.3 85/09/27 19:58:16 root ! 49: * Ended PCC confusion with sizes of objects in registers by forcing SHORT ! 50: * values in registers to be converted to INT. ! 51: * ! 52: * Revision 5.2 85/09/26 19:36:22 donn ! 53: * Added a fix for a bug that allowed character variables which were ! 54: * arguments to subroutines to be made eligible to be register variables. ! 55: * ! 56: * Revision 5.1 85/08/10 03:49:35 donn ! 57: * 4.3 alpha ! 58: * ! 59: * Revision 2.9 85/03/18 21:35:05 donn ! 60: * Bob Corbett's hack to prevent conflicts between subroutine side effects ! 61: * and register assignment. Makes the code a lot worse... ! 62: * ! 63: * Revision 2.8 85/02/22 02:14:08 donn ! 64: * In code like 'x = foo(x)', alreg() would copy the memory version of the ! 65: * variable 'x' into the register version after the assignment, clobbering ! 66: * the result. A small change to regwrite() seems to prevent this. ! 67: * ! 68: * Revision 2.7 85/02/16 03:32:45 donn ! 69: * Fixed a bug where the loop test and increment were having register ! 70: * substitution performed twice, once in the environment of the current ! 71: * loop and once in the environment of the containing loop. If the ! 72: * containing loop puts (say) the inner loop's index variable in register ! 73: * but the inner loop does not, havoc results. ! 74: * ! 75: * Revision 2.6 85/02/14 23:21:45 donn ! 76: * Don't permit variable references of the form 'a(i)' to be put in register ! 77: * if array 'a' is in common. This is because there is no good way to ! 78: * identify instances of this sort without getting confused with other ! 79: * variables in the same common block which are in register. Sigh. ! 80: * ! 81: * Revision 2.5 85/01/11 21:08:00 donn ! 82: * Made changes so that we pay attention to SAVE statements. Added a new ! 83: * gensetreturn() function to implement this. ! 84: * ! 85: * Revision 2.4 84/09/03 22:37:28 donn ! 86: * Changed the treatment of SKRETURN in alreg() so that all variables in ! 87: * register, not just COMMON variables, get written out to memory before a ! 88: * RETURN. This was causing the return value of a function to get lost when ! 89: * a RETURN was done from inside a loop (among other problems). ! 90: * ! 91: * Revision 2.3 84/08/04 20:52:42 donn ! 92: * Added fixes for EXTERNAL parameters from Jerry Berkman. ! 93: * ! 94: * Revision 2.2 84/08/04 20:34:29 donn ! 95: * Fixed a stupidity pointed out by Jerry Berkman -- the 'floats in register' ! 96: * stuff applies if the TARGET is a VAX, not if the local machine is a VAX. ! 97: * ! 98: * Revision 2.1 84/07/19 12:04:47 donn ! 99: * Changed comment headers for UofU. ! 100: * ! 101: * Revision 1.5 83/11/27 19:25:41 donn ! 102: * Added REAL to the list of types which may appear in registers (VAXen only). ! 103: * ! 104: * Revision 1.4 83/11/13 02:38:39 donn ! 105: * Bug fixed in alreg()'s handling of computed goto's. A '<=' in place of a ! 106: * '<' led to core dumps when we walked off the end of the list of labels... ! 107: * ! 108: * Revision 1.3 83/11/12 01:25:57 donn ! 109: * Bug in redundant register assignment code, mistakenly carried over some old ! 110: * code that sometimes rewound a slot pointer even when a redundant slot wasn't ! 111: * deleted; this caused an infinite loop... Seems to work now. ! 112: * ! 113: * Revision 1.2 83/11/09 14:58:12 donn ! 114: * Took out broken code dealing with redundant register initializations. ! 115: * Couldn't see what to do about redundantly initializing a DO variable but ! 116: * I did fix things so that an assignment from a register into the same ! 117: * register is always deleted. ! 118: * ! 119: */ ! 120: ! 121: #include "defs.h" ! 122: #include "optim.h" ! 123: ! 124: #define LABTABSIZE 101 ! 125: #define VARTABSIZE 1009 ! 126: #define TABLELIMIT 12 ! 127: ! 128: #if TARGET==VAX ! 129: #define MSKREGTYPES M(TYLOGICAL) | M(TYADDR) | M(TYSHORT) | M(TYLONG) | M(TYREAL) ! 130: #else ! 131: #define MSKREGTYPES M(TYLOGICAL) | M(TYADDR) | M(TYSHORT) | M(TYLONG) ! 132: #endif ! 133: ! 134: #define ISREGTYPE(x) ONEOF(x, MSKREGTYPES) ! 135: ! 136: #define MSKVARS M(STGAUTO) | M(STGBSS) | M(STGINIT) | M(STGCONST) |\ ! 137: M(STGEQUIV) | M(STGARG) | M(STGCOMMON) ! 138: ! 139: #define ISVAR(x) ((((expptr) x)->headblock.vclass == CLVAR || \ ! 140: ((expptr) x)->headblock.vclass == CLUNKNOWN) \ ! 141: && ONEOF(((expptr) x)->headblock.vstg, MSKVARS)) ! 142: ! 143: ! 144: typedef ! 145: struct regdata ! 146: { ! 147: field vstg; ! 148: field vtype; ! 149: int memno; ! 150: int memoffset; ! 151: int refs; ! 152: Addrp stgp; ! 153: unsigned isarrayarg : 1; ! 154: unsigned istemp : 1; ! 155: unsigned isset : 1; ! 156: unsigned setfirst : 1; ! 157: } REGDATA; ! 158: ! 159: ! 160: typedef ! 161: struct labelnode ! 162: { ! 163: struct labelnode *link; ! 164: int labelno; ! 165: } LABELNODE; ! 166: ! 167: ! 168: ! 169: typedef ! 170: struct varnode ! 171: { ! 172: struct varnode *link; ! 173: int memoffset; ! 174: unsigned isset : 1; ! 175: unsigned isused : 1; ! 176: unsigned setfirst : 1; ! 177: unsigned unusable : 1; ! 178: int refs; ! 179: Addrp stgp; ! 180: } VARNODE; ! 181: ! 182: ! 183: typedef ! 184: struct addrnode ! 185: { ! 186: struct addrnode *link; ! 187: field vtype; ! 188: field vstg; ! 189: int memno; ! 190: unsigned istemp : 1; ! 191: unsigned isset : 1; ! 192: unsigned loopset : 1; ! 193: unsigned freeuse : 1; ! 194: unsigned mixedtype : 1; ! 195: unsigned fixed : 1; ! 196: int refs; ! 197: struct addrnode *commonlink; ! 198: VARNODE *varlist; ! 199: } ADDRNODE; ! 200: ! 201: ! 202: typedef ! 203: struct setnode ! 204: { ! 205: struct setnode *link; ! 206: field vstg; ! 207: int memno; ! 208: int memoffset; ! 209: } SETNODE; ! 210: ! 211: ! 212: typedef ! 213: struct doqueue ! 214: { ! 215: struct doqueue *up, *down; ! 216: Slotp dohead, doend; ! 217: int nregvars; ! 218: REGNODE *reg[MAXREGVAR]; ! 219: } DOQUEUE; ! 220: ! 221: LOCAL DOQUEUE *dqptr, *dqtop, *dqbottom; ! 222: ! 223: ! 224: LOCAL Slotp dohead; ! 225: LOCAL Slotp doend; ! 226: LOCAL Slotp newcode; ! 227: ! 228: ! 229: ! 230: LOCAL LABELNODE *labeltable[LABTABSIZE]; ! 231: LOCAL ADDRNODE *vartable[VARTABSIZE]; ! 232: LOCAL ADDRNODE *commonvars; ! 233: LOCAL SETNODE *setlist; ! 234: LOCAL int topregvar; ! 235: LOCAL int toplcv; ! 236: LOCAL int allset; ! 237: LOCAL ADDRNODE *currentaddr; ! 238: LOCAL int loopcost; ! 239: LOCAL REGDATA *regtab[MAXREGVAR]; ! 240: LOCAL REGDATA *rt[TABLELIMIT]; ! 241: LOCAL int tabletop; ! 242: LOCAL int linearcode; ! 243: LOCAL int docount; ! 244: LOCAL int globalbranch; ! 245: LOCAL int commonunusable; ! 246: LOCAL int regdefined[MAXREGVAR]; ! 247: LOCAL int memdefined[MAXREGVAR]; ! 248: LOCAL int regaltered[MAXREGVAR]; ! 249: ! 250: ! 251: ! 252: LOCAL insertlabel(l) ! 253: int l; ! 254: ! 255: { ! 256: int key; ! 257: LABELNODE *p; ! 258: ! 259: key = l % LABTABSIZE; ! 260: for (p = labeltable[key]; p; p = p->link) ! 261: if (p->labelno == l) return; ! 262: p = labeltable[key]; ! 263: labeltable[key] = ALLOC(labelnode); ! 264: labeltable[key]->link = p; ! 265: labeltable[key]->labelno = l; ! 266: return; ! 267: } ! 268: ! 269: ! 270: ! 271: LOCAL int locallabel(l) ! 272: int l; ! 273: ! 274: { ! 275: int key; ! 276: LABELNODE *p; ! 277: ! 278: key = l % LABTABSIZE; ! 279: for (p = labeltable[key]; p; p = p->link) ! 280: if (p->labelno == l) return YES; ! 281: ! 282: return NO; ! 283: } ! 284: ! 285: ! 286: ! 287: LOCAL freelabtab() ! 288: ! 289: { ! 290: int i; ! 291: LABELNODE *p, *q; ! 292: ! 293: for (i = 0; i < LABTABSIZE; i++) ! 294: if (labeltable[i]) ! 295: { ! 296: p = labeltable[i]; ! 297: labeltable[i] = NULL; ! 298: while (p) ! 299: { ! 300: q = p->link; ! 301: free(p); ! 302: p = q; ! 303: } ! 304: } ! 305: return; ! 306: } ! 307: ! 308: ! 309: ! 310: LOCAL ADDRNODE *getaddr(ap) ! 311: Addrp ap; ! 312: ! 313: { ! 314: int key; ! 315: field vstg; ! 316: int memno; ! 317: register ADDRNODE *q; ! 318: ADDRNODE *q1; ! 319: ! 320: if (!ISVAR(ap)) ! 321: fatal("regalloc: bad data sent to getaddr"); ! 322: vstg = ap->vstg; ! 323: memno = ap->memno; ! 324: key = (256*vstg + memno) % VARTABSIZE; ! 325: ! 326: for (q = vartable[key]; q; q = q->link) ! 327: if ((q->vstg == vstg) && (q->memno == memno)) ! 328: { ! 329: if (ap->istemp) q->istemp = YES; ! 330: if (ap->vtype != q->vtype) ! 331: q->mixedtype = YES; ! 332: if (!fixedaddress(ap)) ! 333: q->fixed = NO; ! 334: return q; ! 335: } ! 336: ! 337: q1 = vartable[key]; ! 338: vartable[key] = q = ALLOC(addrnode); ! 339: q->link = q1; ! 340: q->vstg = vstg; ! 341: q->memno = memno; ! 342: if (ap->istemp) q->istemp = YES; ! 343: if (fixedaddress(ap)) q->fixed = YES; ! 344: q->vtype = ap->vtype; ! 345: q->varlist = NULL; ! 346: if (vstg == STGCOMMON) ! 347: { ! 348: q->commonlink = commonvars; ! 349: commonvars = q; ! 350: } ! 351: return q; ! 352: } ! 353: ! 354: ! 355: ! 356: LOCAL VARNODE *getvar(ainfo, ap) ! 357: ADDRNODE *ainfo; ! 358: Addrp ap; ! 359: ! 360: { ! 361: register VARNODE *q; ! 362: VARNODE *q1; ! 363: int memoffset; ! 364: ! 365: if (!ISVAR(ap)) ! 366: fatal("regalloc: bad data sent to getvar"); ! 367: ! 368: memoffset = ap->memoffset->constblock.constant.ci; ! 369: ! 370: for (q = ainfo->varlist; q; q = q->link) ! 371: if (q->memoffset == memoffset) ! 372: return q; ! 373: ! 374: q1 = ainfo->varlist; ! 375: ainfo->varlist = q = ALLOC(varnode); ! 376: q->link = q1; ! 377: q->memoffset = memoffset; ! 378: q->stgp = (Addrp) cpexpr(ap); ! 379: return q; ! 380: } ! 381: ! 382: ! 383: LOCAL ADDRNODE *lookupaddr(vstg, memno) ! 384: field vstg; ! 385: int memno; ! 386: ! 387: { ! 388: int key; ! 389: register ADDRNODE *q; ! 390: ! 391: key = (256*vstg + memno) % VARTABSIZE; ! 392: ! 393: for (q = vartable[key]; q; q = q->link) ! 394: if ((q->vstg == vstg) && (q->memno == memno)) ! 395: return q; ! 396: ! 397: fatal("regalloc: lookupaddr"); ! 398: } ! 399: ! 400: ! 401: LOCAL VARNODE *lookupvar(ainfo, memoffset) ! 402: ADDRNODE *ainfo; ! 403: int memoffset; ! 404: ! 405: { ! 406: register VARNODE *q; ! 407: ! 408: for (q = ainfo->varlist; q; q = q->link) ! 409: if (q->memoffset == memoffset) ! 410: return q; ! 411: ! 412: fatal("regalloc: lookupvar"); ! 413: } ! 414: ! 415: ! 416: ! 417: LOCAL int invartable(p) ! 418: REGNODE *p; ! 419: ! 420: { ! 421: field vstg; ! 422: int memno; ! 423: int key; ! 424: register ADDRNODE *q; ! 425: ! 426: vstg = p->vstg; ! 427: memno = p->memno; ! 428: key = (256*vstg + memno) % VARTABSIZE; ! 429: ! 430: for (q = vartable[key]; q; q = q->link) ! 431: if ((q->vstg == vstg) && (q->memno == memno)) ! 432: return YES; ! 433: ! 434: return NO; ! 435: } ! 436: ! 437: ! 438: ! 439: LOCAL freevartab() ! 440: ! 441: { ! 442: register ADDRNODE *p; ! 443: ADDRNODE *p1; ! 444: register VARNODE *q; ! 445: VARNODE *q1; ! 446: register int i; ! 447: ! 448: for (i = 0; i < VARTABSIZE; i++) ! 449: if (vartable[i]) ! 450: { ! 451: p = vartable[i]; ! 452: vartable[i] = NULL; ! 453: ! 454: while (p) ! 455: { ! 456: for (q = p->varlist; q; q = q1) ! 457: { ! 458: q1 = q->link; ! 459: frexpr(q->stgp); ! 460: free ((char *) q); ! 461: } ! 462: p1 = p->link; ! 463: free((char *) p); ! 464: p = p1; ! 465: } ! 466: } ! 467: } ! 468: ! 469: LOCAL varloopset() ! 470: ! 471: { ! 472: register ADDRNODE *p; ! 473: register int i; ! 474: ! 475: for (i = 0; i < VARTABSIZE; i++) ! 476: if (p = vartable[i]) ! 477: if (p->isset == YES) ! 478: p->loopset = YES; ! 479: } ! 480: ! 481: ! 482: ! 483: LOCAL insertset(vstg, memno, memoffset) ! 484: field vstg; ! 485: int memno; ! 486: int memoffset; ! 487: ! 488: { ! 489: register SETNODE *p; ! 490: SETNODE *q; ! 491: ! 492: if (allset) return; ! 493: for (p = setlist; p; p = p->link) ! 494: if((p->vstg == vstg) && (p->memno == memno) && (p->memoffset == memoffset)) ! 495: return; ! 496: ! 497: q = p; ! 498: setlist = p = ALLOC(setnode); ! 499: p->link = q; ! 500: p->vstg = vstg; ! 501: p->memno = memno; ! 502: p->memoffset = memoffset; ! 503: return; ! 504: } ! 505: ! 506: ! 507: ! 508: LOCAL int insetlist(vstg, memno, memoffset) ! 509: field vstg; ! 510: int memno; ! 511: int memoffset; ! 512: ! 513: { ! 514: register SETNODE *p; ! 515: ! 516: if (allset) return YES; ! 517: for (p = setlist; p; p = p->link) ! 518: if((p->vstg == vstg) && (p->memno == memno) && (p->memoffset == memoffset)) ! 519: return YES; ! 520: ! 521: return NO; ! 522: } ! 523: ! 524: ! 525: ! 526: LOCAL clearsets() ! 527: ! 528: { ! 529: register SETNODE *p, *q; ! 530: ! 531: allset = NO; ! 532: ! 533: p = setlist; ! 534: while (p) ! 535: { ! 536: q = p->link; ! 537: free ((char *) p); ! 538: p = q; ! 539: } ! 540: setlist = NULL; ! 541: return; ! 542: } ! 543: ! 544: ! 545: ! 546: LOCAL alreg() ! 547: ! 548: { ! 549: register Slotp sp; ! 550: register int i; ! 551: register ADDRNODE *p; ! 552: register VARNODE *q; ! 553: Slotp sp1, sp2; ! 554: ADDRNODE *addrinfo; ! 555: VARNODE *varinfo; ! 556: struct Labelblock **lp; ! 557: int toptrack; ! 558: int track[MAXREGVAR]; ! 559: Addrp ap, ap1; ! 560: DOQUEUE *dqp; ! 561: REGDATA *rp; ! 562: REGNODE *regp; ! 563: ! 564: if (nregvar >= maxregvar) return; ! 565: ! 566: commonvars = NULL; ! 567: docount = 0; ! 568: ! 569: for (sp = dohead; sp != doend->next; sp = sp->next) ! 570: if (docount > 1) ! 571: switch (sp->type) ! 572: { ! 573: case SKDOHEAD: ! 574: docount++; ! 575: break; ! 576: ! 577: case SKENDDO: ! 578: docount--; ! 579: ! 580: default: ! 581: break; ! 582: } ! 583: else ! 584: switch (sp->type) ! 585: { ! 586: case SKLABEL: ! 587: insertlabel(sp->label); ! 588: break; ! 589: ! 590: case SKARIF: ! 591: case SKASGOTO: ! 592: case SKCALL: ! 593: case SKCMGOTO: ! 594: case SKEQ: ! 595: case SKIFN: ! 596: case SKIOIFN: ! 597: case SKSTOP: ! 598: case SKPAUSE: ! 599: case SKRETURN: ! 600: scanvars(sp->expr); ! 601: break; ! 602: ! 603: case SKDOHEAD: ! 604: ++docount; ! 605: break; ! 606: ! 607: case SKENDDO: ! 608: --docount; ! 609: break; ! 610: ! 611: case SKNULL: ! 612: case SKGOTO: ! 613: case SKASSIGN: ! 614: break; ! 615: ! 616: default: ! 617: badthing ("SKtype", "alreg-1", sp->type); ! 618: } ! 619: ! 620: loopcost = 0; ! 621: docount = 1; ! 622: commonunusable = NO; ! 623: if (! dohead->nullslot) fatal ("missing dohead->nullslot -cbb"); ! 624: for (sp = dohead->next, globalbranch = NO; ! 625: docount; ! 626: sp = sp->next, clearsets(), globalbranch = NO) ! 627: if (docount > 1) ! 628: switch (sp->type) ! 629: { ! 630: case SKDOHEAD: ! 631: docount++; ! 632: break; ! 633: ! 634: case SKENDDO: ! 635: docount--; ! 636: ! 637: default: ! 638: break; ! 639: } ! 640: else ! 641: switch (sp->type) ! 642: { ! 643: case SKARIF: ! 644: #define LM ((struct Labelblock * *)sp->ctlinfo)[0]->labelno ! 645: #define LZ ((struct Labelblock * *)sp->ctlinfo)[1]->labelno ! 646: #define LP ((struct Labelblock * *)sp->ctlinfo)[2]->labelno ! 647: ! 648: if (!locallabel(LM) || !locallabel(LZ) || !locallabel(LP)) ! 649: { ! 650: setall(); ! 651: globalbranch = YES; ! 652: } ! 653: countrefs(sp->expr); ! 654: break; ! 655: ! 656: case SKASGOTO: ! 657: setall(); ! 658: globalbranch = YES; ! 659: countrefs(sp->expr); ! 660: break; ! 661: ! 662: case SKCMGOTO: ! 663: lp = (struct Labelblock **) sp->ctlinfo; ! 664: for (i = 0; i < sp->label; i++, lp++) ! 665: if (!locallabel((*lp)->labelno)) ! 666: { ! 667: setall(); ! 668: globalbranch = YES; ! 669: break; ! 670: } ! 671: countrefs(sp->expr); ! 672: break; ! 673: ! 674: case SKDOHEAD: ! 675: globalbranch = YES; ! 676: loopcost = 2; ! 677: docount++; ! 678: break; ! 679: ! 680: case SKENDDO: ! 681: docount = 0; ! 682: break; ! 683: ! 684: case SKGOTO: ! 685: if (!locallabel(sp->label)) ! 686: { ! 687: setall(); ! 688: globalbranch = YES; ! 689: } ! 690: break; ! 691: ! 692: case SKIFN: ! 693: case SKIOIFN: ! 694: if (!locallabel(sp->label)) ! 695: { ! 696: setall(); ! 697: globalbranch = YES; ! 698: } ! 699: countrefs(sp->expr); ! 700: break; ! 701: ! 702: case SKEQ: ! 703: case SKCALL: ! 704: case SKSTOP: ! 705: case SKPAUSE: ! 706: linearcode = YES; ! 707: countrefs(sp->expr); ! 708: linearcode = NO; ! 709: break; ! 710: } ! 711: ! 712: topregvar = toplcv = nregvar - 1; ! 713: ! 714: for (i = 0; i < nregvar; i++) ! 715: { ! 716: ap = memversion(regnamep[i]); ! 717: regtab[i] = rp = ALLOC(regdata); ! 718: rp->vstg = ap->vstg; ! 719: rp->vtype = ap->vtype; ! 720: rp->memno = ap->memno; ! 721: rp->memoffset = ap->memoffset->constblock.constant.ci; ! 722: rp->isarrayarg = NO; ! 723: rp->stgp = ap; ! 724: } ! 725: ! 726: for (i = 0; i < MAXREGVAR; i++) ! 727: track[i] = YES; ! 728: ! 729: for (dqp = dqptr->down; dqp; dqp = dqp->down) ! 730: { ! 731: if (dqp->nregvars - 1 > topregvar) ! 732: topregvar = dqp->nregvars -1; ! 733: for (i = toplcv + 1; i < dqp->nregvars; i++) ! 734: if (track[i]) ! 735: if (regp = dqp->reg[i]) ! 736: if (rp = regtab[i]) ! 737: { ! 738: if (!samevar(rp, regp)) ! 739: track[i] = NO; ! 740: } ! 741: else if (invartable(regp)) ! 742: { ! 743: regtab[i] = rp = ALLOC(regdata); ! 744: rp->vstg = regp->vstg; ! 745: rp->vtype = regp->vtype; ! 746: rp->memno = regp->memno; ! 747: rp->memoffset = regp->memoffset; ! 748: addrinfo = lookupaddr(rp->vstg, rp->memno); ! 749: if (regp->isarrayarg) ! 750: { ! 751: rp->isarrayarg = YES; ! 752: rp->refs = addrinfo->refs; ! 753: } ! 754: else ! 755: { ! 756: varinfo = lookupvar(addrinfo, regp->memoffset); ! 757: rp->refs = varinfo->refs; ! 758: rp->stgp = (Addrp) cpexpr(varinfo->stgp); ! 759: rp->istemp = addrinfo->istemp; ! 760: rp->isset = varinfo->isset; ! 761: rp->setfirst = varinfo->setfirst; ! 762: } ! 763: } ! 764: else ! 765: track[i] = NO; ! 766: else ! 767: track[i] = NO; ! 768: } ! 769: ! 770: toptrack = topregvar; ! 771: ! 772: for (i = toplcv + 1; i <= topregvar; i++) ! 773: if (regtab[i]) ! 774: if ((track[i] == NO) || (regtab[i]->refs <= 0)) ! 775: { ! 776: free((char *) regtab[i]); ! 777: regtab[i] = NULL; ! 778: } ! 779: ! 780: tabletop = -1; ! 781: if (topregvar < maxregvar - 1) ! 782: for (i = 0; i < VARTABSIZE; i++) ! 783: for (p = vartable[i]; p; p = p->link) ! 784: { ! 785: entableaddr(p); ! 786: if ((!p->loopset) && ! 787: (!p->mixedtype) && ! 788: (p->vstg != STGARG) && ! 789: !((p->vstg == STGCOMMON) && ((!p->fixed) || commonunusable))) ! 790: for (q = p->varlist; q; q = q->link) ! 791: entablevar(q); ! 792: } ! 793: ! 794: for (i = 0; (i <= tabletop) && (topregvar + 1 < maxregvar); i++) ! 795: { ! 796: if (inregtab(rt[i]) || (loopcost && rt[i]->isset)) ! 797: continue; ! 798: topregvar++; ! 799: regtab[topregvar] = rp = ALLOC(regdata); ! 800: rp->vstg = rt[i]->vstg; ! 801: rp->vtype = rt[i]->vtype; ! 802: rp->memno = rt[i]->memno; ! 803: rp->memoffset = rt[i]->memoffset; ! 804: rp->refs = rt[i]->refs; ! 805: rp->stgp = (Addrp) cpexpr(rt[i]->stgp); ! 806: rp->isarrayarg = rt[i]->isarrayarg; ! 807: rp->istemp = rt[i]->istemp; ! 808: rp->isset = rt[i]->isset; ! 809: rp->setfirst = rt[i]->setfirst; ! 810: } ! 811: ! 812: for (i = toplcv + 1; i <= topregvar; i++) ! 813: { ! 814: if (rp = regtab[i]) ! 815: if (rp->isarrayarg) ! 816: { ! 817: ap = ALLOC(Addrblock); ! 818: ap->tag = TADDR; ! 819: ap->vstg = STGREG; ! 820: ap->vtype = TYADDR; ! 821: ap->vclass = CLVAR; ! 822: ap->memno = regnum[i]; ! 823: ap->memoffset = ICON(0); ! 824: ! 825: ap1 = ALLOC(Addrblock); ! 826: ap1->tag = TADDR; ! 827: ap1->vstg = rp->vstg; ! 828: ap1->vtype = rp->vtype; ! 829: ap1->vclass = CLVAR; ! 830: ap1->memno = rp->memno; ! 831: ap1->memoffset = ICON(0); ! 832: ! 833: insertassign(dohead, ap, addrof(ap1)); ! 834: } ! 835: else if (!(rp->setfirst && rp->istemp)) ! 836: { ! 837: if (rp->istemp) ! 838: for (sp = newcode; sp && sp != dohead; sp = sp->next) ! 839: if (sp->type == SKEQ) ! 840: { ! 841: ap = (Addrp) sp->expr->exprblock.leftp; ! 842: if ((ap->vstg == rp->vstg) && (ap->memno == rp->memno) && ! 843: fixedaddress(ap) && ! 844: (ap->memoffset->constblock.constant.ci == rp->memoffset)) ! 845: { ! 846: changetoreg(ap, i); ! 847: goto L1; ! 848: } ! 849: } ! 850: ap = (Addrp) cpexpr(rp->stgp); ! 851: changetoreg(ap, i); ! 852: insertassign(dohead, ap, cpexpr(rp->stgp)); ! 853: } ! 854: L1:; ! 855: } ! 856: ! 857: for (i = toplcv + 1; i <= topregvar; i++) ! 858: if (rp = regtab[i]) ! 859: if (rp->isset && !(rp->istemp || rp->isarrayarg)) ! 860: { ! 861: ap = (Addrp) cpexpr(rp->stgp); ! 862: changetoreg(ap, i); ! 863: appendassign(doend, cpexpr(rp->stgp), ap); ! 864: } ! 865: ! 866: docount = 1; ! 867: clearmems(); ! 868: setregs(); ! 869: sp = dohead->next; ! 870: if (loopcost) ! 871: for (i = toptrack + 1; i <= topregvar; i++) ! 872: if ((rp = regtab[i]) && !rp->isarrayarg) ! 873: { ! 874: ap = (Addrp) cpexpr(rp->stgp); ! 875: changetoreg(ap, i); ! 876: insertassign(sp, cpexpr(rp->stgp), ap); ! 877: } ! 878: ! 879: for ( sp = dohead->next; ! 880: docount || sp->type != SKNULL; ! 881: sp = sp->next) ! 882: if (docount > 1) ! 883: switch (sp->type) ! 884: { ! 885: case SKDOHEAD: ! 886: docount++; ! 887: break; ! 888: ! 889: case SKENDDO: ! 890: if (--docount == 1) ! 891: { ! 892: /* ! 893: * Remove redundant stores to memory. ! 894: */ ! 895: sp1 = sp->nullslot->next; ! 896: while (sp1) ! 897: { ! 898: if (regtomem(sp1)) ! 899: { ! 900: ap = (Addrp) sp1->expr->exprblock.rightp; ! 901: sp2 = sp1->next; ! 902: for (i = toplcv + 2; i <= toptrack; i++) ! 903: if (regtab[i] && (regnum[i] == ap->memno)) ! 904: { ! 905: deleteslot(sp1); ! 906: break; ! 907: } ! 908: sp1 = sp2; ! 909: } ! 910: else ! 911: sp1 = NULL; ! 912: } ! 913: ! 914: /* ! 915: * Restore register variables (complement to DOHEAD code). ! 916: */ ! 917: sp1 = sp->nullslot->next; ! 918: for (i = toplcv + 1; i <= topregvar; i++) ! 919: if (rp = regtab[i]) ! 920: if (!regdefined[i]) ! 921: if (i >= dqp->nregvars || !samevar(rp, dqp->reg[i])) ! 922: { ! 923: ap = (Addrp) cpexpr(rp->stgp); ! 924: changetoreg(ap, i); ! 925: insertassign(sp1, ap, cpexpr(rp->stgp)); ! 926: regdefined[i] = YES; ! 927: } ! 928: ! 929: clearmems(); ! 930: if (toplcv + 1 < maxregvar) ! 931: memdefined[toplcv + 1] = YES; ! 932: sp = sp1->prev; ! 933: } ! 934: break; ! 935: } ! 936: else ! 937: { ! 938: setregs(); ! 939: for (i = 0; i <= MAXREGVAR; i++) ! 940: regaltered[i] = NO; ! 941: globalbranch = NO; ! 942: ! 943: switch (sp->type) ! 944: { ! 945: case SKLABEL: ! 946: clearmems(); ! 947: break; ! 948: ! 949: case SKGOTO: ! 950: if (!locallabel(sp->label)) ! 951: gensetall(sp); ! 952: break; ! 953: ! 954: case SKENDDO: ! 955: docount = 0; ! 956: break; ! 957: ! 958: case SKRETURN: ! 959: gensetreturn(sp); ! 960: linearcode = YES; ! 961: regwrite(sp, sp->expr); ! 962: linearcode = NO; ! 963: break; ! 964: ! 965: case SKDOHEAD: ! 966: /* ! 967: * If one of the current loop's register variables is not in ! 968: * register in an inner loop, we must save it. It's a pity ! 969: * we don't save enough info to optimize this properly... ! 970: */ ! 971: for (dqp = dqptr->down; dqp; dqp = dqp->down) ! 972: if (dqp->dohead == sp) ! 973: break; ! 974: if (dqp == NULL) ! 975: fatal("confused in alreg loop analysis"); ! 976: for (i = toplcv + 1; i <= topregvar; i++) ! 977: if (rp = regtab[i]) ! 978: if (!memdefined[i]) ! 979: if (i >= dqp->nregvars || !samevar(rp, dqp->reg[i])) ! 980: { ! 981: ap = (Addrp) cpexpr(rp->stgp); ! 982: changetoreg(ap, i); ! 983: insertassign(sp, cpexpr(rp->stgp), ap); ! 984: memdefined[i] = YES; ! 985: regdefined[i] = NO; ! 986: } ! 987: ! 988: docount++; ! 989: globalbranch = YES; ! 990: break; ! 991: ! 992: case SKEQ: ! 993: case SKCALL: ! 994: case SKSTOP: ! 995: case SKPAUSE: ! 996: linearcode = YES; ! 997: regwrite(sp, sp->expr); ! 998: for (i = toplcv + 1; i <= topregvar; i++) ! 999: if (!regdefined[i] && ((rp = regtab[i]) && rp->isset)) ! 1000: { ! 1001: ap = (Addrp) cpexpr(rp->stgp); ! 1002: changetoreg(ap, i); ! 1003: appendassign(sp, ap, cpexpr(rp->stgp)); ! 1004: sp = sp->next; ! 1005: regdefined[i] = YES; ! 1006: } ! 1007: linearcode = NO; ! 1008: ! 1009: /* ! 1010: * Eliminate redundant register moves. ! 1011: */ ! 1012: if (regtoreg(sp)) ! 1013: { ! 1014: ap = (Addrp) sp->expr->exprblock.leftp; ! 1015: sp1 = sp->prev; ! 1016: for (i = toplcv + 1; i <= toptrack; i++) ! 1017: if (regtab[i] && (regnum[i] == ap->memno)) ! 1018: { ! 1019: deleteslot(sp); ! 1020: sp = sp1; ! 1021: break; ! 1022: } ! 1023: } ! 1024: break; ! 1025: ! 1026: case SKARIF: ! 1027: if (!locallabel(LM) || !locallabel(LZ) || !locallabel(LP)) ! 1028: { ! 1029: gensetall(sp); ! 1030: globalbranch = YES; ! 1031: } ! 1032: regwrite(sp, sp->expr); ! 1033: break; ! 1034: ! 1035: case SKASGOTO: ! 1036: gensetall(sp); ! 1037: globalbranch = YES; ! 1038: regwrite(sp, sp->expr); ! 1039: break; ! 1040: ! 1041: case SKCMGOTO: ! 1042: lp = (struct Labelblock **) sp->ctlinfo; ! 1043: for (i = 0; i < sp->label; i++, lp++) ! 1044: if (!locallabel((*lp)->labelno)) ! 1045: { ! 1046: gensetall(sp); ! 1047: globalbranch = YES; ! 1048: break; ! 1049: } ! 1050: regwrite(sp, sp->expr); ! 1051: break; ! 1052: ! 1053: case SKIFN: ! 1054: case SKIOIFN: ! 1055: if (!locallabel(sp->label)) ! 1056: { ! 1057: gensetall(sp); ! 1058: globalbranch = YES; ! 1059: } ! 1060: regwrite(sp, sp->expr); ! 1061: break; ! 1062: ! 1063: case SKNULL: ! 1064: case SKASSIGN: ! 1065: break; ! 1066: ! 1067: default: ! 1068: badthing ("SKtype","alreg-3",sp->type); ! 1069: } ! 1070: ! 1071: for (i = toplcv + 1; i <= topregvar; i++) ! 1072: if (regaltered[i]) ! 1073: memdefined[i] = NO; ! 1074: } ! 1075: ! 1076: if (topregvar + 1 > highregvar) ! 1077: highregvar = topregvar + 1; ! 1078: dqptr->nregvars = topregvar + 1; ! 1079: for (i = 0; i <= topregvar; i++) ! 1080: if (rp = regtab[i]) ! 1081: { ! 1082: dqptr->reg[i] = regp = ALLOC(regnode); ! 1083: regp->vstg = rp->vstg; ! 1084: regp->vtype = rp->vtype; ! 1085: regp->memno = rp->memno; ! 1086: regp->memoffset = rp->memoffset; ! 1087: regp->isarrayarg = rp->isarrayarg; ! 1088: frexpr(rp->stgp); ! 1089: free((char *) rp); ! 1090: regtab[i] = NULL; ! 1091: } ! 1092: ! 1093: while (tabletop >= 0) ! 1094: free((char *) rt[tabletop--]); ! 1095: varloopset(); ! 1096: return; ! 1097: } ! 1098: ! 1099: ! 1100: ! 1101: LOCAL scanvars(p) ! 1102: expptr p; ! 1103: ! 1104: { ! 1105: Addrp ap; ! 1106: ADDRNODE *addrinfo; ! 1107: VARNODE *varinfo; ! 1108: chainp args; ! 1109: VARNODE *q; ! 1110: ! 1111: if (p == NULL) return; ! 1112: ! 1113: switch (p->tag) ! 1114: { ! 1115: case TCONST: ! 1116: return; ! 1117: ! 1118: case TEXPR: ! 1119: switch (p->exprblock.opcode) ! 1120: { ! 1121: case OPASSIGN: ! 1122: scanassign(p); ! 1123: return; ! 1124: ! 1125: case OPPLUSEQ: ! 1126: case OPSTAREQ: ! 1127: scanopeq(p); ! 1128: return; ! 1129: ! 1130: case OPCALL: ! 1131: scancall(p); ! 1132: return; ! 1133: ! 1134: default: ! 1135: scanvars(p->exprblock.vleng); ! 1136: scanvars(p->exprblock.leftp); ! 1137: scanvars(p->exprblock.rightp); ! 1138: return; ! 1139: } ! 1140: ! 1141: case TADDR: ! 1142: ap = (Addrp) p; ! 1143: scanvars(ap->vleng); ! 1144: scanvars(ap->memoffset); ! 1145: if (!ISVAR(ap)) return; ! 1146: ! 1147: addrinfo = getaddr(ap); ! 1148: if (fixedaddress(ap)) ! 1149: { ! 1150: if (ISREGTYPE(ap->vtype)) ! 1151: { ! 1152: varinfo = getvar(addrinfo, ap); ! 1153: varinfo->isused = YES; ! 1154: } ! 1155: } ! 1156: else ! 1157: { ! 1158: addrinfo->freeuse = YES; ! 1159: for (q = addrinfo->varlist; q; q = q->link) ! 1160: q->isused = YES; ! 1161: } ! 1162: return; ! 1163: ! 1164: case TLIST: ! 1165: for (args = p->listblock.listp; args; args = args->nextp) ! 1166: scanvars(args->datap); ! 1167: return; ! 1168: ! 1169: default: ! 1170: badtag ("regalloc:scanvars", p->tag); ! 1171: } ! 1172: } ! 1173: ! 1174: ! 1175: ! 1176: LOCAL scanassign(ep) ! 1177: Exprp ep; ! 1178: ! 1179: { ! 1180: Addrp lhs; ! 1181: VARNODE *varinfo; ! 1182: ADDRNODE *addrinfo; ! 1183: ! 1184: scanvars(ep->rightp); ! 1185: if (ep->leftp->tag == TADDR) ! 1186: { ! 1187: lhs = (Addrp) ep->leftp; ! 1188: scanvars(lhs->vleng); ! 1189: scanvars(lhs->memoffset); ! 1190: if ((lhs->vstg == STGREG) || (lhs->vstg == STGPREG)) ! 1191: return; ! 1192: if (ISVAR(lhs)) ! 1193: { ! 1194: addrinfo = getaddr(lhs); ! 1195: addrinfo->isset = YES; ! 1196: if (docount > 1) ! 1197: addrinfo->loopset = YES; ! 1198: if (fixedaddress(lhs) && ISREGTYPE(lhs->vtype)) ! 1199: { ! 1200: varinfo = getvar(addrinfo, lhs); ! 1201: if (addrinfo->freeuse) varinfo->isused = YES; ! 1202: varinfo->isset = YES; ! 1203: if (!addrinfo->freeuse && !varinfo->isused) ! 1204: varinfo->setfirst = YES; ! 1205: } ! 1206: } ! 1207: } ! 1208: else ! 1209: badtag ("regalloc:scanassign", ep->leftp->tag); ! 1210: } ! 1211: ! 1212: ! 1213: ! 1214: LOCAL scanopeq(ep) ! 1215: Exprp ep; ! 1216: ! 1217: { ! 1218: Addrp lhs; ! 1219: ADDRNODE *addrinfo; ! 1220: VARNODE *varinfo; ! 1221: ! 1222: scanvars(ep->rightp); ! 1223: if (ep->leftp->tag == TADDR) ! 1224: { ! 1225: lhs = (Addrp) ep->leftp; ! 1226: scanvars(lhs->vleng); ! 1227: scanvars(lhs->memoffset); ! 1228: if ((lhs->vstg == STGREG) || (lhs->vstg == STGPREG)) ! 1229: return; ! 1230: if (ISVAR(lhs)) ! 1231: { ! 1232: addrinfo = getaddr(lhs); ! 1233: addrinfo->isset = YES; ! 1234: if (docount > 1) ! 1235: addrinfo->loopset = YES; ! 1236: if (fixedaddress(lhs)) ! 1237: { ! 1238: if (ISREGTYPE(lhs->vtype)) ! 1239: { ! 1240: varinfo = getvar(addrinfo, lhs); ! 1241: varinfo->isused = YES; ! 1242: varinfo->isset = YES; ! 1243: } ! 1244: } ! 1245: } ! 1246: else ! 1247: addrinfo->freeuse = YES; ! 1248: } ! 1249: else ! 1250: badtag ("regalloc:scanopeq", ep->leftp->tag); ! 1251: } ! 1252: ! 1253: ! 1254: ! 1255: LOCAL scancall(ep) ! 1256: Exprp ep; ! 1257: ! 1258: { ! 1259: Addrp lhs; ! 1260: chainp args; ! 1261: Addrp ap; ! 1262: VARNODE *varinfo; ! 1263: ADDRNODE *addrinfo; ! 1264: ! 1265: lhs = (Addrp) ep->leftp; ! 1266: scanvars(lhs->vleng); ! 1267: scanvars(lhs->memoffset); ! 1268: ! 1269: if (ep->rightp == NULL) return; ! 1270: ! 1271: if (lhs->vstg != STGINTR) ! 1272: { ! 1273: args = ep->rightp->listblock.listp; ! 1274: for (; args; args = args->nextp) ! 1275: { ! 1276: if (args->datap->tag == TADDR) ! 1277: { ! 1278: ap = (Addrp) args->datap; ! 1279: scanvars(ap->vleng); ! 1280: scanvars(ap->memoffset); ! 1281: if (!ISVAR(ap)) continue; ! 1282: ! 1283: addrinfo = getaddr(ap); ! 1284: addrinfo->isset = YES; ! 1285: if (docount > 1) ! 1286: addrinfo->loopset = YES; ! 1287: if (fixedaddress(ap) && ISREGTYPE(ap->vtype)) ! 1288: { ! 1289: varinfo = getvar(addrinfo, ap); ! 1290: if (ap->vstg != STGCONST) ! 1291: varinfo->isset = YES; ! 1292: varinfo->isused = YES; ! 1293: } ! 1294: else ! 1295: addrinfo->freeuse = YES; ! 1296: } ! 1297: else ! 1298: scanvars(args->datap); ! 1299: } ! 1300: } ! 1301: else ! 1302: scanvars(ep->rightp); ! 1303: ! 1304: return; ! 1305: } ! 1306: ! 1307: ! 1308: ! 1309: LOCAL int fixedaddress(ap) ! 1310: Addrp ap; ! 1311: ! 1312: { ! 1313: if (!ap->memoffset) ! 1314: return NO; ! 1315: return (ISCONST(ap->memoffset) && ISINT(ap->memoffset->headblock.vtype)); ! 1316: } ! 1317: ! 1318: ! 1319: ! 1320: LOCAL countrefs(p) ! 1321: expptr p; ! 1322: ! 1323: { ! 1324: Addrp ap; ! 1325: ADDRNODE *addrinfo; ! 1326: VARNODE *varinfo; ! 1327: VARNODE *vp; ! 1328: chainp args; ! 1329: ! 1330: if (p == NULL) return; ! 1331: ! 1332: switch (p->tag) ! 1333: { ! 1334: case TCONST: ! 1335: return; ! 1336: ! 1337: case TEXPR: ! 1338: switch (p->exprblock.opcode) ! 1339: { ! 1340: case OPCALL: ! 1341: if (p->exprblock.leftp->tag != TADDR) ! 1342: badtag ("regalloc:countrefs", p->exprblock.leftp->tag); ! 1343: countrefs(p->exprblock.leftp->addrblock.vleng); ! 1344: countrefs(p->exprblock.leftp->addrblock.memoffset); ! 1345: ! 1346: if (p->exprblock.leftp->addrblock.vstg != STGINTR) ! 1347: { ! 1348: if (!commonunusable) ! 1349: if (linearcode) ! 1350: setcommon(); ! 1351: else ! 1352: commonunusable = YES; ! 1353: if (p->exprblock.rightp == NULL) return; ! 1354: args = p->exprblock.rightp->listblock.listp; ! 1355: for (; args; args = args->nextp) ! 1356: if (args->datap->tag == TADDR) ! 1357: { ! 1358: ap = (Addrp) args->datap; ! 1359: countrefs(ap->vleng); ! 1360: countrefs(ap->memoffset); ! 1361: if (!ISVAR(ap) || ap->vstg == STGCONST) continue; ! 1362: addrinfo = lookupaddr(ap->vstg, ap->memno); ! 1363: if (ap->vstg == STGARG) ! 1364: addrinfo->refs++; ! 1365: for (vp = addrinfo->varlist; vp; vp = vp->link) ! 1366: if (linearcode) ! 1367: if (!insetlist(ap->vstg, ap->memno, vp->memoffset)) ! 1368: if (addrinfo->istemp) ! 1369: vp->refs--; ! 1370: else ! 1371: { ! 1372: vp->refs -= 2; ! 1373: insertset(ap->vstg, ap->memno, vp->memoffset); ! 1374: } ! 1375: else ! 1376: vp->refs--; ! 1377: else ! 1378: { ! 1379: if (!addrinfo->istemp) ! 1380: vp->unusable = YES; ! 1381: } ! 1382: } ! 1383: else ! 1384: countrefs(args->datap); ! 1385: } ! 1386: else ! 1387: { ! 1388: if (p->exprblock.rightp == NULL) return; ! 1389: args = p->exprblock.rightp->listblock.listp; ! 1390: for (; args; args = args->nextp) ! 1391: if (args->datap->tag == TADDR) ! 1392: { ! 1393: ap = (Addrp) args->datap; ! 1394: countrefs(ap->vleng); ! 1395: countrefs(ap->memoffset); ! 1396: if (!ISVAR(ap) || ap->vstg == STGCONST) continue; ! 1397: addrinfo = lookupaddr(ap->vstg, ap->memno); ! 1398: addrinfo->refs++; ! 1399: for (vp = addrinfo->varlist; vp; vp = vp->link) ! 1400: if (!insetlist(ap->vstg, ap->memno, vp->memoffset)) ! 1401: { ! 1402: vp->refs--; ! 1403: insertset(ap->vstg, ap->memno, vp->memoffset); ! 1404: } ! 1405: } ! 1406: else ! 1407: countrefs(args->datap); ! 1408: } ! 1409: return; ! 1410: ! 1411: case OPASSIGN: ! 1412: case OPPLUSEQ: ! 1413: case OPSTAREQ: ! 1414: countrefs(p->exprblock.vleng); ! 1415: countrefs(p->exprblock.rightp); ! 1416: ap = (Addrp) p->exprblock.leftp; ! 1417: if (fixedaddress(ap)) ! 1418: if (globalbranch) ! 1419: { ! 1420: countrefs(ap->vleng); ! 1421: countrefs(ap->memoffset); ! 1422: } ! 1423: else ! 1424: countrefs(ap); ! 1425: else if (linearcode) ! 1426: { ! 1427: countrefs(ap); ! 1428: for (vp = lookupaddr(ap->vstg, ap->memno)->varlist; ! 1429: vp; ! 1430: vp = vp->link) ! 1431: vp->refs--; ! 1432: } ! 1433: else ! 1434: { ! 1435: countrefs(ap); ! 1436: for (vp = lookupaddr(ap->vstg, ap->memno)->varlist; ! 1437: vp; ! 1438: vp = vp->link) ! 1439: vp->unusable = YES; ! 1440: } ! 1441: return; ! 1442: ! 1443: default: ! 1444: countrefs(p->exprblock.vleng); ! 1445: countrefs(p->exprblock.leftp); ! 1446: countrefs(p->exprblock.rightp); ! 1447: return; ! 1448: } ! 1449: ! 1450: case TADDR: ! 1451: ap = (Addrp) p; ! 1452: countrefs(ap->vleng); ! 1453: countrefs(ap->memoffset); ! 1454: if (!ISVAR(ap)) return; ! 1455: ! 1456: addrinfo = lookupaddr(ap->vstg, ap->memno); ! 1457: if (ap->vstg == STGARG) ! 1458: addrinfo->refs++; ! 1459: ! 1460: if (fixedaddress(ap)) ! 1461: { ! 1462: if (ISREGTYPE(ap->vtype)) ! 1463: { ! 1464: varinfo = lookupvar(addrinfo, ap->memoffset->constblock.constant.ci); ! 1465: varinfo->refs++; ! 1466: } ! 1467: } ! 1468: else ! 1469: for (vp = addrinfo->varlist; vp; vp = vp->link) ! 1470: if (!insetlist(ap->vstg, ap->memno, vp->memoffset)) ! 1471: { ! 1472: vp->refs--; ! 1473: insertset(ap->vstg, ap->memno, vp->memoffset); ! 1474: } ! 1475: return; ! 1476: ! 1477: case TLIST: ! 1478: args = p->listblock.listp; ! 1479: for (; args; args = args->nextp) ! 1480: countrefs(args->datap); ! 1481: return; ! 1482: ! 1483: default: ! 1484: badtag ("regalloc:countrefs", p->tag); ! 1485: } ! 1486: } ! 1487: ! 1488: ! 1489: ! 1490: LOCAL regwrite(sp, p) ! 1491: Slotp sp; ! 1492: expptr p; ! 1493: ! 1494: { ! 1495: register int i; ! 1496: REGDATA *rp; ! 1497: chainp args; ! 1498: Addrp ap, ap1; ! 1499: int memoffset; ! 1500: ! 1501: if (p == NULL) return; ! 1502: ! 1503: switch (p->tag) ! 1504: { ! 1505: case TCONST: ! 1506: return; ! 1507: ! 1508: case TEXPR: ! 1509: switch (p->exprblock.opcode) ! 1510: { ! 1511: case OPCALL: ! 1512: ap = (Addrp) p->exprblock.leftp; ! 1513: regwrite(sp, ap->vleng); ! 1514: regwrite(sp, ap->memoffset); ! 1515: if (ap->vstg != STGINTR) ! 1516: { ! 1517: if (linearcode) ! 1518: { ! 1519: gensetcommon(sp); ! 1520: for (i = toplcv + 1; i <= topregvar; i++) ! 1521: if ((rp = regtab[i]) && (rp->vstg == STGCOMMON)) ! 1522: regdefined[i] = NO; ! 1523: } ! 1524: if (p->exprblock.rightp == NULL) return; ! 1525: args = p->exprblock.rightp->listblock.listp; ! 1526: for (; args; args = args->nextp) ! 1527: if (args->datap->tag == TADDR) ! 1528: { ! 1529: ap = (Addrp) args->datap; ! 1530: regwrite(sp, ap->vleng); ! 1531: regwrite(sp, ap->memoffset); ! 1532: for (i = toplcv + 1; i <= topregvar; i++) ! 1533: if ((rp = regtab[i]) && ! 1534: !rp->isarrayarg && ! 1535: !rp->istemp && ! 1536: (rp->vstg == ap->vstg) && ! 1537: (rp->memno == ap->memno)) ! 1538: { ! 1539: regdefined[i] = NO; ! 1540: if (!memdefined[i]) ! 1541: { ! 1542: ap1 = (Addrp) cpexpr(rp->stgp); ! 1543: changetoreg(ap1, i); ! 1544: insertassign(sp, cpexpr(rp->stgp), ap1); ! 1545: memdefined[i] = YES; ! 1546: } ! 1547: } ! 1548: else if (rp->isarrayarg && ! 1549: (ap->vstg == STGARG) && ! 1550: (ap->memno == rp->memno)) ! 1551: { ! 1552: ap->vstg = STGPREG; ! 1553: ap->memno = regnum[i]; ! 1554: } ! 1555: } ! 1556: else ! 1557: regwrite(sp, args->datap); ! 1558: } ! 1559: else ! 1560: { ! 1561: if (p->exprblock.rightp == NULL) return; ! 1562: args = p->exprblock.rightp->listblock.listp; ! 1563: for (; args; args = args->nextp) ! 1564: if (args->datap->tag == TADDR) ! 1565: { ! 1566: ap = (Addrp) args->datap; ! 1567: regwrite(sp, ap->vleng); ! 1568: regwrite(sp, ap->memoffset); ! 1569: for (i = toplcv + 1; i <= topregvar; i++) ! 1570: if ((rp = regtab[i]) && ! 1571: !rp->isarrayarg && ! 1572: !rp->istemp && ! 1573: (rp->vstg == ap->vstg) && ! 1574: (rp->memno == ap->memno) && ! 1575: !memdefined[i]) ! 1576: { ! 1577: ap1 = (Addrp) cpexpr(rp->stgp); ! 1578: changetoreg(ap1, i); ! 1579: insertassign(sp, cpexpr(rp->stgp), ap1); ! 1580: memdefined[i] = YES; ! 1581: } ! 1582: else if (rp->isarrayarg && ! 1583: (ap->vstg == STGARG) && ! 1584: (rp->memno == ap->memno)) ! 1585: { ! 1586: ap->vstg = STGPREG; ! 1587: ap->memno = regnum[i]; ! 1588: } ! 1589: } ! 1590: else ! 1591: { ! 1592: regwrite(sp, args->datap); ! 1593: } ! 1594: } ! 1595: return; ! 1596: ! 1597: case OPASSIGN: ! 1598: case OPPLUSEQ: ! 1599: case OPSTAREQ: ! 1600: regwrite(sp, p->exprblock.vleng); ! 1601: regwrite(sp, p->exprblock.rightp); ! 1602: ap = (Addrp) p->exprblock.leftp; ! 1603: regwrite(sp, ap->vleng); ! 1604: regwrite(sp, ap->memoffset); ! 1605: ! 1606: if (ap->vstg == STGARG) ! 1607: for (i = toplcv + 1; i<=topregvar; i++) ! 1608: if ((rp = regtab[i]) && ! 1609: rp->isarrayarg && ! 1610: (rp->memno == ap->memno)) ! 1611: { ! 1612: ap->vstg = STGPREG; ! 1613: ap->memno = regnum[i]; ! 1614: return; ! 1615: } ! 1616: ! 1617: if (fixedaddress(ap)) ! 1618: { ! 1619: memoffset = ap->memoffset->constblock.constant.ci; ! 1620: for (i = toplcv + 1; i <= topregvar; i++) ! 1621: if ((rp = regtab[i]) && ! 1622: !rp->isarrayarg && ! 1623: (rp->vstg == ap->vstg) && ! 1624: (rp->memno == ap->memno) && ! 1625: (rp->memoffset == memoffset)) ! 1626: { ! 1627: changetoreg(ap, i); ! 1628: if (globalbranch) ! 1629: { ! 1630: p->exprblock.rightp = (expptr) cpexpr(p); ! 1631: p->exprblock.leftp = (expptr) cpexpr(rp->stgp); ! 1632: p->exprblock.opcode = OPASSIGN; ! 1633: memdefined[i] = YES; ! 1634: } ! 1635: else ! 1636: { ! 1637: regaltered[i] = YES; ! 1638: regdefined[i] = YES; ! 1639: } ! 1640: } ! 1641: return; ! 1642: } ! 1643: ! 1644: if (linearcode) ! 1645: for (i = toplcv + 1; i <= topregvar; i++) ! 1646: if ((rp = regtab[i]) && ! 1647: !rp->isarrayarg && ! 1648: (rp->vstg == ap->vstg) && ! 1649: (rp->memno == ap->memno)) ! 1650: regdefined[i] = NO; ! 1651: return; ! 1652: ! 1653: default: ! 1654: regwrite(sp, p->exprblock.vleng); ! 1655: regwrite(sp, p->exprblock.leftp); ! 1656: regwrite(sp, p->exprblock.rightp); ! 1657: return; ! 1658: } ! 1659: ! 1660: case TADDR: ! 1661: ap = (Addrp) p; ! 1662: regwrite(sp, ap->vleng); ! 1663: regwrite(sp, ap->memoffset); ! 1664: ! 1665: if (ap->vstg == STGARG) ! 1666: for (i = toplcv + 1; i <= topregvar; i++) ! 1667: if ((rp = regtab[i]) && ! 1668: rp->isarrayarg && ! 1669: (rp->memno == ap->memno)) ! 1670: { ! 1671: ap->vstg = STGPREG; ! 1672: ap->memno = regnum[i]; ! 1673: return; ! 1674: } ! 1675: ! 1676: if (fixedaddress(ap)) ! 1677: { ! 1678: memoffset = ap->memoffset->constblock.constant.ci; ! 1679: for (i = toplcv + 1; i <= topregvar; i++) ! 1680: if ((rp = regtab[i]) && ! 1681: !rp->isarrayarg && ! 1682: (rp->vstg == ap->vstg) && ! 1683: (rp->memno == ap->memno) && ! 1684: (rp->memoffset == memoffset)) ! 1685: { ! 1686: changetoreg(ap, i); ! 1687: return; ! 1688: } ! 1689: } ! 1690: else ! 1691: { ! 1692: for (i = toplcv + 1; i <= topregvar; i++) ! 1693: if ((rp = regtab[i]) && ! 1694: !rp->isarrayarg && ! 1695: (rp->vstg == ap->vstg) && ! 1696: (rp->memno == ap->memno) && ! 1697: !memdefined[i]) ! 1698: { ! 1699: ap1 = (Addrp) cpexpr(rp->stgp); ! 1700: changetoreg(ap1, i); ! 1701: insertassign(sp, cpexpr(rp->stgp), ap1); ! 1702: memdefined[i] = YES; ! 1703: } ! 1704: } ! 1705: return; ! 1706: ! 1707: case TLIST: ! 1708: for (args = p->listblock.listp; args; args = args->nextp) ! 1709: regwrite(sp, args->datap); ! 1710: return; ! 1711: ! 1712: default: ! 1713: badtag ("regalloc:regwrite", p->tag); ! 1714: } ! 1715: } ! 1716: ! 1717: ! 1718: ! 1719: LOCAL setcommon() ! 1720: ! 1721: { ! 1722: ADDRNODE *ap; ! 1723: VARNODE *vp; ! 1724: ! 1725: for (ap = commonvars; ap; ap = ap->commonlink) ! 1726: for (vp = ap->varlist; vp; vp = vp->link) ! 1727: if (!insetlist(ap->vstg, ap->memno, vp->memoffset)) ! 1728: { ! 1729: vp->refs -= 2; ! 1730: insertset(ap->vstg, ap->memno, vp->memoffset); ! 1731: } ! 1732: else ! 1733: vp->refs--; ! 1734: ! 1735: return; ! 1736: } ! 1737: ! 1738: ! 1739: ! 1740: LOCAL setall() ! 1741: ! 1742: { ! 1743: register int i; ! 1744: register ADDRNODE *p; ! 1745: register VARNODE *q; ! 1746: ! 1747: for (i = 0; i < VARTABSIZE; i++) ! 1748: for (p = vartable[i]; p; p = p->link) ! 1749: if (p->istemp || !p->isset) ! 1750: break; ! 1751: else ! 1752: for (q = p->varlist; q; q = q->link) ! 1753: if (q->isset && !insetlist(p->vstg, p->memno, q->memoffset)) ! 1754: q->refs--; ! 1755: ! 1756: allset = YES; ! 1757: return; ! 1758: } ! 1759: ! 1760: ! 1761: ! 1762: LOCAL int samevar(r1, r2) ! 1763: register REGDATA *r1; ! 1764: register REGNODE *r2; ! 1765: ! 1766: { ! 1767: if ((r1->vstg != r2->vstg) || ! 1768: (r1->memno != r2->memno) || ! 1769: (r1->isarrayarg != r2->isarrayarg)) ! 1770: return NO; ! 1771: if (r1->isarrayarg) ! 1772: return YES; ! 1773: return (r1->memoffset == r2->memoffset); ! 1774: } ! 1775: ! 1776: ! 1777: ! 1778: LOCAL entableaddr(p) ! 1779: ADDRNODE *p; ! 1780: ! 1781: { ! 1782: int refs; ! 1783: Addrp ap; ! 1784: register int i; ! 1785: ! 1786: if (p->vstg != STGARG) ! 1787: { ! 1788: currentaddr = p; ! 1789: return; ! 1790: } ! 1791: ! 1792: refs = p->refs; ! 1793: if (refs <= 0) return; ! 1794: ! 1795: if (tabletop < 0) ! 1796: tabletop = i = 0; ! 1797: else if (refs > rt[tabletop]->refs) ! 1798: { ! 1799: if (tabletop + 1 < TABLELIMIT) ! 1800: tabletop++; ! 1801: else ! 1802: { ! 1803: frexpr(rt[tabletop]->stgp); ! 1804: free((char *) rt[tabletop]); ! 1805: } ! 1806: ! 1807: for (i = tabletop; i > 0; i--) ! 1808: if (refs > rt[i - 1]->refs) ! 1809: rt[i] = rt[i - 1]; ! 1810: else ! 1811: break; ! 1812: } ! 1813: else if (tabletop + 1 < TABLELIMIT) ! 1814: i = ++tabletop; ! 1815: else ! 1816: return; ! 1817: ! 1818: rt[i] = ALLOC(regdata); ! 1819: rt[i]->vstg = p->vstg; ! 1820: rt[i]->vtype = p->vtype; ! 1821: rt[i]->memno = p->memno; ! 1822: rt[i]->refs = refs; ! 1823: rt[i]->isarrayarg = YES; ! 1824: ! 1825: return; ! 1826: } ! 1827: ! 1828: ! 1829: ! 1830: ! 1831: LOCAL entablevar(p) ! 1832: VARNODE *p; ! 1833: ! 1834: { ! 1835: int refs; ! 1836: register int i; ! 1837: ! 1838: if (p->unusable) return; ! 1839: refs = p->refs - loopcost; ! 1840: if (refs <= 0) return; ! 1841: ! 1842: if (tabletop < 0) ! 1843: tabletop = i = 0; ! 1844: else if (refs > rt[tabletop]->refs) ! 1845: { ! 1846: if (tabletop + 1 < TABLELIMIT) ! 1847: tabletop++; ! 1848: else ! 1849: { ! 1850: frexpr(rt[tabletop]->stgp); ! 1851: free((char *) rt[tabletop]); ! 1852: } ! 1853: ! 1854: for (i = tabletop; i > 0; i--) ! 1855: if (refs > rt[i - 1]->refs) ! 1856: rt[i] = rt[i - 1]; ! 1857: else ! 1858: break; ! 1859: } ! 1860: else if (tabletop + 1 < TABLELIMIT) ! 1861: i = ++tabletop; ! 1862: else ! 1863: return; ! 1864: ! 1865: rt[i] = ALLOC(regdata); ! 1866: rt[i]->vstg = currentaddr->vstg; ! 1867: rt[i]->vtype = currentaddr->vtype; ! 1868: rt[i]->memno = currentaddr->memno; ! 1869: rt[i]->memoffset = p->memoffset; ! 1870: rt[i]->refs = refs; ! 1871: rt[i]->stgp = (Addrp) cpexpr(p->stgp); ! 1872: rt[i]->isarrayarg = NO; ! 1873: rt[i]->istemp = currentaddr->istemp; ! 1874: rt[i]->isset = p->isset; ! 1875: rt[i]->setfirst = p->setfirst; ! 1876: ! 1877: return; ! 1878: } ! 1879: ! 1880: ! 1881: ! 1882: LOCAL int inregtab(p) ! 1883: register REGDATA *p; ! 1884: ! 1885: { ! 1886: register REGDATA *rp; ! 1887: register int i; ! 1888: ! 1889: for (i = 0; i <= topregvar; i++) ! 1890: if (rp = regtab[i]) ! 1891: if ((rp->vstg == p->vstg) && ! 1892: (rp->memno == p->memno) && ! 1893: (rp->isarrayarg == p->isarrayarg)) ! 1894: if (rp->isarrayarg) ! 1895: return YES; ! 1896: else if (rp->memoffset == p->memoffset) ! 1897: return YES; ! 1898: ! 1899: return NO; ! 1900: } ! 1901: ! 1902: ! 1903: ! 1904: LOCAL changetoreg(ap, i) ! 1905: register Addrp ap; ! 1906: int i; ! 1907: ! 1908: { ! 1909: ap->vstg = STGREG; ! 1910: ap->memno = regnum[i]; ! 1911: frexpr(ap->memoffset); ! 1912: ap->memoffset = ICON(0); ! 1913: #if FAMILY == PCC && SZSHORT < SZINT ! 1914: /* ! 1915: * Handle PCC bogosity that values in registers must be at least INT width. ! 1916: */ ! 1917: if (ap->vtype == TYSHORT) ! 1918: ap->vtype = TYINT; ! 1919: #endif ! 1920: ap->istemp = NO; ! 1921: return; ! 1922: } ! 1923: ! 1924: ! 1925: ! 1926: LOCAL insertassign(sp, dest, src) ! 1927: Slotp sp; ! 1928: Addrp dest; ! 1929: expptr src; ! 1930: ! 1931: { ! 1932: Slotp newslot; ! 1933: expptr p; ! 1934: ! 1935: p = mkexpr(OPASSIGN, dest, src); ! 1936: newslot = optinsert (SKEQ,p,0,0,sp); ! 1937: ! 1938: if (sp == dohead) ! 1939: if (!newcode) ! 1940: newcode = newslot; ! 1941: ! 1942: return; ! 1943: } ! 1944: ! 1945: ! 1946: LOCAL appendassign(sp, dest, src) ! 1947: Slotp sp; ! 1948: Addrp dest; ! 1949: expptr src; ! 1950: ! 1951: { ! 1952: Slotp newslot; ! 1953: expptr p; ! 1954: ! 1955: if (!sp) ! 1956: fatal ("regalloc:appendassign"); ! 1957: ! 1958: p = mkexpr(OPASSIGN, dest, src); ! 1959: newslot = optinsert (SKEQ,p,0,0,sp->next); ! 1960: ! 1961: return; ! 1962: } ! 1963: ! 1964: ! 1965: ! 1966: LOCAL int regtomem(sp) ! 1967: Slotp sp; ! 1968: ! 1969: { ! 1970: expptr p, l, r; ! 1971: int i; ! 1972: ! 1973: if (sp->type != SKEQ) return NO; ! 1974: ! 1975: p = sp->expr; ! 1976: if ((p->tag != TEXPR) || (p->exprblock.opcode != OPASSIGN)) ! 1977: return NO; ! 1978: ! 1979: r = p->exprblock.rightp; ! 1980: if ((r->tag != TADDR) || (r->addrblock.vstg != STGREG)) ! 1981: return NO; ! 1982: ! 1983: l = p->exprblock.leftp; ! 1984: if (l->tag != TADDR) ! 1985: return NO; ! 1986: i = r->addrblock.memno; ! 1987: if (regtab[i] && ! 1988: (l->addrblock.vstg == regtab[i]->vstg) && ! 1989: (l->addrblock.memno == regtab[i]->memno) && ! 1990: fixedaddress(l) && ! 1991: (l->addrblock.memoffset->constblock.constant.ci == regtab[i]->memoffset)) ! 1992: return YES; ! 1993: ! 1994: return NO; ! 1995: } ! 1996: ! 1997: ! 1998: ! 1999: LOCAL int regtoreg(sp) ! 2000: Slotp sp; ! 2001: ! 2002: { ! 2003: expptr p, l, r; ! 2004: ! 2005: if (sp->type != SKEQ) return NO; ! 2006: ! 2007: p = sp->expr; ! 2008: if ((p->tag != TEXPR) || (p->exprblock.opcode != OPASSIGN)) ! 2009: return NO; ! 2010: ! 2011: l = p->exprblock.leftp; ! 2012: if ((l->tag != TADDR) || (l->addrblock.vstg != STGREG)) ! 2013: return NO; ! 2014: ! 2015: r = p->exprblock.rightp; ! 2016: if ((r->tag == TADDR) && ! 2017: (r->addrblock.vstg == STGREG) && ! 2018: (r->addrblock.memno == l->addrblock.memno)) ! 2019: return YES; ! 2020: ! 2021: if ((r->tag == TEXPR) && ! 2022: (r->exprblock.opcode == OPADDR) && ! 2023: (r->exprblock.leftp->tag == TADDR) && ! 2024: (r->exprblock.leftp->addrblock.vstg == STGPREG) && ! 2025: (r->exprblock.leftp->addrblock.memno == l->addrblock.memno)) ! 2026: return YES; ! 2027: ! 2028: return NO; ! 2029: } ! 2030: ! 2031: ! 2032: ! 2033: LOCAL deleteslot(sp) ! 2034: Slotp sp; ! 2035: ! 2036: { ! 2037: if (newcode == sp) ! 2038: { ! 2039: newcode = sp->next; ! 2040: if (newcode == dohead) ! 2041: newcode = NULL; ! 2042: } ! 2043: ! 2044: delslot (sp); ! 2045: return; ! 2046: } ! 2047: ! 2048: ! 2049: ! 2050: LOCAL gensetall(sp) ! 2051: Slotp sp; ! 2052: ! 2053: { ! 2054: register int i; ! 2055: register REGDATA *rp; ! 2056: register Addrp ap; ! 2057: ! 2058: for (i = toplcv + 1; i <= topregvar; i++) ! 2059: if (rp = regtab[i]) ! 2060: if (rp->isset && !(rp->istemp || rp->isarrayarg)) ! 2061: if (!memdefined[i]) ! 2062: { ! 2063: ap = (Addrp) cpexpr(rp->stgp); ! 2064: changetoreg(ap, i); ! 2065: insertassign(sp, cpexpr(rp->stgp), ap); ! 2066: memdefined[i] = YES; ! 2067: } ! 2068: ! 2069: return; ! 2070: } ! 2071: ! 2072: ! 2073: LOCAL gensetcommon(sp) ! 2074: Slotp sp; ! 2075: ! 2076: { ! 2077: register int i; ! 2078: register REGDATA *rp; ! 2079: register Addrp ap; ! 2080: ! 2081: for (i = toplcv + 1; i <= topregvar; i++) ! 2082: if (rp = regtab[i]) ! 2083: if ((rp->vstg == STGCOMMON) && !rp->isarrayarg) ! 2084: if (!memdefined[i]) ! 2085: { ! 2086: ap = (Addrp) cpexpr(rp->stgp); ! 2087: changetoreg(ap, i); ! 2088: insertassign(sp, cpexpr(rp->stgp), ap); ! 2089: memdefined[i] = YES; ! 2090: } ! 2091: ! 2092: return; ! 2093: } ! 2094: ! 2095: ! 2096: LOCAL gensetreturn(sp) ! 2097: Slotp sp; ! 2098: ! 2099: { ! 2100: register int i; ! 2101: register REGDATA *rp; ! 2102: register Addrp ap; ! 2103: ! 2104: for (i = toplcv + 1; i <= topregvar; i++) ! 2105: if (rp = regtab[i]) ! 2106: if (((rp->vstg == STGCOMMON) && !rp->isarrayarg) ! 2107: || (rp->isset && (saveall || rp->stgp->issaved) && !(rp->istemp || rp->isarrayarg))) ! 2108: if (!memdefined[i]) ! 2109: { ! 2110: ap = (Addrp) cpexpr(rp->stgp); ! 2111: changetoreg(ap, i); ! 2112: insertassign(sp, cpexpr(rp->stgp), ap); ! 2113: memdefined[i] = YES; ! 2114: } ! 2115: ! 2116: return; ! 2117: } ! 2118: ! 2119: ! 2120: ! 2121: LOCAL clearmems() ! 2122: ! 2123: { ! 2124: REGDATA *rp; ! 2125: register int i; ! 2126: ! 2127: for (i = 0; i <= toplcv; i++) ! 2128: memdefined[i] = YES; ! 2129: for (; i <= topregvar; i++) ! 2130: if ((rp = regtab[i]) && rp->isset) ! 2131: memdefined[i] = NO; ! 2132: else ! 2133: memdefined[i] = YES; ! 2134: return; ! 2135: } ! 2136: ! 2137: ! 2138: LOCAL setregs() ! 2139: ! 2140: { ! 2141: register int i; ! 2142: ! 2143: for (i = 0; i <= topregvar; i++) ! 2144: regdefined[i] = YES; ! 2145: return; ! 2146: } ! 2147: ! 2148: ! 2149: ! 2150: regalloc() ! 2151: ! 2152: { ! 2153: int match; ! 2154: Slotp nextslot; ! 2155: Slotp sl1,sl2; ! 2156: Slotp lastlabslot; ! 2157: ! 2158: if (! optimflag) return; ! 2159: ! 2160: docount = 0; ! 2161: lastlabslot = NULL; ! 2162: for (sl1 = firstslot; sl1; sl1 = nextslot) ! 2163: { ! 2164: nextslot = sl1->next; ! 2165: switch (sl1->type) ! 2166: { ! 2167: ! 2168: /* temporarily commented out ----- ! 2169: case SKLABEL: ! 2170: lastlabslot = sl1; ! 2171: break; ! 2172: ! 2173: case SKGOTO: ! 2174: if (lastlabslot && sl1->label == lastlabslot->label) ! 2175: { ! 2176: dohead = lastlabslot; ! 2177: doend = sl1; ! 2178: alreg (); ! 2179: } ! 2180: break; ! 2181: ----- */ ! 2182: ! 2183: case SKDOHEAD: ! 2184: ++docount; ! 2185: pushq (sl1); ! 2186: break; ! 2187: ! 2188: case SKENDDO: ! 2189: --docount; ! 2190: match = 0; ! 2191: for (sl2 = sl1; sl2; sl2 = sl2->prev) ! 2192: { ! 2193: if (sl2->type == SKDOHEAD) match++; ! 2194: else if (sl2->type == SKENDDO) match--; ! 2195: if (match == 0) break; ! 2196: } ! 2197: if (sl2) ! 2198: dohead = sl2; ! 2199: else ! 2200: fatal ("unmatched enddo in code buffer"); ! 2201: if (sl2->type != SKDOHEAD) ! 2202: fatal ("internal error in regalloc"); ! 2203: ! 2204: for (dqptr = dqbottom; dqptr; dqptr = dqptr->up) ! 2205: { ! 2206: if (dqptr->dohead == dohead) ! 2207: break; ! 2208: } ! 2209: ! 2210: if (!dqptr) ! 2211: fatal ("garbled doqueue in regalloc"); ! 2212: ! 2213: /* sl1 now points to the SKENDDO slot; the SKNULL slot ! 2214: * is reached through sl1->nullslot ! 2215: */ ! 2216: dqptr->doend = (Slotp) sl1->nullslot; ! 2217: ! 2218: if (docount == 0) ! 2219: { ! 2220: for (dqptr = dqbottom; dqptr; dqptr = dqptr->up) ! 2221: { ! 2222: dohead = dqptr->dohead; ! 2223: doend = dqptr->doend; ! 2224: alreg(); ! 2225: } ! 2226: while (dqtop) ! 2227: popq (dqtop->dohead); ! 2228: docount = 0; ! 2229: freelabtab(); ! 2230: freevartab(); ! 2231: } ! 2232: break; ! 2233: ! 2234: default: ! 2235: break; ! 2236: } ! 2237: } ! 2238: ! 2239: return; ! 2240: } ! 2241: ! 2242: ! 2243: ! 2244: LOCAL pushq(sp) ! 2245: Slotp sp; ! 2246: ! 2247: { ! 2248: DOQUEUE *t; ! 2249: ! 2250: if (sp->type != SKDOHEAD) ! 2251: fatal("regalloc:pushq: DO statement expected"); ! 2252: ! 2253: if (dqbottom) ! 2254: { ! 2255: t = ALLOC(doqueue); ! 2256: t->up = dqbottom; ! 2257: dqbottom->down = t; ! 2258: dqbottom = t; ! 2259: } ! 2260: else ! 2261: dqtop = dqbottom = ALLOC(doqueue); ! 2262: ! 2263: dqbottom->dohead = sp; ! 2264: } ! 2265: ! 2266: ! 2267: LOCAL popq(sp) ! 2268: Slotp sp; ! 2269: ! 2270: { ! 2271: DOQUEUE *t; ! 2272: register int i; ! 2273: ! 2274: if (!dqtop) ! 2275: fatal("regalloc:popq: empty DO queue"); ! 2276: if (dqtop->dohead != sp) ! 2277: fatal("regalloc:popq: garbled DO queue"); ! 2278: ! 2279: t = dqtop; ! 2280: ! 2281: dqtop = t->down; ! 2282: if (dqtop) ! 2283: dqtop->up = NULL; ! 2284: else ! 2285: dqbottom = NULL; ! 2286: for (i = 0; i < MAXREGVAR; i++) ! 2287: if (t->reg[i]) ! 2288: free((char *) t->reg[i]); ! 2289: free(t); ! 2290: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.