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