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[] = "@(#)optcse.c	5.1 (Berkeley) 6/7/85";
   9: #endif not lint
  10: 
  11: /*
  12:  * optcse.c
  13:  *
  14:  * Common subexpression elimination routines, F77 compiler pass 1.
  15:  *
  16:  * University of Utah CS Dept modification history:
  17:  *
  18:  * $Log:	optcse.c,v $
  19:  * Revision 2.4  84/10/29  04:40:48  donn
  20:  * Problem with conversions -- two expressions headed by a conversion may be
  21:  * identical in structure but different in type, thus type must be checked in
  22:  * findnode().  This was causing a subscript to become REAL*8 type...
  23:  *
  24:  * Revision 2.3  84/08/04  20:38:53  donn
  25:  * Added fix from Jerry Berkman for an earlier fix from Alastair Fyfe --
  26:  * samebase() should treat EQUIVALENCEd variables just as daintily as
  27:  * COMMON variables.
  28:  *
  29:  * Revision 2.2  84/08/01  16:04:33  donn
  30:  * Changed rmcommaop so that it does subscripts too.
  31:  *
  32:  * Revision 2.1  84/07/19  12:03:44  donn
  33:  * Changed comment headers for UofU.
  34:  *
  35:  * Revision 1.5  84/07/09  14:43:05  donn
  36:  * Added changes to make OPPLUSEQ and OPSTAREQ expressions ineligible for
  37:  * CSE, since I can't think of a simple way to handle them and they are broken
  38:  * in the previous version, where they were treated like OPASSIGN -- this
  39:  * fails because CSE would think that the value of the lhs and rhs were equal.
  40:  *
  41:  * Revision 1.4  84/06/08  11:43:35  donn
  42:  * Yet another way of handling the bug with COMMON -- this one is from Alastair
  43:  * Fyfe at Sun.  I backed out the old fix.
  44:  *
  45:  * Revision 1.3  84/03/07  19:25:14  donn
  46:  * Changed method of handling COMMON bug -- COMMON variables are now treated
  47:  * like array elements and hence are ineligible for CSE.
  48:  *
  49:  * Revision 1.2  84/02/26  03:30:47  donn
  50:  * Fixed bug in evaluation graph construction that caused two variables in
  51:  * common to be considered identical if they were merely in the same common,
  52:  * rather than in the same common at the same offset.
  53:  *
  54:  */
  55: 
  56: #include "defs.h"
  57: #include "optim.h"
  58: 
  59: #define FALSE   0
  60: #define TRUE    1
  61: 
  62: LOCAL Bblockp   current_BB;
  63: LOCAL int   cse1count;  /* count of number of cse uses eliminated */
  64: LOCAL int   cse2count;  /* count of number of cse def's eliminated */
  65: 
  66: 
  67: 
  68: 
  69: LOCAL dumpstacks()
  70: {
  71:     duplptr dl;
  72:     valuen p;
  73:     idlptr idl;
  74:     idptr idp;
  75:     nodelptr nl;
  76:     int i;
  77: 
  78:     fprintf(diagfile,"\n *** IDblocks ***\n");
  79:     for(idp=current_BB->headid;idp;idp=idp->next)
  80:     {
  81:         fprintf(diagfile,
  82:             "idp= %d idaddr= %d initval= %d assgnval= %d \n",
  83:             idp, idp->idaddr, idp->initval, idp->assgnval);
  84:         fprintf(diagfile,"nodes: ");
  85:         i=0;
  86:         for (nl=idp->headnodelist;nl;nl=nl->next) {
  87:             if(++i>20){
  88:                 fprintf(diagfile,"\n");
  89:                 i=0;
  90:             }
  91:             fprintf(diagfile," %d ",nl->nodep);
  92:         }
  93:         fprintf(diagfile,"\n");
  94:     }
  95: 
  96:     fprintf(diagfile,"\n *** VALUE NODES *** \n");
  97:     for(p=current_BB->headnode;p;p=p->next) {
  98:         fprintf(diagfile,
  99:            "\np= %d opp= %d lc= %d rc= %d rs= %d is_dead= %d n_dups %d",
 100:            p, p->opp,p->lc,p->rc, p->rs, p->is_dead, p->n_dups);
 101:         if (p->rs){
 102:             fprintf(diagfile,"tag= %d ",p->opp->tag);
 103:             if(p->opp->tag==TEXPR)
 104:                 fprintf(diagfile,"opco= %d ",
 105:                     p->opp->exprblock.opcode);
 106:         }
 107:         fprintf(diagfile,"\n");
 108:         fprintf(diagfile,"parent= %d dups:  ",p->parent);
 109:         i=0;
 110:         for(dl=p->headduplist;dl;dl=dl->next) {
 111:             if(++i>20){
 112:                 fprintf(diagfile,"\n");
 113:                 i=0;
 114:             }
 115:             fprintf(diagfile," %d ",dl->parent);
 116:         }
 117: 
 118:         fprintf(diagfile,"\ndeps IDs");
 119:         i=0;
 120:         for(idl=p->headdeplist;idl;idl=idl->next) {
 121:             if(++i>20){
 122:                 fprintf(diagfile,"\n");
 123:                 i=0;
 124:             }
 125:             fprintf(diagfile," %d ",idl->idp);
 126:         }
 127:     }
 128: }
 129: 
 130: 
 131: 
 132: LOCAL idlptr mergedeps(lnode,rnode)
 133: valuen lnode,rnode;
 134: /* Given two value nodes, merge the lists of identifiers on which they
 135: ** depend to produce a new list incorporating both dependencies. Lists
 136: ** are assumed to be ordered by increasing idp address. No duplicate identifiers
 137: ** are generated in the output list.
 138: */
 139: {
 140:     register idlptr lp,lp1,lp2;
 141:     idlptr head;
 142: 
 143:     lp = lp1 = lp2 = head = NULL;
 144:     if(lnode) lp1 = lnode->headdeplist;
 145:     if(rnode) lp2 = rnode->headdeplist;
 146: 
 147:     while (lp1 || lp2) {
 148:         if (lp) {
 149:             lp->next = ALLOC(IDlist);
 150:             lp = lp->next;
 151:         }
 152:         else lp = head = ALLOC(IDlist);
 153:         lp->next = 0;
 154:         if (lp1 == 0) {
 155:             lp->idp = lp2->idp;
 156:             lp2 = lp2->next;
 157:         }
 158:         else if (lp2 == 0) {
 159:             lp->idp = lp1->idp;
 160:             lp1 = lp1->next;
 161:         }
 162:         else if (lp1->idp < lp2->idp) {
 163:             lp->idp = lp1->idp;
 164:             lp1 = lp1->next;
 165:         }
 166:         else if (lp1->idp > lp2->idp) {
 167:             lp->idp = lp2->idp;
 168:             lp2 = lp2->next;
 169:         }
 170:         else {
 171:             lp->idp = lp1->idp;
 172:             lp1 = lp1->next;
 173:             lp2 = lp2->next;
 174:         }
 175:     }
 176:     return(head);
 177: }
 178: 
 179: 
 180: 
 181: LOCAL removenode(nodep)
 182: valuen nodep;
 183: /*  Removes a value node from every IDblock on the node's list of identifiers.
 184: */
 185: {
 186:     register idlptr idl;
 187:     register nodelptr nl;
 188:     register nodelptr *addrnl;
 189: 
 190:     if(nodep == NULL) return ;
 191: 
 192:     /* loop through all identifiers */
 193:     for(idl=nodep->headdeplist;idl;idl=idl->next)
 194:     {
 195:         addrnl = &(idl->idp->headnodelist);
 196:         /* for each identifier loop through all nodes until match is found */
 197:         for(nl = *addrnl; nl; nl = *addrnl)
 198:         {
 199:             if(nl->nodep == nodep) {
 200:                 *addrnl = nl->next;
 201:                 free ( (charptr) nl );
 202:                 break;
 203:             }
 204:             addrnl = &nl->next;
 205:         }
 206:     }
 207:     nodep->is_dead = TRUE;
 208: }
 209: 
 210: 
 211: 
 212: LOCAL killid(idp)
 213: idptr idp;
 214: /* Kill all nodes on one identifier's list of dependent nodes, i.e. remove
 215: ** all calculations that depend on this identifier from the available
 216: ** values stack.  Free the list of records pointing at the dependent nodes.
 217: */
 218: {
 219:     nodelptr nl1,nl2;
 220: 
 221:     for (nl1 = idp->headnodelist; nl1; nl1=nl2)
 222:     {
 223:         nl2 = nl1->next;
 224:         removenode(nl1->nodep);
 225:     }
 226:     /* the above call frees the node list record pointed at by nl1 since it frees
 227: 	** all the node list records that reference the value node being killed
 228: 	*/
 229:     idp->headnodelist = NULL;
 230: 
 231: }
 232: 
 233: 
 234: 
 235: LOCAL killdepnodes(idp)
 236: idptr idp;
 237: /* Kill all value nodes that represent calculations which depend on
 238: ** this identifier. If the identifier is in COMMON or EQUIVALENCE storage,
 239: ** kill all values that depend on identifiers in COMMON or EQUIVALENCE
 240: */
 241: {
 242:     int thismemno;
 243: 
 244:     if(idp->idaddr->addrblock.vstg == STGCOMMON)
 245:     {
 246:         for(idp=current_BB->headid;idp;idp=idp->next)
 247:             if(idp->idaddr->addrblock.vstg == STGCOMMON)
 248:                 killid(idp);
 249:     }
 250:     else if(idp->idaddr->addrblock.vstg == STGEQUIV)
 251:     {
 252:         thismemno=idp->idaddr->addrblock.memno;
 253:         for(idp=current_BB->headid;idp;idp=idp->next)
 254:             if(idp->idaddr->addrblock.vstg == STGEQUIV
 255:                 && idp->idaddr->addrblock.memno == thismemno)
 256:                 killid(idp);
 257:     }
 258:     else killid(idp);
 259: 
 260: }
 261: 
 262: 
 263: 
 264: LOCAL appendnode(nodep)
 265: valuen nodep;
 266: /* Append a value node to all the IDblocks on that node's list of
 267: ** dependent identifiers i.e., since this computation depends on
 268: ** all the identifiers on its list then each of those identifiers should
 269: ** include this node in their list of dependent nodes.
 270: */
 271: {
 272:     register idlptr idl;
 273:     register nodelptr nl;
 274: 
 275:     for(idl=nodep->headdeplist;idl;idl=idl->next)
 276:         if(idl->idp->idaddr->tag == TADDR ||
 277:            idl->idp->idaddr->tag == TTEMP)
 278:             {
 279:             nl=ALLOC(NODElist);
 280:             nl->nodep = nodep;
 281:             nl->next = idl->idp->headnodelist;
 282:             idl->idp->headnodelist = nl;
 283:             }
 284: }
 285: 
 286: 
 287: 
 288: LOCAL idlptr addadep(idp,nodep)
 289: idptr idp;
 290: valuen nodep;
 291: /* Add an identifier to the dependents list of a value node.  Dependents
 292: ** lists are ordered by increasing idp value
 293: */
 294: {
 295:     register idlptr lp1,lp2;
 296: 
 297:     lp2 = ALLOC(IDlist);
 298:     lp2->idp = idp;
 299:     if(nodep->headdeplist == 0) {
 300:         lp2->next = 0;
 301:         nodep->headdeplist = lp2;
 302:     }
 303:     else if(idp <= nodep->headdeplist->idp) {
 304:         lp2->next = nodep->headdeplist;
 305:         nodep->headdeplist = lp2;
 306:     }
 307:     else for(lp1 = nodep->headdeplist; lp1; lp1 = lp1->next)
 308:         if( (lp1->next == 0) || (idp <= lp1->next->idp) )
 309:         {
 310:             lp2->next = lp1->next;
 311:             lp1->next = lp2;
 312:             break;
 313:         }
 314:     return(lp2);
 315: }
 316: 
 317: 
 318: 
 319: LOCAL valuen newnode(expr,left,right,rslt)
 320: expptr expr;
 321: valuen left,right,rslt;
 322: /* Build a new value node
 323: */
 324: {
 325:     register valuen p;
 326: 
 327:     p= ALLOC(VALUEnode);
 328:     p->opp = expr ;
 329:     p->parent = NULL ;
 330:     p->lc = left;
 331:     p->rc = right;
 332:     p->rs = rslt;
 333:     p->n_dups = 0;
 334:     p->is_dead = FALSE;
 335:     p->next=NULL;
 336:     p->headdeplist = mergedeps(left,right);
 337:     p->headduplist=NULL;
 338:     if(current_BB->headnode == 0) current_BB->headnode=p;
 339:     else if(current_BB->tailnode) current_BB->tailnode->next=p;
 340:     current_BB->tailnode=p;
 341: 
 342:     return(p);
 343: }
 344: 
 345: 
 346: 
 347: LOCAL newid(idaddr,addrof_idptr)
 348: expptr idaddr;
 349: idptr *addrof_idptr;
 350: /* Build a new IDblock and hook it on the current BB's ID list
 351: */
 352: {
 353:     register idptr p;
 354: 
 355:     p= ALLOC(IDblock);
 356: 
 357: /* build a leaf value node for the identifier and put the ID on the leaf node's
 358: ** list of dependent identifiers
 359: */
 360:     p->initval =  newnode(idaddr,NULL,NULL,NULL);
 361:     p->initval->rs = p->initval;
 362:     addadep(p,p->initval);
 363: 
 364:     p->idaddr = idaddr;
 365:     *addrof_idptr = p;
 366:     p->headnodelist=NULL;
 367:     p->next=NULL;
 368: 
 369: }
 370: 
 371: 
 372: 
 373: LOCAL addadup(parent,nodep)
 374: expptr *parent;
 375: valuen nodep;
 376: 
 377: /* A subtree has been found that duplicates the calculation represented
 378: ** by the value node referenced by nodep : add the root of the reduntant
 379: ** tree to the value node's list of duplicates.
 380: */
 381: 
 382: {
 383:     register duplptr dp;
 384:     valuen child;
 385: 
 386:     dp = ALLOC(DUPlist);
 387:     dp->parent = parent;
 388:     dp->next = nodep->headduplist;
 389:     nodep->headduplist = dp;
 390:     ++nodep->n_dups;
 391: 
 392: /* Check whether either of nodep's children is also a duplicate calculation
 393: ** and if so peel off it's most recent dup record
 394: */
 395: 
 396:     if ( (child = nodep->lc) && (child->n_dups) )
 397:     {
 398:         dp = child->headduplist;
 399:         child->headduplist = dp->next;
 400:         free ( (charptr) dp );
 401:         --child->n_dups;
 402:     }
 403:     if ( (child = nodep->rc) && (child->n_dups) )
 404:     {
 405:         dp = child->headduplist;
 406:         child->headduplist = dp->next;
 407:         free ( (charptr) dp );
 408:         --child->n_dups;
 409:     }
 410: 
 411: }
 412: 
 413: 
 414: 
 415: LOCAL samebase(ep1,ep2)
 416: expptr ep1,ep2;
 417: {
 418:     if ( ep1->tag == ep2->tag  )
 419:     switch (ep2->tag) {
 420:         case TTEMP :
 421:         if (ep1->tempblock.memalloc == ep2->tempblock.memalloc)
 422:             return (TRUE);
 423:         break;
 424:         case TADDR :
 425:         if (ep1->addrblock.vstg == ep2->addrblock.vstg) {
 426:             switch(ep1->addrblock.vstg) {
 427:             case STGEQUIV:
 428:             case STGCOMMON:
 429:                 if (ep1->addrblock.memno == ep2->addrblock.memno &&
 430:                 ISCONST(ep1->addrblock.memoffset) &&
 431:                 ISCONST(ep2->addrblock.memoffset) &&
 432:                 ep1->addrblock.memoffset->constblock.const.ci ==
 433:                 ep2->addrblock.memoffset->constblock.const.ci ) {
 434:                     return(TRUE);
 435:                 }
 436:                 break;
 437: 
 438:             default:
 439:                 if (ep1->addrblock.memno == ep2->addrblock.memno ) {
 440:                 return(TRUE);
 441:                 }
 442:             }
 443:         }
 444:         break;
 445:         case TCONST :
 446:         if( (ep1->constblock.vtype) ==
 447:             (ep2->constblock.vtype)  )
 448:         {
 449:             union Constant *ap,*bp;
 450:             ap= &ep1->constblock.const;
 451:             bp= &ep2->constblock.const;
 452:             switch(ep1->constblock.vtype)
 453: 
 454:             {
 455:             case TYSHORT:
 456:             case TYLONG:
 457:                 if(ap->ci == bp->ci) return(TRUE);
 458:                 break;
 459:             case TYREAL:
 460:             case TYDREAL:
 461:                 if(ap->cd[0] == bp->cd[0]) return(TRUE);
 462:                 break;
 463:             case TYCOMPLEX:
 464:             case TYDCOMPLEX:
 465:                 if(ap->cd[0] == bp->cd[0] &&
 466:                     ap->cd[1] == bp->cd[1] )
 467:                     return(TRUE);
 468:                 break;
 469:             }
 470:         }
 471:         break;
 472: 
 473:         default :
 474:         badtag ("samebase",ep2->tag);
 475:     }
 476:     return(FALSE);
 477: }
 478: 
 479: 
 480: 
 481: LOCAL idptr findid(idaddr)
 482: expptr idaddr;
 483: 
 484: /* Find an identifier's IDblock given its idaddr. If the identifier has no
 485: ** IBblock build one
 486: */
 487: 
 488: {
 489:     register idptr idp;
 490:     if(current_BB->headid == 0) newid(idaddr,&current_BB->headid);
 491:     idp=current_BB->headid;
 492: 
 493:     do {
 494:         if (samebase(idp->idaddr,idaddr) )  break;
 495:         if (idp->next == 0) {
 496:             newid(idaddr,&idp->next);
 497:             idp = idp->next;
 498:             break;
 499:         }
 500:         idp = idp->next;
 501:     }
 502:     while(TRUE);
 503: 
 504:     return(idp);
 505: }
 506: 
 507: 
 508: 
 509: LOCAL valuen findnode(ep,leftc,rightc)
 510: expptr ep;
 511: valuen leftc,rightc;
 512: {
 513:     /* Look for a matching value node in the available computations stack
 514: 	*/
 515:     register valuen p;
 516: 
 517:     for ( p=current_BB->headnode; p ; p=p->next)  {
 518:         if( ( ! p->is_dead)   &&
 519:             (p->lc == leftc)  &&
 520:             (p->rc == rightc) &&
 521:             ( (ep->tag == TEXPR && p->opp->tag == TEXPR
 522:               && p->opp->exprblock.opcode == ep->exprblock.opcode
 523:               && p->opp->exprblock.vtype == ep->exprblock.vtype
 524:               )
 525:             || (ep->tag == TADDR) || (ep->tag == TTEMP)
 526:             )
 527:           )
 528:             return(p);
 529:     }
 530:     return(NULL);
 531: }
 532: 
 533: 
 534: 
 535: LOCAL valuen scanchain(listp,p_parent)
 536: expptr listp;
 537: chainp *p_parent;
 538: 
 539: /* Make value nodes from the chain hanging off a LISTBLOCK
 540: */
 541: 
 542: {
 543:     valuen lnode,rnode,new,scantree();
 544:     chainp p;
 545: 
 546:     p= *p_parent;
 547:     if (p == NULL) return(NULL);
 548:     lnode = scantree( &p->datap);
 549:     rnode = scanchain(listp, &p->nextp);
 550:     new = newnode(listp,lnode,rnode,0);
 551:     new->rs = new;
 552:     return(new->rs);
 553: }
 554: 
 555: 
 556: 
 557: LOCAL valuen scantree(p_parent)
 558: expptr *p_parent;
 559: 
 560: /* build a value node and return its address. p must point to an
 561: ** exprblock an addrblock a listblock  or a constblock.
 562: */
 563: 
 564: {
 565: valuen lnode, rnode,rsltnode,new;
 566: expptr opp,p;
 567: Exprp ep1,ep2;
 568: idptr idp;
 569: 
 570: p = *p_parent;
 571: if(p == NULL) return(NULL);
 572: 
 573: switch (p->tag) {
 574:     case TCONST :
 575:         return( findid(p)->initval );
 576: 
 577:     case TTEMP :
 578:         idp = findid(p);
 579:         if(idp->assgnval) return(idp->assgnval);
 580: 
 581:         lnode = idp->initval;
 582:         rnode = scantree( &p->tempblock.memalloc);
 583: 
 584:         rsltnode = findnode(p,lnode,rnode);
 585:         if(rsltnode)
 586:             return(rsltnode);
 587:         else {
 588:             new = newnode(p,lnode,rnode,0);
 589:             new->rs = new;
 590:             new->parent = p_parent;
 591:             return(new->rs);
 592:         }
 593: 
 594:     case TADDR :
 595:         idp = findid(p);
 596:         if(idp->assgnval) return(idp->assgnval);
 597: 
 598:         lnode = idp->initval;
 599:         rnode = scantree( &p->addrblock.memoffset);
 600: 
 601:         rsltnode = findnode(p,lnode,rnode);
 602:         if(rsltnode) {
 603: #ifdef  notdef
 604:             /*
 605: 			 * This code is broken until OPINDIRECT is implemented.
 606: 			 */
 607:             if(p->addrblock.memoffset != NULL &&
 608:                 p->addrblock.memoffset->tag == TEXPR)
 609:                 addadup(p_parent,rsltnode);
 610: #endif	notdef
 611:             return(rsltnode);
 612:         }
 613:         else {
 614:             new = newnode(p,lnode,rnode,0);
 615:             new->rs = new;
 616:             new->parent = p_parent;
 617:             return(new->rs);
 618:         }
 619: 
 620:     case TLIST :
 621:         return(scanchain(p->listblock.listp,&p->listblock.listp));
 622: 
 623:     default :
 624:         badtag ("scantree",p->tag);
 625: 
 626:     case TEXPR  :
 627:         lnode = scantree(&p->exprblock.leftp);
 628:         rnode = scantree(&p->exprblock.rightp);
 629: 
 630:         switch (p->exprblock.opcode) {
 631:             case OPASSIGN :
 632:                 {
 633:                 Addrp ap;
 634: 
 635:                 ap = (Addrp) p->exprblock.leftp;
 636:                 idp = findid(ap);
 637:                 killdepnodes(idp);
 638:                 if( ! ap->isarray ) {
 639:                     if(rnode->is_dead)idp->assgnval=idp->initval;
 640:                     else idp->assgnval = rnode;
 641:                 }
 642:                 new = newnode(p,idp->initval,NULL,NULL);
 643:                 appendnode(new);
 644:                 new->rs = new;
 645:                 return(new->rs);
 646:                 }
 647: 
 648:             /*
 649: 			 * Don't optimize these...  they're a real hassle.
 650: 			 */
 651:             case OPPLUSEQ :
 652:             case OPSTAREQ :
 653:                 {
 654:                 Addrp ap;
 655: 
 656:                 ap = (Addrp) p->exprblock.leftp;
 657:                 idp = findid(ap);
 658:                 killdepnodes(idp);
 659:                 idp->assgnval = NULL;
 660:                 new = newnode(p,lnode,rnode,NULL);
 661:                 new->rs = new;
 662:                 return(new->rs);
 663:                 }
 664: 
 665:             case OPCALL :
 666:                 {
 667:                 chainp cp;
 668: 
 669:                 if(p->exprblock.rightp)
 670: 
 671:     /* pretend that all variables on the arglist have just
 672: 	** been assigned to i.e. kill of calculations that
 673: 	** depend on them. Not necessary for CCALL(by value)
 674: 	*/
 675: 
 676:                 for(cp=p->exprblock.rightp->listblock.listp;
 677:                                 cp;cp=cp->nextp)
 678:                     if (cp->datap->tag == TADDR ||
 679:                         cp->datap->tag == TTEMP){
 680:                         idp = findid(cp->datap);
 681:                         killdepnodes(idp);
 682:                         idp->assgnval = NULL;
 683:                 }
 684: 
 685:                 new = newnode(p,lnode,rnode,NULL);
 686:                 new->rs = new;
 687:                 return(new->rs);
 688:                 }
 689: 
 690:             case OPCONCAT:
 691:             case OPADDR:
 692:             case OPCOLON:
 693:             case OPINDIRECT:
 694:         /*
 695: 		 * For now, do not optimize LSHIFT until OPINDIRECT
 696: 		 * implemented.
 697: 		 */
 698:             case OPLSHIFT:
 699:                 new = newnode(p,lnode,rnode,NULL);
 700:                 new->rs = new;
 701:                 return(new->rs);
 702: 
 703:             case OPCOMMA:
 704:                 badop ("scantree",OPCOMMA);
 705:                 break;
 706: 
 707:             default :
 708:                 rsltnode = findnode(p,lnode,rnode);
 709:                 if (rsltnode) {
 710:                     addadup(p_parent,rsltnode);
 711:                     return(rsltnode);
 712:                 }
 713:                 else {
 714:                     new = newnode(p,lnode,rnode,NULL);
 715:                     new->rs = new;
 716:                     new->parent = p_parent;
 717:                     appendnode(new);
 718:                     return(new->rs);
 719:                 }
 720:             }
 721:     }
 722: }
 723: 
 724: 
 725: 
 726: LOCAL prunetrees()
 727: 
 728: /* The only optcse.c routine that does any real work: go through the available
 729: ** computations stack and eliminate redundant subtrees.
 730: */
 731: 
 732: {
 733: Addrp tempv;
 734: register duplptr dl;
 735: register valuen p;
 736: expptr t;
 737: int is_addrnode;
 738: expptr *addr_tree1 = NULL ;
 739: expptr tree2 = NULL ;
 740: 
 741: for(p=current_BB->headnode;p;p=p->next)
 742: {
 743:     if(p->rs == NULL) {
 744:         if( addr_tree1 && tree2 )
 745:              *addr_tree1 = fixtype(mkexpr(OPCOMMA,tree2,*addr_tree1));
 746:         addr_tree1 = (expptr*) p->opp;
 747:         tree2 = NULL;
 748:     }
 749:     if (p->n_dups ) {
 750: 
 751:         if (p->opp->tag == TTEMP)
 752:             fprintf(diagfile,"TTEMP in prunetrees - cbb\n");
 753:         if(p->opp->tag == TADDR) is_addrnode = TRUE;
 754:         else is_addrnode = FALSE;
 755: 
 756:         if (is_addrnode)
 757:             tempv = mktemp(TYADDR,NULL);
 758:         else
 759:             tempv = mktemp(p->opp->exprblock.vtype,
 760:                 p->opp->exprblock.vleng);
 761:         cse2count++;
 762: 
 763:         if(tree2)
 764:             tree2 = fixtype(mkexpr(OPCOMMA,tree2,
 765:                 fixtype(mkexpr(OPASSIGN,cpexpr(tempv),
 766:                 (is_addrnode ? addrof(p->opp) :  p->opp)
 767:                 ))));
 768:         else
 769:             tree2 = fixtype(mkexpr(OPASSIGN,cpexpr(tempv),
 770:                 (is_addrnode ? addrof(p->opp) :  p->opp)
 771:                 ));
 772: 
 773:         if(is_addrnode)
 774:             *(p->parent) = fixtype(mkexpr(OPINDIRECT,cpexpr(tempv), NULL));
 775:         else
 776:             *(p->parent) = (expptr) cpexpr(tempv);
 777: 
 778: /* then replaces all future instances of the calculation by references to
 779:    the temporary */
 780: 
 781:         for(dl=p->headduplist;dl->next;dl=dl->next) {
 782:             cse1count++;
 783:             frexpr(*dl->parent);
 784:             if(is_addrnode)
 785:                 *(dl->parent) = fixtype(
 786:                     mkexpr(OPINDIRECT,cpexpr(tempv), NULL));
 787:             else
 788:                 *(dl->parent) = (expptr) cpexpr(tempv);
 789:         }
 790: 
 791: /* the last reference does not use a copy since the temporary can
 792:    now be freed */
 793: 
 794:         cse1count++;
 795:         frexpr(*dl->parent);
 796:         if(is_addrnode)
 797:             *(dl->parent) = fixtype(mkexpr(OPINDIRECT,tempv, NULL));
 798:         else
 799:             *(dl->parent) = (expptr) tempv;
 800: 
 801:         frtemp (tempv);
 802:     }
 803: }
 804: if(addr_tree1 && tree2)
 805:     *addr_tree1 = fixtype(mkexpr(OPCOMMA,tree2,*addr_tree1));
 806: }
 807: 
 808: 
 809: 
 810: LOCAL rewritebb (bb)
 811: Bblockp bb;
 812: {
 813:     Slotp sp;
 814:     expptr p;
 815: 
 816:     if (bb == NULL)
 817:         return;
 818:     else
 819:         current_BB = bb;
 820:     sp = current_BB->first;
 821: 
 822:     /* loop trough all BB slots and scan candidate expr trees when found */
 823: 
 824:     for (sp = current_BB->first; ; sp = sp->next)
 825:         {
 826:         switch (sp->type)
 827:             {
 828:             case SKEQ :
 829:             case SKIFN :
 830:             case SKCMGOTO :
 831:             case SKCALL :
 832:             newnode((expptr) &sp->expr,NULL,NULL,NULL);
 833:             scantree(&sp->expr);
 834:             break;
 835: 
 836:             default  :
 837:             break;
 838:             }
 839:         if (sp == current_BB->last) break;
 840:         }
 841: 
 842: /* use the information built up by scantree to prune reduntant subtrees */
 843:     prunetrees();
 844: 
 845:     current_BB = NULL;
 846: }
 847: 
 848: 
 849: 
 850: /*
 851:  *  removes all instances of OPCOMMA from the given subexpression of
 852:  *  the given buffer slot
 853:  */
 854: 
 855: expptr rmcommaop (p,sl)
 856: expptr  p;
 857: Slotp   sl;
 858: 
 859: {
 860: expptr  leftp,rightp;
 861: chainp  cp;
 862: 
 863: if (!p)
 864:     return (ENULL);
 865: switch (p->tag)
 866:     {
 867:     case TEXPR:
 868:         leftp = p->exprblock.leftp;
 869:         rightp = p->exprblock.rightp;
 870:         leftp = rmcommaop (leftp,sl);
 871:         if (p->exprblock.opcode == OPCOMMA)
 872:             {
 873:             optinsert (SKEQ,leftp,0,0,sl);
 874:             if (p->exprblock.vleng)
 875:                 free ((charptr) p->exprblock.vleng);
 876:             free ((charptr) p);
 877:             p = rmcommaop (rightp,sl);
 878:             return (p);
 879:             }
 880:         p->exprblock.leftp = leftp;
 881:         p->exprblock.rightp = rmcommaop (rightp,sl);
 882:         return (p);
 883: 
 884:     case TLIST:
 885:         for (cp = p->listblock.listp; cp; cp = cp->nextp)
 886:             cp->datap = (tagptr) rmcommaop (cp->datap,sl);
 887:         return (p);
 888: 
 889:     case TADDR:
 890:         p->addrblock.memoffset = rmcommaop (p->addrblock.memoffset,sl);
 891:         return (p);
 892: 
 893:     default:
 894:         return (p);
 895:     }
 896: }
 897: 
 898: 
 899: 
 900: /*
 901:  *  scans the code buffer, performing common subexpression elimination
 902:  */
 903: 
 904: optcse ()
 905: 
 906: {
 907: Slotp   sl;
 908: Bblockp bb;
 909: 
 910: if (debugflag[13])
 911:     return;
 912: 
 913: cse1count = 0;
 914: cse2count = 0;
 915: for (sl = firstslot; sl; sl = sl->next)
 916:     sl->expr = rmcommaop (sl->expr,sl);
 917: for (bb = firstblock; bb; bb = bb->next)
 918:     rewritebb (bb);
 919: 
 920: if (debugflag[0])
 921:     fprintf (diagfile,
 922:         "%d common subexpression use%s eliminated (%d definition%s)\n",
 923:         cse1count, (cse1count==1 ? "" : "s"),
 924:         cse2count, (cse2count==1 ? "" : "s"));
 925: }

Defined functions

addadep defined in line 288; used 1 times
addadup defined in line 373; used 2 times
appendnode defined in line 264; used 2 times
dumpstacks defined in line 69; never used
findid defined in line 481; used 6 times
findnode defined in line 509; used 3 times
killdepnodes defined in line 235; used 3 times
killid defined in line 212; used 3 times
mergedeps defined in line 132; used 1 times
newid defined in line 347; used 2 times
newnode defined in line 319; used 10 times
optcse defined in line 904; used 1 times
prunetrees defined in line 726; used 1 times
removenode defined in line 181; used 1 times
rewritebb defined in line 810; used 1 times
rmcommaop defined in line 855; used 8 times
samebase defined in line 415; used 1 times
scanchain defined in line 535; used 2 times
scantree defined in line 557; used 7 times

Defined variables

cse1count defined in line 63; used 5 times
cse2count defined in line 64; used 4 times
current_BB defined in line 62; used 19 times
sccsid defined in line 8; never used

Defined macros

FALSE defined in line 59; used 3 times
TRUE defined in line 60; used 9 times
Last modified: 1985-06-08
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2659
Valid CSS Valid XHTML 1.0 Strict