|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char sccsid[] = "@(#)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,¤t_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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.