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