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