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[] = "@(#)optloop.c	5.1 (Berkeley) 6/7/85";
   9: #endif not lint
  10: 
  11: /*
  12:  * optloop.c
  13:  *
  14:  * Loop optimizations, f77 compiler pass 1, 4.2 BSD.
  15:  *
  16:  * University of Utah CS Dept. modification history:
  17:  *
  18:  * $Log:	optloop.c,v $
  19:  * Revision 1.4  84/10/25  01:27:29  donn
  20:  * Fixed a subtle bug in removesafe().  When the moved code is an assignment
  21:  * into a temporary, we use the lhs to substitute for the expression inside
  22:  * the loop.  Previously the data structure for the temporary was not copied,
  23:  * so later on when the lhs was freed, the substitute was too, turning it
  24:  * into garbage.
  25:  *
  26:  * Revision 1.3  84/08/05  17:04:03  donn
  27:  * Changed worthcost() so that it skips variable length strings -- we can't
  28:  * make temporaries for these...
  29:  *
  30:  * Revision 1.2  84/07/19  11:50:39  donn
  31:  * Installed changes to force non-intrinsic subroutines and functions to define
  32:  * their arguments (make them ineligible for optimization), function setsuses.
  33:  * Fix from A.F.
  34:  *
  35:  */
  36: 
  37: #include "defs.h"
  38: #include "optim.h"
  39: 
  40: 
  41: #define SCFREE   0
  42: #define SCSAFE   1
  43: 
  44: 
  45: 
  46: typedef
  47:   struct varblock
  48:     {
  49:       struct varblock *next;
  50:       field vstg;
  51:       int memno;    /* holds memalloc for TTEMP */
  52:       short sets;
  53:       short uses;
  54:       field setfirst;
  55:     } VARBLOCK;
  56: 
  57: typedef VARBLOCK *Varp;
  58: 
  59: #define TABLESIZE 59
  60: 
  61: LOCAL Varp table[TABLESIZE];
  62: 
  63: 
  64: 
  65: LOCAL Varp mkbucket(vstg,memno)
  66: field vstg;
  67: int memno;
  68: 
  69: {
  70:   Varp q;
  71: 
  72:   q = ALLOC(varblock);
  73:   q->vstg = vstg;
  74:   q->memno = memno;
  75:   return q;
  76: }
  77: 
  78: 
  79: 
  80: LOCAL Varp lookup(p)
  81: tagptr p;
  82: 
  83: {
  84: int vstg, memno;
  85: int key;
  86: Varp q, r;
  87: 
  88: switch (p->tag)
  89:     {
  90:     case TTEMP:
  91:         vstg = 0;
  92:         memno = (int) p->tempblock.memalloc;
  93:         break;
  94: 
  95:     case TADDR:
  96:         vstg = p->addrblock.vstg;
  97:         memno = p->addrblock.memno;
  98:         break;
  99: 
 100:     default:
 101:         badtag ("lookup",p->tag);
 102:     }
 103: key = memno % TABLESIZE;
 104: q = table[key];
 105: 
 106: if (q)
 107:     {
 108:     for (; q; r = q, q = q->next)
 109:         if ((q->vstg == vstg) && (q->memno == memno))
 110:             return q;
 111:     return r->next = mkbucket(vstg,memno);
 112:     }
 113: else
 114:     return table[key] = mkbucket(vstg,memno);
 115: }
 116: 
 117: 
 118: 
 119: LOCAL freetable()
 120: 
 121: {
 122:   int i;
 123:   Varp p, q;
 124: 
 125:   for (i = 0; i < TABLESIZE; i++)
 126:     if (table[i])
 127:       {
 128:     p = table[i];
 129:     table[i] = NULL;
 130: 
 131:     while (p)
 132:       {
 133:         q = p->next;
 134:         free((char *) p);
 135:         p = q;
 136:       }
 137:       }
 138: }
 139: 
 140: 
 141: 
 142: Slotp newcode;
 143: Slotp dohead, doend;
 144: LOCAL Slotp first, last;
 145: LOCAL commonset;
 146: LOCAL int comocount;    /* count of number of code motions done */
 147: 
 148: 
 149: optloops()
 150: 
 151: {
 152: int match;
 153: Slotp   nextslot;
 154: Slotp   sl1,sl2;
 155: Slotp   lastlabslot;
 156: int lab;
 157: 
 158: if (! optimflag) return;
 159: if (debugflag[6]) return;
 160: 
 161: lastlabslot = NULL;
 162: comocount = 0;
 163: for (sl1 = firstslot; sl1; sl1 = nextslot)
 164:     {
 165:     nextslot = sl1->next;
 166:     switch (sl1->type)
 167:         {
 168:         case SKLABEL:
 169:         lastlabslot = sl1;
 170:         break;
 171: 
 172:         case SKGOTO:
 173:         if (lastlabslot && sl1->label == lastlabslot->label)
 174:             {
 175:             lab = newlabel ();
 176:             first = optinsert (SKLABEL,0,lab,0,lastlabslot->next);
 177:             last = sl1;
 178:             last->label = lab;
 179:             optloop ();
 180:             }
 181:         break;
 182: 
 183:         case SKDOHEAD:
 184:         match = 0;
 185:         for (sl2 = sl1; sl2; sl2 = sl2->next)
 186:             {
 187:             if (sl2->type == SKDOHEAD) match++;
 188:             else if (sl2->type == SKENDDO) match--;
 189:             if (match == 0) break;
 190:             }
 191:         if (sl2)
 192:             last = sl2;
 193:         else
 194:             fatal ("unmatched do in code buffer");
 195:         if (sl2->type != SKENDDO)
 196:             fatal ("internal error in optloops");
 197: 
 198:         /*  last now points to the SKENDDO slot; the SKNULL slot
 199: 		 *  is reached through last->nullslot
 200: 		 */
 201:         last = (Slotp) last->nullslot;
 202: 
 203:         first = sl1;
 204: 
 205:         optloop ();
 206:         break;
 207: 
 208:         default:
 209:         break;
 210:         }
 211:     }
 212: 
 213: if (debugflag[0])
 214:     fprintf (diagfile,"%d code motion%s performed\n",comocount,
 215:         (comocount==1 ? "" : "s") );
 216: return;
 217: }
 218: 
 219: 
 220: 
 221: optloop()
 222: 
 223: {
 224: newcode = NULL;
 225: 
 226: modify();
 227: 
 228: return;
 229: }
 230: 
 231: 
 232: LOCAL modify()
 233: 
 234: {
 235:   Slotp sp;
 236:   int s;
 237: 
 238:   scanvars();
 239: 
 240:   for (sp = first; sp != last->next; sp = sp->next)
 241:     switch (sp->type)
 242:       {
 243:       case SKEQ:
 244:     s = anex(sp->expr);
 245:     if (s == SCSAFE)
 246:       removesafe (&sp->expr);
 247:     break;
 248: 
 249:       case SKARIF:
 250:       case SKASGOTO:
 251:       case SKCALL:
 252:       case SKCMGOTO:
 253:       case SKIFN:
 254:       case SKSTOP:
 255:       case SKRETURN:
 256:       case SKPAUSE:
 257:       case SKIOIFN:
 258:     s = anex(sp->expr);
 259:     if (s == SCSAFE)
 260:       removesafe(&sp->expr);
 261:     break;
 262: 
 263:       default:
 264:     break;
 265:       }
 266: 
 267:   freetable();
 268:   return;
 269: }
 270: 
 271: 
 272: LOCAL scanvars()
 273: 
 274: {
 275:   Slotp sp;
 276:   Varp varinfo;
 277:   int i;
 278:   Varp p;
 279: 
 280:   commonset = NO;
 281: 
 282:   for (sp = first; sp != last->next; sp = sp->next)
 283:     {
 284:       switch (sp->type)
 285:     {
 286:     case SKARIF:
 287:     case SKASGOTO:
 288:     case SKCALL:
 289:     case SKCMGOTO:
 290:     case SKIFN:
 291:     case SKSTOP:
 292:     case SKRETURN:
 293:     case SKPAUSE:
 294:     case SKIOIFN:
 295:     case SKEQ:
 296:       setsuses(sp->expr);
 297:       break;
 298: 
 299:     default:
 300:       break;
 301:     }
 302:     }
 303: 
 304:   if (commonset)
 305:     for (i = 0; i < TABLESIZE; i++)
 306:       for (p = table[i]; p; p = p->next)
 307:     if (p->vstg == STGCOMMON)
 308:       {
 309:         p->sets++;
 310:         p->setfirst = NO;
 311:       }
 312: }
 313: 
 314: 
 315: LOCAL setsuses(p)
 316: expptr p;
 317: 
 318: {
 319:   Addrp lhs;
 320:   Varp varinfo;
 321:   chainp args;
 322: 
 323:   if (!p) return;
 324: 
 325:   switch (p->tag)
 326:     {
 327:     case TEXPR:
 328:       switch (p->exprblock.opcode)
 329:     {
 330:     default:
 331:       setsuses(p->exprblock.leftp);
 332:       setsuses(p->exprblock.rightp);
 333:       setsuses(p->exprblock.vleng);
 334:       break;
 335: 
 336:     case OPASSIGN:
 337:       switch (p->exprblock.leftp->tag)
 338:         {
 339:         case TTEMP:
 340:           lhs = (Addrp) p->exprblock.leftp;
 341:           goto taddr;
 342: 
 343:         case TADDR:
 344:           lhs = (Addrp) p->exprblock.leftp;
 345:           setsuses(lhs->memoffset);
 346:           setsuses(lhs->vleng);
 347:         taddr:
 348:           setsuses(p->exprblock.rightp);
 349:           setsuses(p->exprblock.vleng);
 350:           varinfo = lookup(lhs);
 351:           varinfo->sets++;
 352:               if (varinfo->uses == 0)
 353:             varinfo->setfirst = YES;
 354:           break;
 355: 
 356:         default:
 357:           fatal("O6:  l-value expected");
 358:         }
 359:       break;
 360: 
 361:     case OPSTAREQ:
 362:     case OPPLUSEQ:
 363:       switch (p->exprblock.leftp->tag)
 364:         {
 365:         case TADDR:
 366:           lhs = (Addrp) p->exprblock.leftp;
 367:           break;
 368:         case TTEMP:
 369:           lhs = (Addrp) p->exprblock.leftp;
 370:           break;
 371:         default:
 372:           fatal("O7:  l-value expected");
 373:         }
 374:       setsuses(p->exprblock.leftp);
 375:       setsuses(p->exprblock.rightp);
 376:       setsuses(p->exprblock.vleng);
 377:       varinfo = lookup(lhs);
 378:       varinfo->sets++;
 379:       break;
 380: 
 381:     case OPCALL:
 382:       if (p->exprblock.leftp->tag != TADDR)
 383:         fatal("O8:  subprogram expected");
 384:       setsuses(p->exprblock.rightp);
 385:       setsuses(p->exprblock.vleng);
 386:       if (p->exprblock.leftp->addrblock.vstg == STGINTR) break;
 387:       commonset = YES;
 388:       if (p->exprblock.rightp == NULL) break;
 389:       args = p->exprblock.rightp->listblock.listp;
 390:       for (; args; args = args->nextp)
 391:         if (args->datap->tag == TADDR)
 392:           {
 393:         lhs = (Addrp) args->datap;
 394:         switch (lhs->vstg)
 395:           {
 396:           case STGARG:
 397:           case STGAUTO:
 398:           case STGBSS:
 399:           case STGINIT:
 400:           case STGCOMMON:
 401:           case STGEQUIV:
 402:           case STGREG:
 403:           case STGPREG:
 404:             varinfo = lookup(lhs);
 405:             varinfo->sets++;
 406:           }
 407:           }
 408:         else if (args->datap->tag == TTEMP)
 409:           {
 410:         lhs = (Addrp) args->datap;
 411:         varinfo = lookup (lhs);
 412:         varinfo->sets++;
 413:           }
 414:       break;
 415:         }
 416: 
 417:       return;
 418: 
 419:     case TTEMP:
 420:       varinfo = lookup((Addrp) p);
 421:       varinfo->uses++;
 422:       return;
 423: 
 424:     case TADDR:
 425:       setsuses(p->addrblock.memoffset);
 426:       setsuses(p->addrblock.vleng);
 427:       varinfo = lookup((Addrp) p);
 428:       varinfo->uses++;
 429:       return;
 430: 
 431:     case TLIST:
 432:       for (args = p->listblock.listp; args; args = args->nextp)
 433:     setsuses(args->datap);
 434: 
 435:     case TCONST:
 436:     case TERROR:
 437:       return;
 438: 
 439:     default:
 440:       fatal("O9:  bad tag value");
 441:     }
 442: }
 443: 
 444: 
 445: LOCAL int anex(p)
 446: expptr p;
 447: 
 448: {
 449:   int s1, s2, s3;
 450:   expptr q;
 451:   Varp varinfo;
 452:   chainp ch;
 453:   int setfirst;
 454:   expptr expr;
 455: 
 456: 
 457:   if (p == ENULL)
 458:     return SCSAFE;
 459: 
 460:   switch (p->tag)
 461:     {
 462:     case TCONST:
 463:       return SCSAFE;
 464: 
 465:     case TLIST:
 466:       for (ch = p->listblock.listp; ch; ch = ch->nextp)
 467:     {
 468:       s1 = anex (ch->datap);
 469:       if (s1 == SCSAFE)
 470:         removesafe (&ch->datap);
 471:     }
 472:       return SCFREE;
 473: 
 474:     case TEXPR:
 475:       s1 = anex(p->exprblock.leftp);
 476:       s2 = anex(p->exprblock.rightp);
 477:       s3 = anex(p->exprblock.vleng);
 478: 
 479:       switch (p->exprblock.opcode)
 480:     {
 481:     case OPASSIGN:
 482:       expr = p->exprblock.leftp;
 483:       varinfo = lookup(expr);
 484:       setfirst = varinfo->setfirst && (varinfo->sets == 1);
 485:       if (expr->tag == TTEMP && setfirst &&
 486:         s2 == SCSAFE && s3 == SCSAFE)
 487:         {
 488:           movefrtemp (expr);
 489:           return SCSAFE;
 490:         }
 491:       else
 492:         {
 493:           if (s2 == SCSAFE) removesafe (&p->exprblock.rightp);
 494:           if (s3 == SCSAFE) removesafe (&p->exprblock.vleng);
 495:           return SCFREE;
 496:         }
 497: 
 498:     case OPNEG:
 499:     case OPNOT:
 500:     case OPABS:
 501:     case OPADDR:
 502:     case OPBITNOT:
 503:       if ((s2 == SCSAFE) && (s3 == SCSAFE))
 504:         return s1;
 505:       else
 506:         return SCFREE;
 507: 
 508:     case OPCONV:
 509:       if ((s2 != SCSAFE) || (s3 != SCSAFE))
 510:         return SCFREE;
 511: 
 512:       if (ISINT(p->exprblock.vtype))
 513:         return s1;
 514:       if (ISINT(p->exprblock.leftp->headblock.vtype))
 515:         return s1;
 516: 
 517:       return SCFREE;
 518: 
 519: 
 520:     case OPSTAR:
 521:       if (ISINT(p->exprblock.vtype))
 522:         goto safeop;
 523: 
 524:       if (safefactor(p->exprblock.leftp) ||
 525:           safefactor(p->exprblock.rightp))
 526:         goto safeop;
 527: 
 528:       goto floatop;
 529: 
 530: 
 531:     case OPPLUS:
 532:     case OPMINUS:
 533:       if (ISINT(p->exprblock.vtype))
 534:         goto safeop;
 535: 
 536:     floatop:
 537:       if (!(ISREAL(p->exprblock.vtype) || ISCOMPLEX(p->exprblock.vtype)))
 538:         return SCFREE;
 539: 
 540:       switch (s1)
 541:         {
 542:         case SCSAFE:
 543:           removesafe(&p->exprblock.leftp);
 544:           if (s2 == SCSAFE)
 545:         removesafe(&p->exprblock.leftp);
 546:           return SCFREE;
 547: 
 548:         case SCFREE:
 549:           if (s2 == SCSAFE)
 550:         removesafe(&p->exprblock.rightp);
 551:           return SCFREE;
 552:         }
 553: 
 554:     case OPOR:
 555:     case OPAND:
 556:     case OPEQV:
 557:     case OPNEQV:
 558:     case OPLT:
 559:     case OPEQ:
 560:     case OPGT:
 561:     case OPLE:
 562:     case OPNE:
 563:     case OPGE:
 564:     case OPLSHIFT:
 565:     case OPMIN:
 566:     case OPMAX:
 567:     case OPBITOR:
 568:     case OPBITAND:
 569:     case OPBITXOR:
 570:     case OPRSHIFT:
 571:     safeop:
 572:       if ((p->exprblock.vleng != ENULL) && ( ! ISCONST(p->exprblock.vleng)))
 573:         return SCFREE;
 574: 
 575:       switch (s1)
 576:         {
 577:         case SCSAFE:
 578:         if (s2 == SCFREE) removesafe (&p->exprblock.leftp);
 579:         return s2;
 580: 
 581:         case SCFREE:
 582:         if (s2 == SCSAFE) removesafe (&p->exprblock.rightp);
 583:         return SCFREE;
 584:         }
 585: 
 586:     default:
 587:       if (s1 == SCSAFE) removesafe(&p->exprblock.leftp);
 588:       if (s2 == SCSAFE) removesafe(&p->exprblock.rightp);
 589:       if (s3 == SCSAFE) removesafe(&p->exprblock.vleng);
 590:       return SCFREE;
 591:     }
 592: 
 593: 
 594:     case TTEMP:
 595:       varinfo = lookup(p);
 596:       if (varinfo->sets == 0)
 597:     return SCSAFE;
 598:       else
 599:     return SCFREE;
 600: 
 601:     case TADDR:
 602:       s1 = anex(p->addrblock.memoffset);
 603:       s2 = anex(p->addrblock.vleng);
 604: 
 605:       varinfo = lookup(p);
 606: 
 607:       if (varinfo->sets == 0)
 608:     switch (s1)
 609:       {
 610:       case SCSAFE:
 611:         if (s2 == SCFREE) removesafe(&p->addrblock.memoffset);
 612:         return s2;
 613: 
 614:       case SCFREE:
 615:         if (s2 == SCSAFE) removesafe(&p->addrblock.vleng);
 616:         return SCFREE;
 617:       }
 618: 
 619:       if (s1 == SCSAFE) removesafe(&p->addrblock.memoffset);
 620:       if (s2 == SCSAFE) removesafe(&p->addrblock.vleng);
 621:       return SCFREE;
 622: 
 623: 
 624:     default:
 625:       return SCFREE;
 626:     }
 627: }
 628: 
 629: 
 630: LOCAL safefactor(p)
 631: expptr p;
 632: 
 633: {
 634:   if ( ! ISCONST(p))
 635:     return NO;
 636: 
 637:   if (ISINT(p->constblock.vtype))
 638:     if (abs(p->constblock.const.ci) <= 1)
 639:       return YES;
 640: 
 641:   if (ISREAL(p->constblock.vtype))
 642:     if (abs(p->constblock.const.cd[0]) <= 1.0)
 643:       return YES;
 644: 
 645:   return NO;
 646: }
 647: 
 648: 
 649: LOCAL int worthcost(p)
 650: expptr p;
 651: 
 652: {
 653:   int cost;
 654:   chainp q;
 655:   expptr memoffset,vleng;
 656: 
 657:   if (p == ENULL)
 658:     return NO;
 659: 
 660:   switch (p->tag)
 661:     {
 662:     case TCONST:
 663:       return NO;
 664: 
 665:     case TTEMP:
 666:       return NO;
 667: 
 668:     case TADDR:
 669:       if ((vleng = p->addrblock.vleng) && ! ISCONST(vleng))
 670:     return NO;  /* Can't make variable length temporaries */
 671:       if ((memoffset = p->addrblock.memoffset) && ! ISCONST(memoffset))
 672:     return YES;
 673:       else
 674:     return NO;
 675: 
 676:     case TEXPR:
 677:       return YES;
 678: 
 679:     case TLIST:
 680:       cost = 0;
 681:       for (q = p->listblock.listp; q; q = q->nextp)
 682:     {
 683:     if (worthcost ((expptr) q->datap))
 684:       return YES;
 685:     cost++;
 686:     }
 687:       return (cost>2 ? YES : NO);
 688: 
 689:     default:
 690:       return NO;
 691:     }
 692: }
 693: 
 694: 
 695: LOCAL removesafe(refexpr)
 696: expptr *refexpr;
 697: 
 698: {
 699:   expptr ep;
 700:   Tempp ap;
 701:   Slotp newslot;
 702: 
 703:   extern Addrp gettemp();
 704: 
 705:   ep = *refexpr;
 706:   if (! worthcost(ep))
 707:     return;
 708: 
 709:   if (ep->tag == TEXPR && ep->exprblock.opcode == OPASSIGN)
 710:     {
 711:       if (ep->exprblock.leftp->tag != TTEMP)
 712:     fatal ("non-TEMP in assignment to be moved in optloop");
 713: 
 714:       newslot = optinsert (SKEQ, ep, 0, 0, first);
 715:       *refexpr = (expptr) cpexpr (ep->exprblock.leftp);
 716:     }
 717:   else
 718:     {
 719:       ap = (Tempp) gettemp(ep);
 720:       newslot = optinsert (SKEQ, mkexpr(OPASSIGN,cpexpr(ap),ep), 0, 0, first);
 721:       *refexpr = (expptr) ap;
 722:       optinsert (SKFRTEMP,ap->memalloc,0,0,last->next);
 723:     }
 724: 
 725:   comocount++;
 726:   if (!newcode)
 727:     newcode = newslot;
 728: 
 729:   return;
 730: }
 731: 
 732: 
 733: LOCAL Addrp gettemp(p)
 734: expptr p;
 735: 
 736: {
 737:   return mktemp(p->headblock.vtype, p->headblock.vleng);
 738: }
 739: 
 740: 
 741: 
 742: LOCAL movefrtemp (expr)
 743: Tempp   expr;
 744: 
 745: {
 746:   Slotp s;
 747: 
 748:   if (expr->tag != TTEMP)
 749:     badtag ("movefrtemp",expr->tag);
 750: 
 751:   for (s = first; s; s = s->next)
 752:     if (s->type == SKFRTEMP && s->expr == (expptr) expr->memalloc)
 753:       {
 754:     removeslot (s);
 755:     insertslot (s,last->next);
 756:     return;
 757:       }
 758: }

Defined functions

anex defined in line 445; used 8 times
freetable defined in line 119; used 1 times
gettemp defined in line 733; used 2 times
lookup defined in line 80; used 9 times
mkbucket defined in line 65; used 2 times
modify defined in line 232; used 1 times
movefrtemp defined in line 742; used 1 times
optloop defined in line 221; used 2 times
optloops defined in line 149; used 1 times
removesafe defined in line 695; used 17 times
safefactor defined in line 630; used 2 times
scanvars defined in line 272; used 1 times
setsuses defined in line 315; used 16 times
worthcost defined in line 649; used 2 times

Defined variables

comocount defined in line 146; used 4 times
doend defined in line 143; never used
dohead defined in line 143; never used
first defined in line 144; used 7 times
last defined in line 144; used 9 times
newcode defined in line 142; used 3 times
sccsid defined in line 8; never used
table defined in line 61; used 6 times

Defined struct's

varblock defined in line 47; used 2 times
  • in line 49(2)

Defined typedef's

VARBLOCK defined in line 55; used 1 times
  • in line 57
Varp defined in line 57; used 10 times

Defined macros

SCFREE defined in line 41; used 17 times
SCSAFE defined in line 42; used 24 times
TABLESIZE defined in line 59; used 4 times
Last modified: 1985-06-08
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2752
Valid CSS Valid XHTML 1.0 Strict