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.5 (Berkeley) 4/27/86";
   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.const.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.const.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.const.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.const.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.const.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.const.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.const.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: }

Defined functions

alreg defined in line 546; used 1 times
appendassign defined in line 1946; used 2 times
changetoreg defined in line 1904; used 15 times
clearmems defined in line 2121; used 3 times
clearsets defined in line 526; used 1 times
countrefs defined in line 1320; used 26 times
deleteslot defined in line 2033; used 2 times
entableaddr defined in line 1778; used 1 times
entablevar defined in line 1831; used 1 times
fixedaddress defined in line 1309; used 12 times
freelabtab defined in line 287; used 1 times
freevartab defined in line 439; used 1 times
gensetall defined in line 2050; used 5 times
gensetcommon defined in line 2073; used 1 times
gensetreturn defined in line 2096; used 1 times
getaddr defined in line 310; used 4 times
getvar defined in line 356; used 4 times
inregtab defined in line 1882; used 1 times
insertassign defined in line 1926; used 11 times
insertlabel defined in line 252; used 1 times
insertset defined in line 483; used 4 times
insetlist defined in line 508; used 5 times
invartable defined in line 417; used 1 times
locallabel defined in line 271; used 12 times
lookupaddr defined in line 383; used 6 times
lookupvar defined in line 401; used 2 times
popq defined in line 2267; used 1 times
pushq defined in line 2244; used 1 times
regalloc defined in line 2150; used 1 times
regtomem defined in line 1966; used 1 times
regtoreg defined in line 1999; used 1 times
regwrite defined in line 1490; used 24 times
samevar defined in line 1762; used 3 times
scanassign defined in line 1176; used 1 times
scancall defined in line 1255; used 1 times
scanopeq defined in line 1214; used 1 times
scanvars defined in line 1101; used 19 times
setall defined in line 1740; used 5 times
setcommon defined in line 1719; used 1 times
setregs defined in line 2138; used 2 times
varloopset defined in line 469; used 1 times

Defined variables

allset defined in line 236; used 4 times
commonunusable defined in line 245; used 4 times
commonvars defined in line 232; used 4 times
currentaddr defined in line 237; used 5 times
docount defined in line 243; used 28 times
doend defined in line 225; used 6 times
dohead defined in line 224; used 20 times
dqbottom defined in line 221; used 9 times
dqptr defined in line 221; used 17 times
dqtop defined in line 221; used 9 times
globalbranch defined in line 244; used 16 times
labeltable defined in line 230; used 9 times
linearcode defined in line 242; used 11 times
loopcost defined in line 238; used 5 times
memdefined defined in line 247; used 20 times
newcode defined in line 226; used 7 times
regaltered defined in line 248; used 3 times
regdefined defined in line 246; used 10 times
regtab defined in line 239; used 36 times
rt defined in line 240; used 42 times
sccsid defined in line 8; never used
setlist defined in line 233; used 5 times
tabletop defined in line 241; used 24 times
toplcv defined in line 235; used 26 times
topregvar defined in line 234; used 35 times
vartable defined in line 231; used 11 times

Defined struct's

addrnode defined in line 184; used 4 times
doqueue defined in line 213; used 2 times
  • in line 215(2)
labelnode defined in line 161; used 2 times
  • in line 163(2)
regdata defined in line 145; never used
setnode defined in line 203; used 2 times
  • in line 205(2)
varnode defined in line 170; used 2 times
  • in line 172(2)

Defined typedef's

ADDRNODE defined in line 199; used 24 times
DOQUEUE defined in line 219; used 4 times
LABELNODE defined in line 165; used 4 times
REGDATA defined in line 157; used 11 times
SETNODE defined in line 209; used 5 times
VARNODE defined in line 180; used 20 times

Defined macros

ISREGTYPE defined in line 134; used 5 times
ISVAR defined in line 139; used 9 times
LABTABSIZE defined in line 124; used 4 times
LM defined in line 644; used 2 times
LP defined in line 646; used 2 times
LZ defined in line 645; used 2 times
MSKREGTYPES defined in line 131; used 1 times
MSKVARS defined in line 136; used 1 times
TABLELIMIT defined in line 126; used 5 times
VARTABSIZE defined in line 125; used 8 times
Last modified: 1986-04-27
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 7033
Valid CSS Valid XHTML 1.0 Strict