122848Smckusick /* 222848Smckusick * Copyright (c) 1980 Regents of the University of California. 322848Smckusick * All rights reserved. The Berkeley software License Agreement 422848Smckusick * specifies the terms and conditions for redistribution. 522848Smckusick */ 622848Smckusick 722848Smckusick #ifndef lint 8*33257Sbostic static char sccsid[] = "@(#)optcse.c 5.2 (Berkeley) 01/03/88"; 922848Smckusick #endif not lint 1022848Smckusick 1122848Smckusick /* 1222848Smckusick * optcse.c 1322848Smckusick * 1422848Smckusick * Common subexpression elimination routines, F77 compiler pass 1. 1522848Smckusick * 1622848Smckusick * University of Utah CS Dept modification history: 1722848Smckusick * 1822848Smckusick * $Log: optcse.c,v $ 1922848Smckusick * Revision 2.4 84/10/29 04:40:48 donn 2022848Smckusick * Problem with conversions -- two expressions headed by a conversion may be 2122848Smckusick * identical in structure but different in type, thus type must be checked in 2222848Smckusick * findnode(). This was causing a subscript to become REAL*8 type... 2322848Smckusick * 2422848Smckusick * Revision 2.3 84/08/04 20:38:53 donn 2522848Smckusick * Added fix from Jerry Berkman for an earlier fix from Alastair Fyfe -- 2622848Smckusick * samebase() should treat EQUIVALENCEd variables just as daintily as 2722848Smckusick * COMMON variables. 2822848Smckusick * 2922848Smckusick * Revision 2.2 84/08/01 16:04:33 donn 3022848Smckusick * Changed rmcommaop so that it does subscripts too. 3122848Smckusick * 3222848Smckusick * Revision 2.1 84/07/19 12:03:44 donn 3322848Smckusick * Changed comment headers for UofU. 3422848Smckusick * 3522848Smckusick * Revision 1.5 84/07/09 14:43:05 donn 3622848Smckusick * Added changes to make OPPLUSEQ and OPSTAREQ expressions ineligible for 3722848Smckusick * CSE, since I can't think of a simple way to handle them and they are broken 3822848Smckusick * in the previous version, where they were treated like OPASSIGN -- this 3922848Smckusick * fails because CSE would think that the value of the lhs and rhs were equal. 4022848Smckusick * 4122848Smckusick * Revision 1.4 84/06/08 11:43:35 donn 4222848Smckusick * Yet another way of handling the bug with COMMON -- this one is from Alastair 4322848Smckusick * Fyfe at Sun. I backed out the old fix. 4422848Smckusick * 4522848Smckusick * Revision 1.3 84/03/07 19:25:14 donn 4622848Smckusick * Changed method of handling COMMON bug -- COMMON variables are now treated 4722848Smckusick * like array elements and hence are ineligible for CSE. 4822848Smckusick * 4922848Smckusick * Revision 1.2 84/02/26 03:30:47 donn 5022848Smckusick * Fixed bug in evaluation graph construction that caused two variables in 5122848Smckusick * common to be considered identical if they were merely in the same common, 5222848Smckusick * rather than in the same common at the same offset. 5322848Smckusick * 5422848Smckusick */ 5522848Smckusick 5622848Smckusick #include "defs.h" 5722848Smckusick #include "optim.h" 5822848Smckusick 5922848Smckusick #define FALSE 0 6022848Smckusick #define TRUE 1 6122848Smckusick 6222848Smckusick LOCAL Bblockp current_BB; 6322848Smckusick LOCAL int cse1count; /* count of number of cse uses eliminated */ 6422848Smckusick LOCAL int cse2count; /* count of number of cse def's eliminated */ 6522848Smckusick 6622848Smckusick 6722848Smckusick 6822848Smckusick 6922848Smckusick LOCAL dumpstacks() 7022848Smckusick { 7122848Smckusick duplptr dl; 7222848Smckusick valuen p; 7322848Smckusick idlptr idl; 7422848Smckusick idptr idp; 7522848Smckusick nodelptr nl; 7622848Smckusick int i; 7722848Smckusick 7822848Smckusick fprintf(diagfile,"\n *** IDblocks ***\n"); 7922848Smckusick for(idp=current_BB->headid;idp;idp=idp->next) 8022848Smckusick { 8122848Smckusick fprintf(diagfile, 8222848Smckusick "idp= %d idaddr= %d initval= %d assgnval= %d \n", 8322848Smckusick idp, idp->idaddr, idp->initval, idp->assgnval); 8422848Smckusick fprintf(diagfile,"nodes: "); 8522848Smckusick i=0; 8622848Smckusick for (nl=idp->headnodelist;nl;nl=nl->next) { 8722848Smckusick if(++i>20){ 8822848Smckusick fprintf(diagfile,"\n"); 8922848Smckusick i=0; 9022848Smckusick } 9122848Smckusick fprintf(diagfile," %d ",nl->nodep); 9222848Smckusick } 9322848Smckusick fprintf(diagfile,"\n"); 9422848Smckusick } 9522848Smckusick 9622848Smckusick fprintf(diagfile,"\n *** VALUE NODES *** \n"); 9722848Smckusick for(p=current_BB->headnode;p;p=p->next) { 9822848Smckusick fprintf(diagfile, 9922848Smckusick "\np= %d opp= %d lc= %d rc= %d rs= %d is_dead= %d n_dups %d", 10022848Smckusick p, p->opp,p->lc,p->rc, p->rs, p->is_dead, p->n_dups); 10122848Smckusick if (p->rs){ 10222848Smckusick fprintf(diagfile,"tag= %d ",p->opp->tag); 10322848Smckusick if(p->opp->tag==TEXPR) 10422848Smckusick fprintf(diagfile,"opco= %d ", 10522848Smckusick p->opp->exprblock.opcode); 10622848Smckusick } 10722848Smckusick fprintf(diagfile,"\n"); 10822848Smckusick fprintf(diagfile,"parent= %d dups: ",p->parent); 10922848Smckusick i=0; 11022848Smckusick for(dl=p->headduplist;dl;dl=dl->next) { 11122848Smckusick if(++i>20){ 11222848Smckusick fprintf(diagfile,"\n"); 11322848Smckusick i=0; 11422848Smckusick } 11522848Smckusick fprintf(diagfile," %d ",dl->parent); 11622848Smckusick } 11722848Smckusick 11822848Smckusick fprintf(diagfile,"\ndeps IDs"); 11922848Smckusick i=0; 12022848Smckusick for(idl=p->headdeplist;idl;idl=idl->next) { 12122848Smckusick if(++i>20){ 12222848Smckusick fprintf(diagfile,"\n"); 12322848Smckusick i=0; 12422848Smckusick } 12522848Smckusick fprintf(diagfile," %d ",idl->idp); 12622848Smckusick } 12722848Smckusick } 12822848Smckusick } 12922848Smckusick 13022848Smckusick 13122848Smckusick 13222848Smckusick LOCAL idlptr mergedeps(lnode,rnode) 13322848Smckusick valuen lnode,rnode; 13422848Smckusick /* Given two value nodes, merge the lists of identifiers on which they 13522848Smckusick ** depend to produce a new list incorporating both dependencies. Lists 13622848Smckusick ** are assumed to be ordered by increasing idp address. No duplicate identifiers 13722848Smckusick ** are generated in the output list. 13822848Smckusick */ 13922848Smckusick { 14022848Smckusick register idlptr lp,lp1,lp2; 14122848Smckusick idlptr head; 14222848Smckusick 14322848Smckusick lp = lp1 = lp2 = head = NULL; 14422848Smckusick if(lnode) lp1 = lnode->headdeplist; 14522848Smckusick if(rnode) lp2 = rnode->headdeplist; 14622848Smckusick 14722848Smckusick while (lp1 || lp2) { 14822848Smckusick if (lp) { 14922848Smckusick lp->next = ALLOC(IDlist); 15022848Smckusick lp = lp->next; 15122848Smckusick } 15222848Smckusick else lp = head = ALLOC(IDlist); 15322848Smckusick lp->next = 0; 15422848Smckusick if (lp1 == 0) { 15522848Smckusick lp->idp = lp2->idp; 15622848Smckusick lp2 = lp2->next; 15722848Smckusick } 15822848Smckusick else if (lp2 == 0) { 15922848Smckusick lp->idp = lp1->idp; 16022848Smckusick lp1 = lp1->next; 16122848Smckusick } 16222848Smckusick else if (lp1->idp < lp2->idp) { 16322848Smckusick lp->idp = lp1->idp; 16422848Smckusick lp1 = lp1->next; 16522848Smckusick } 16622848Smckusick else if (lp1->idp > lp2->idp) { 16722848Smckusick lp->idp = lp2->idp; 16822848Smckusick lp2 = lp2->next; 16922848Smckusick } 17022848Smckusick else { 17122848Smckusick lp->idp = lp1->idp; 17222848Smckusick lp1 = lp1->next; 17322848Smckusick lp2 = lp2->next; 17422848Smckusick } 17522848Smckusick } 17622848Smckusick return(head); 17722848Smckusick } 17822848Smckusick 17922848Smckusick 18022848Smckusick 18122848Smckusick LOCAL removenode(nodep) 18222848Smckusick valuen nodep; 18322848Smckusick /* Removes a value node from every IDblock on the node's list of identifiers. 18422848Smckusick */ 18522848Smckusick { 18622848Smckusick register idlptr idl; 18722848Smckusick register nodelptr nl; 18822848Smckusick register nodelptr *addrnl; 18922848Smckusick 19022848Smckusick if(nodep == NULL) return ; 19122848Smckusick 19222848Smckusick /* loop through all identifiers */ 19322848Smckusick for(idl=nodep->headdeplist;idl;idl=idl->next) 19422848Smckusick { 19522848Smckusick addrnl = &(idl->idp->headnodelist); 19622848Smckusick /* for each identifier loop through all nodes until match is found */ 19722848Smckusick for(nl = *addrnl; nl; nl = *addrnl) 19822848Smckusick { 19922848Smckusick if(nl->nodep == nodep) { 20022848Smckusick *addrnl = nl->next; 20122848Smckusick free ( (charptr) nl ); 20222848Smckusick break; 20322848Smckusick } 20422848Smckusick addrnl = &nl->next; 20522848Smckusick } 20622848Smckusick } 20722848Smckusick nodep->is_dead = TRUE; 20822848Smckusick } 20922848Smckusick 21022848Smckusick 21122848Smckusick 21222848Smckusick LOCAL killid(idp) 21322848Smckusick idptr idp; 21422848Smckusick /* Kill all nodes on one identifier's list of dependent nodes, i.e. remove 21522848Smckusick ** all calculations that depend on this identifier from the available 21622848Smckusick ** values stack. Free the list of records pointing at the dependent nodes. 21722848Smckusick */ 21822848Smckusick { 21922848Smckusick nodelptr nl1,nl2; 22022848Smckusick 22122848Smckusick for (nl1 = idp->headnodelist; nl1; nl1=nl2) 22222848Smckusick { 22322848Smckusick nl2 = nl1->next; 22422848Smckusick removenode(nl1->nodep); 22522848Smckusick } 22622848Smckusick /* the above call frees the node list record pointed at by nl1 since it frees 22722848Smckusick ** all the node list records that reference the value node being killed 22822848Smckusick */ 22922848Smckusick idp->headnodelist = NULL; 23022848Smckusick 23122848Smckusick } 23222848Smckusick 23322848Smckusick 23422848Smckusick 23522848Smckusick LOCAL killdepnodes(idp) 23622848Smckusick idptr idp; 23722848Smckusick /* Kill all value nodes that represent calculations which depend on 23822848Smckusick ** this identifier. If the identifier is in COMMON or EQUIVALENCE storage, 23922848Smckusick ** kill all values that depend on identifiers in COMMON or EQUIVALENCE 24022848Smckusick */ 24122848Smckusick { 24222848Smckusick int thismemno; 24322848Smckusick 24422848Smckusick if(idp->idaddr->addrblock.vstg == STGCOMMON) 24522848Smckusick { 24622848Smckusick for(idp=current_BB->headid;idp;idp=idp->next) 24722848Smckusick if(idp->idaddr->addrblock.vstg == STGCOMMON) 24822848Smckusick killid(idp); 24922848Smckusick } 25022848Smckusick else if(idp->idaddr->addrblock.vstg == STGEQUIV) 25122848Smckusick { 25222848Smckusick thismemno=idp->idaddr->addrblock.memno; 25322848Smckusick for(idp=current_BB->headid;idp;idp=idp->next) 25422848Smckusick if(idp->idaddr->addrblock.vstg == STGEQUIV 25522848Smckusick && idp->idaddr->addrblock.memno == thismemno) 25622848Smckusick killid(idp); 25722848Smckusick } 25822848Smckusick else killid(idp); 25922848Smckusick 26022848Smckusick } 26122848Smckusick 26222848Smckusick 26322848Smckusick 26422848Smckusick LOCAL appendnode(nodep) 26522848Smckusick valuen nodep; 26622848Smckusick /* Append a value node to all the IDblocks on that node's list of 26722848Smckusick ** dependent identifiers i.e., since this computation depends on 26822848Smckusick ** all the identifiers on its list then each of those identifiers should 26922848Smckusick ** include this node in their list of dependent nodes. 27022848Smckusick */ 27122848Smckusick { 27222848Smckusick register idlptr idl; 27322848Smckusick register nodelptr nl; 27422848Smckusick 27522848Smckusick for(idl=nodep->headdeplist;idl;idl=idl->next) 27622848Smckusick if(idl->idp->idaddr->tag == TADDR || 27722848Smckusick idl->idp->idaddr->tag == TTEMP) 27822848Smckusick { 27922848Smckusick nl=ALLOC(NODElist); 28022848Smckusick nl->nodep = nodep; 28122848Smckusick nl->next = idl->idp->headnodelist; 28222848Smckusick idl->idp->headnodelist = nl; 28322848Smckusick } 28422848Smckusick } 28522848Smckusick 28622848Smckusick 28722848Smckusick 28822848Smckusick LOCAL idlptr addadep(idp,nodep) 28922848Smckusick idptr idp; 29022848Smckusick valuen nodep; 29122848Smckusick /* Add an identifier to the dependents list of a value node. Dependents 29222848Smckusick ** lists are ordered by increasing idp value 29322848Smckusick */ 29422848Smckusick { 29522848Smckusick register idlptr lp1,lp2; 29622848Smckusick 29722848Smckusick lp2 = ALLOC(IDlist); 29822848Smckusick lp2->idp = idp; 29922848Smckusick if(nodep->headdeplist == 0) { 30022848Smckusick lp2->next = 0; 30122848Smckusick nodep->headdeplist = lp2; 30222848Smckusick } 30322848Smckusick else if(idp <= nodep->headdeplist->idp) { 30422848Smckusick lp2->next = nodep->headdeplist; 30522848Smckusick nodep->headdeplist = lp2; 30622848Smckusick } 30722848Smckusick else for(lp1 = nodep->headdeplist; lp1; lp1 = lp1->next) 30822848Smckusick if( (lp1->next == 0) || (idp <= lp1->next->idp) ) 30922848Smckusick { 31022848Smckusick lp2->next = lp1->next; 31122848Smckusick lp1->next = lp2; 31222848Smckusick break; 31322848Smckusick } 31422848Smckusick return(lp2); 31522848Smckusick } 31622848Smckusick 31722848Smckusick 31822848Smckusick 31922848Smckusick LOCAL valuen newnode(expr,left,right,rslt) 32022848Smckusick expptr expr; 32122848Smckusick valuen left,right,rslt; 32222848Smckusick /* Build a new value node 32322848Smckusick */ 32422848Smckusick { 32522848Smckusick register valuen p; 32622848Smckusick 32722848Smckusick p= ALLOC(VALUEnode); 32822848Smckusick p->opp = expr ; 32922848Smckusick p->parent = NULL ; 33022848Smckusick p->lc = left; 33122848Smckusick p->rc = right; 33222848Smckusick p->rs = rslt; 33322848Smckusick p->n_dups = 0; 33422848Smckusick p->is_dead = FALSE; 33522848Smckusick p->next=NULL; 33622848Smckusick p->headdeplist = mergedeps(left,right); 33722848Smckusick p->headduplist=NULL; 33822848Smckusick if(current_BB->headnode == 0) current_BB->headnode=p; 33922848Smckusick else if(current_BB->tailnode) current_BB->tailnode->next=p; 34022848Smckusick current_BB->tailnode=p; 34122848Smckusick 34222848Smckusick return(p); 34322848Smckusick } 34422848Smckusick 34522848Smckusick 34622848Smckusick 34722848Smckusick LOCAL newid(idaddr,addrof_idptr) 34822848Smckusick expptr idaddr; 34922848Smckusick idptr *addrof_idptr; 35022848Smckusick /* Build a new IDblock and hook it on the current BB's ID list 35122848Smckusick */ 35222848Smckusick { 35322848Smckusick register idptr p; 35422848Smckusick 35522848Smckusick p= ALLOC(IDblock); 35622848Smckusick 35722848Smckusick /* build a leaf value node for the identifier and put the ID on the leaf node's 35822848Smckusick ** list of dependent identifiers 35922848Smckusick */ 36022848Smckusick p->initval = newnode(idaddr,NULL,NULL,NULL); 36122848Smckusick p->initval->rs = p->initval; 36222848Smckusick addadep(p,p->initval); 36322848Smckusick 36422848Smckusick p->idaddr = idaddr; 36522848Smckusick *addrof_idptr = p; 36622848Smckusick p->headnodelist=NULL; 36722848Smckusick p->next=NULL; 36822848Smckusick 36922848Smckusick } 37022848Smckusick 37122848Smckusick 37222848Smckusick 37322848Smckusick LOCAL addadup(parent,nodep) 37422848Smckusick expptr *parent; 37522848Smckusick valuen nodep; 37622848Smckusick 37722848Smckusick /* A subtree has been found that duplicates the calculation represented 37822848Smckusick ** by the value node referenced by nodep : add the root of the reduntant 37922848Smckusick ** tree to the value node's list of duplicates. 38022848Smckusick */ 38122848Smckusick 38222848Smckusick { 38322848Smckusick register duplptr dp; 38422848Smckusick valuen child; 38522848Smckusick 38622848Smckusick dp = ALLOC(DUPlist); 38722848Smckusick dp->parent = parent; 38822848Smckusick dp->next = nodep->headduplist; 38922848Smckusick nodep->headduplist = dp; 39022848Smckusick ++nodep->n_dups; 39122848Smckusick 39222848Smckusick /* Check whether either of nodep's children is also a duplicate calculation 39322848Smckusick ** and if so peel off it's most recent dup record 39422848Smckusick */ 39522848Smckusick 39622848Smckusick if ( (child = nodep->lc) && (child->n_dups) ) 39722848Smckusick { 39822848Smckusick dp = child->headduplist; 39922848Smckusick child->headduplist = dp->next; 40022848Smckusick free ( (charptr) dp ); 40122848Smckusick --child->n_dups; 40222848Smckusick } 40322848Smckusick if ( (child = nodep->rc) && (child->n_dups) ) 40422848Smckusick { 40522848Smckusick dp = child->headduplist; 40622848Smckusick child->headduplist = dp->next; 40722848Smckusick free ( (charptr) dp ); 40822848Smckusick --child->n_dups; 40922848Smckusick } 41022848Smckusick 41122848Smckusick } 41222848Smckusick 41322848Smckusick 41422848Smckusick 41522848Smckusick LOCAL samebase(ep1,ep2) 41622848Smckusick expptr ep1,ep2; 41722848Smckusick { 41822848Smckusick if ( ep1->tag == ep2->tag ) 41922848Smckusick switch (ep2->tag) { 42022848Smckusick case TTEMP : 42122848Smckusick if (ep1->tempblock.memalloc == ep2->tempblock.memalloc) 42222848Smckusick return (TRUE); 42322848Smckusick break; 42422848Smckusick case TADDR : 42522848Smckusick if (ep1->addrblock.vstg == ep2->addrblock.vstg) { 42622848Smckusick switch(ep1->addrblock.vstg) { 42722848Smckusick case STGEQUIV: 42822848Smckusick case STGCOMMON: 42922848Smckusick if (ep1->addrblock.memno == ep2->addrblock.memno && 43022848Smckusick ISCONST(ep1->addrblock.memoffset) && 43122848Smckusick ISCONST(ep2->addrblock.memoffset) && 432*33257Sbostic ep1->addrblock.memoffset->constblock.constant.ci == 433*33257Sbostic ep2->addrblock.memoffset->constblock.constant.ci ) { 43422848Smckusick return(TRUE); 43522848Smckusick } 43622848Smckusick break; 43722848Smckusick 43822848Smckusick default: 43922848Smckusick if (ep1->addrblock.memno == ep2->addrblock.memno ) { 44022848Smckusick return(TRUE); 44122848Smckusick } 44222848Smckusick } 44322848Smckusick } 44422848Smckusick break; 44522848Smckusick case TCONST : 44622848Smckusick if( (ep1->constblock.vtype) == 44722848Smckusick (ep2->constblock.vtype) ) 44822848Smckusick { 44922848Smckusick union Constant *ap,*bp; 450*33257Sbostic ap= &ep1->constblock.constant; 451*33257Sbostic bp= &ep2->constblock.constant; 45222848Smckusick switch(ep1->constblock.vtype) 45322848Smckusick 45422848Smckusick { 45522848Smckusick case TYSHORT: 45622848Smckusick case TYLONG: 45722848Smckusick if(ap->ci == bp->ci) return(TRUE); 45822848Smckusick break; 45922848Smckusick case TYREAL: 46022848Smckusick case TYDREAL: 46122848Smckusick if(ap->cd[0] == bp->cd[0]) return(TRUE); 46222848Smckusick break; 46322848Smckusick case TYCOMPLEX: 46422848Smckusick case TYDCOMPLEX: 46522848Smckusick if(ap->cd[0] == bp->cd[0] && 46622848Smckusick ap->cd[1] == bp->cd[1] ) 46722848Smckusick return(TRUE); 46822848Smckusick break; 46922848Smckusick } 47022848Smckusick } 47122848Smckusick break; 47222848Smckusick 47322848Smckusick default : 47422848Smckusick badtag ("samebase",ep2->tag); 47522848Smckusick } 47622848Smckusick return(FALSE); 47722848Smckusick } 47822848Smckusick 47922848Smckusick 48022848Smckusick 48122848Smckusick LOCAL idptr findid(idaddr) 48222848Smckusick expptr idaddr; 48322848Smckusick 48422848Smckusick /* Find an identifier's IDblock given its idaddr. If the identifier has no 48522848Smckusick ** IBblock build one 48622848Smckusick */ 48722848Smckusick 48822848Smckusick { 48922848Smckusick register idptr idp; 49022848Smckusick if(current_BB->headid == 0) newid(idaddr,¤t_BB->headid); 49122848Smckusick idp=current_BB->headid; 49222848Smckusick 49322848Smckusick do { 49422848Smckusick if (samebase(idp->idaddr,idaddr) ) break; 49522848Smckusick if (idp->next == 0) { 49622848Smckusick newid(idaddr,&idp->next); 49722848Smckusick idp = idp->next; 49822848Smckusick break; 49922848Smckusick } 50022848Smckusick idp = idp->next; 50122848Smckusick } 50222848Smckusick while(TRUE); 50322848Smckusick 50422848Smckusick return(idp); 50522848Smckusick } 50622848Smckusick 50722848Smckusick 50822848Smckusick 50922848Smckusick LOCAL valuen findnode(ep,leftc,rightc) 51022848Smckusick expptr ep; 51122848Smckusick valuen leftc,rightc; 51222848Smckusick { 51322848Smckusick /* Look for a matching value node in the available computations stack 51422848Smckusick */ 51522848Smckusick register valuen p; 51622848Smckusick 51722848Smckusick for ( p=current_BB->headnode; p ; p=p->next) { 51822848Smckusick if( ( ! p->is_dead) && 51922848Smckusick (p->lc == leftc) && 52022848Smckusick (p->rc == rightc) && 52122848Smckusick ( (ep->tag == TEXPR && p->opp->tag == TEXPR 52222848Smckusick && p->opp->exprblock.opcode == ep->exprblock.opcode 52322848Smckusick && p->opp->exprblock.vtype == ep->exprblock.vtype 52422848Smckusick ) 52522848Smckusick || (ep->tag == TADDR) || (ep->tag == TTEMP) 52622848Smckusick ) 52722848Smckusick ) 52822848Smckusick return(p); 52922848Smckusick } 53022848Smckusick return(NULL); 53122848Smckusick } 53222848Smckusick 53322848Smckusick 53422848Smckusick 53522848Smckusick LOCAL valuen scanchain(listp,p_parent) 53622848Smckusick expptr listp; 53722848Smckusick chainp *p_parent; 53822848Smckusick 53922848Smckusick /* Make value nodes from the chain hanging off a LISTBLOCK 54022848Smckusick */ 54122848Smckusick 54222848Smckusick { 54322848Smckusick valuen lnode,rnode,new,scantree(); 54422848Smckusick chainp p; 54522848Smckusick 54622848Smckusick p= *p_parent; 54722848Smckusick if (p == NULL) return(NULL); 54822848Smckusick lnode = scantree( &p->datap); 54922848Smckusick rnode = scanchain(listp, &p->nextp); 55022848Smckusick new = newnode(listp,lnode,rnode,0); 55122848Smckusick new->rs = new; 55222848Smckusick return(new->rs); 55322848Smckusick } 55422848Smckusick 55522848Smckusick 55622848Smckusick 55722848Smckusick LOCAL valuen scantree(p_parent) 55822848Smckusick expptr *p_parent; 55922848Smckusick 56022848Smckusick /* build a value node and return its address. p must point to an 56122848Smckusick ** exprblock an addrblock a listblock or a constblock. 56222848Smckusick */ 56322848Smckusick 56422848Smckusick { 56522848Smckusick valuen lnode, rnode,rsltnode,new; 56622848Smckusick expptr opp,p; 56722848Smckusick Exprp ep1,ep2; 56822848Smckusick idptr idp; 56922848Smckusick 57022848Smckusick p = *p_parent; 57122848Smckusick if(p == NULL) return(NULL); 57222848Smckusick 57322848Smckusick switch (p->tag) { 57422848Smckusick case TCONST : 57522848Smckusick return( findid(p)->initval ); 57622848Smckusick 57722848Smckusick case TTEMP : 57822848Smckusick idp = findid(p); 57922848Smckusick if(idp->assgnval) return(idp->assgnval); 58022848Smckusick 58122848Smckusick lnode = idp->initval; 58222848Smckusick rnode = scantree( &p->tempblock.memalloc); 58322848Smckusick 58422848Smckusick rsltnode = findnode(p,lnode,rnode); 58522848Smckusick if(rsltnode) 58622848Smckusick return(rsltnode); 58722848Smckusick else { 58822848Smckusick new = newnode(p,lnode,rnode,0); 58922848Smckusick new->rs = new; 59022848Smckusick new->parent = p_parent; 59122848Smckusick return(new->rs); 59222848Smckusick } 59322848Smckusick 59422848Smckusick case TADDR : 59522848Smckusick idp = findid(p); 59622848Smckusick if(idp->assgnval) return(idp->assgnval); 59722848Smckusick 59822848Smckusick lnode = idp->initval; 59922848Smckusick rnode = scantree( &p->addrblock.memoffset); 60022848Smckusick 60122848Smckusick rsltnode = findnode(p,lnode,rnode); 60222848Smckusick if(rsltnode) { 60322848Smckusick #ifdef notdef 60422848Smckusick /* 60522848Smckusick * This code is broken until OPINDIRECT is implemented. 60622848Smckusick */ 60722848Smckusick if(p->addrblock.memoffset != NULL && 60822848Smckusick p->addrblock.memoffset->tag == TEXPR) 60922848Smckusick addadup(p_parent,rsltnode); 61022848Smckusick #endif notdef 61122848Smckusick return(rsltnode); 61222848Smckusick } 61322848Smckusick else { 61422848Smckusick new = newnode(p,lnode,rnode,0); 61522848Smckusick new->rs = new; 61622848Smckusick new->parent = p_parent; 61722848Smckusick return(new->rs); 61822848Smckusick } 61922848Smckusick 62022848Smckusick case TLIST : 62122848Smckusick return(scanchain(p->listblock.listp,&p->listblock.listp)); 62222848Smckusick 62322848Smckusick default : 62422848Smckusick badtag ("scantree",p->tag); 62522848Smckusick 62622848Smckusick case TEXPR : 62722848Smckusick lnode = scantree(&p->exprblock.leftp); 62822848Smckusick rnode = scantree(&p->exprblock.rightp); 62922848Smckusick 63022848Smckusick switch (p->exprblock.opcode) { 63122848Smckusick case OPASSIGN : 63222848Smckusick { 63322848Smckusick Addrp ap; 63422848Smckusick 63522848Smckusick ap = (Addrp) p->exprblock.leftp; 63622848Smckusick idp = findid(ap); 63722848Smckusick killdepnodes(idp); 63822848Smckusick if( ! ap->isarray ) { 63922848Smckusick if(rnode->is_dead)idp->assgnval=idp->initval; 64022848Smckusick else idp->assgnval = rnode; 64122848Smckusick } 64222848Smckusick new = newnode(p,idp->initval,NULL,NULL); 64322848Smckusick appendnode(new); 64422848Smckusick new->rs = new; 64522848Smckusick return(new->rs); 64622848Smckusick } 64722848Smckusick 64822848Smckusick /* 64922848Smckusick * Don't optimize these... they're a real hassle. 65022848Smckusick */ 65122848Smckusick case OPPLUSEQ : 65222848Smckusick case OPSTAREQ : 65322848Smckusick { 65422848Smckusick Addrp ap; 65522848Smckusick 65622848Smckusick ap = (Addrp) p->exprblock.leftp; 65722848Smckusick idp = findid(ap); 65822848Smckusick killdepnodes(idp); 65922848Smckusick idp->assgnval = NULL; 66022848Smckusick new = newnode(p,lnode,rnode,NULL); 66122848Smckusick new->rs = new; 66222848Smckusick return(new->rs); 66322848Smckusick } 66422848Smckusick 66522848Smckusick case OPCALL : 66622848Smckusick { 66722848Smckusick chainp cp; 66822848Smckusick 66922848Smckusick if(p->exprblock.rightp) 67022848Smckusick 67122848Smckusick /* pretend that all variables on the arglist have just 67222848Smckusick ** been assigned to i.e. kill of calculations that 67322848Smckusick ** depend on them. Not necessary for CCALL(by value) 67422848Smckusick */ 67522848Smckusick 67622848Smckusick for(cp=p->exprblock.rightp->listblock.listp; 67722848Smckusick cp;cp=cp->nextp) 67822848Smckusick if (cp->datap->tag == TADDR || 67922848Smckusick cp->datap->tag == TTEMP){ 68022848Smckusick idp = findid(cp->datap); 68122848Smckusick killdepnodes(idp); 68222848Smckusick idp->assgnval = NULL; 68322848Smckusick } 68422848Smckusick 68522848Smckusick new = newnode(p,lnode,rnode,NULL); 68622848Smckusick new->rs = new; 68722848Smckusick return(new->rs); 68822848Smckusick } 68922848Smckusick 69022848Smckusick case OPCONCAT: 69122848Smckusick case OPADDR: 69222848Smckusick case OPCOLON: 69322848Smckusick case OPINDIRECT: 69422848Smckusick /* 69522848Smckusick * For now, do not optimize LSHIFT until OPINDIRECT 69622848Smckusick * implemented. 69722848Smckusick */ 69822848Smckusick case OPLSHIFT: 69922848Smckusick new = newnode(p,lnode,rnode,NULL); 70022848Smckusick new->rs = new; 70122848Smckusick return(new->rs); 70222848Smckusick 70322848Smckusick case OPCOMMA: 70422848Smckusick badop ("scantree",OPCOMMA); 70522848Smckusick break; 70622848Smckusick 70722848Smckusick default : 70822848Smckusick rsltnode = findnode(p,lnode,rnode); 70922848Smckusick if (rsltnode) { 71022848Smckusick addadup(p_parent,rsltnode); 71122848Smckusick return(rsltnode); 71222848Smckusick } 71322848Smckusick else { 71422848Smckusick new = newnode(p,lnode,rnode,NULL); 71522848Smckusick new->rs = new; 71622848Smckusick new->parent = p_parent; 71722848Smckusick appendnode(new); 71822848Smckusick return(new->rs); 71922848Smckusick } 72022848Smckusick } 72122848Smckusick } 72222848Smckusick } 72322848Smckusick 72422848Smckusick 72522848Smckusick 72622848Smckusick LOCAL prunetrees() 72722848Smckusick 72822848Smckusick /* The only optcse.c routine that does any real work: go through the available 72922848Smckusick ** computations stack and eliminate redundant subtrees. 73022848Smckusick */ 73122848Smckusick 73222848Smckusick { 73322848Smckusick Addrp tempv; 73422848Smckusick register duplptr dl; 73522848Smckusick register valuen p; 73622848Smckusick expptr t; 73722848Smckusick int is_addrnode; 73822848Smckusick expptr *addr_tree1 = NULL ; 73922848Smckusick expptr tree2 = NULL ; 74022848Smckusick 74122848Smckusick for(p=current_BB->headnode;p;p=p->next) 74222848Smckusick { 74322848Smckusick if(p->rs == NULL) { 74422848Smckusick if( addr_tree1 && tree2 ) 74522848Smckusick *addr_tree1 = fixtype(mkexpr(OPCOMMA,tree2,*addr_tree1)); 74622848Smckusick addr_tree1 = (expptr*) p->opp; 74722848Smckusick tree2 = NULL; 74822848Smckusick } 74922848Smckusick if (p->n_dups ) { 75022848Smckusick 75122848Smckusick if (p->opp->tag == TTEMP) 75222848Smckusick fprintf(diagfile,"TTEMP in prunetrees - cbb\n"); 75322848Smckusick if(p->opp->tag == TADDR) is_addrnode = TRUE; 75422848Smckusick else is_addrnode = FALSE; 75522848Smckusick 75622848Smckusick if (is_addrnode) 75722848Smckusick tempv = mktemp(TYADDR,NULL); 75822848Smckusick else 75922848Smckusick tempv = mktemp(p->opp->exprblock.vtype, 76022848Smckusick p->opp->exprblock.vleng); 76122848Smckusick cse2count++; 76222848Smckusick 76322848Smckusick if(tree2) 76422848Smckusick tree2 = fixtype(mkexpr(OPCOMMA,tree2, 76522848Smckusick fixtype(mkexpr(OPASSIGN,cpexpr(tempv), 76622848Smckusick (is_addrnode ? addrof(p->opp) : p->opp) 76722848Smckusick )))); 76822848Smckusick else 76922848Smckusick tree2 = fixtype(mkexpr(OPASSIGN,cpexpr(tempv), 77022848Smckusick (is_addrnode ? addrof(p->opp) : p->opp) 77122848Smckusick )); 77222848Smckusick 77322848Smckusick if(is_addrnode) 77422848Smckusick *(p->parent) = fixtype(mkexpr(OPINDIRECT,cpexpr(tempv), NULL)); 77522848Smckusick else 77622848Smckusick *(p->parent) = (expptr) cpexpr(tempv); 77722848Smckusick 77822848Smckusick /* then replaces all future instances of the calculation by references to 77922848Smckusick the temporary */ 78022848Smckusick 78122848Smckusick for(dl=p->headduplist;dl->next;dl=dl->next) { 78222848Smckusick cse1count++; 78322848Smckusick frexpr(*dl->parent); 78422848Smckusick if(is_addrnode) 78522848Smckusick *(dl->parent) = fixtype( 78622848Smckusick mkexpr(OPINDIRECT,cpexpr(tempv), NULL)); 78722848Smckusick else 78822848Smckusick *(dl->parent) = (expptr) cpexpr(tempv); 78922848Smckusick } 79022848Smckusick 79122848Smckusick /* the last reference does not use a copy since the temporary can 79222848Smckusick now be freed */ 79322848Smckusick 79422848Smckusick cse1count++; 79522848Smckusick frexpr(*dl->parent); 79622848Smckusick if(is_addrnode) 79722848Smckusick *(dl->parent) = fixtype(mkexpr(OPINDIRECT,tempv, NULL)); 79822848Smckusick else 79922848Smckusick *(dl->parent) = (expptr) tempv; 80022848Smckusick 80122848Smckusick frtemp (tempv); 80222848Smckusick } 80322848Smckusick } 80422848Smckusick if(addr_tree1 && tree2) 80522848Smckusick *addr_tree1 = fixtype(mkexpr(OPCOMMA,tree2,*addr_tree1)); 80622848Smckusick } 80722848Smckusick 80822848Smckusick 80922848Smckusick 81022848Smckusick LOCAL rewritebb (bb) 81122848Smckusick Bblockp bb; 81222848Smckusick { 81322848Smckusick Slotp sp; 81422848Smckusick expptr p; 81522848Smckusick 81622848Smckusick if (bb == NULL) 81722848Smckusick return; 81822848Smckusick else 81922848Smckusick current_BB = bb; 82022848Smckusick sp = current_BB->first; 82122848Smckusick 82222848Smckusick /* loop trough all BB slots and scan candidate expr trees when found */ 82322848Smckusick 82422848Smckusick for (sp = current_BB->first; ; sp = sp->next) 82522848Smckusick { 82622848Smckusick switch (sp->type) 82722848Smckusick { 82822848Smckusick case SKEQ : 82922848Smckusick case SKIFN : 83022848Smckusick case SKCMGOTO : 83122848Smckusick case SKCALL : 83222848Smckusick newnode((expptr) &sp->expr,NULL,NULL,NULL); 83322848Smckusick scantree(&sp->expr); 83422848Smckusick break; 83522848Smckusick 83622848Smckusick default : 83722848Smckusick break; 83822848Smckusick } 83922848Smckusick if (sp == current_BB->last) break; 84022848Smckusick } 84122848Smckusick 84222848Smckusick /* use the information built up by scantree to prune reduntant subtrees */ 84322848Smckusick prunetrees(); 84422848Smckusick 84522848Smckusick current_BB = NULL; 84622848Smckusick } 84722848Smckusick 84822848Smckusick 84922848Smckusick 85022848Smckusick /* 85122848Smckusick * removes all instances of OPCOMMA from the given subexpression of 85222848Smckusick * the given buffer slot 85322848Smckusick */ 85422848Smckusick 85522848Smckusick expptr rmcommaop (p,sl) 85622848Smckusick expptr p; 85722848Smckusick Slotp sl; 85822848Smckusick 85922848Smckusick { 86022848Smckusick expptr leftp,rightp; 86122848Smckusick chainp cp; 86222848Smckusick 86322848Smckusick if (!p) 86422848Smckusick return (ENULL); 86522848Smckusick switch (p->tag) 86622848Smckusick { 86722848Smckusick case TEXPR: 86822848Smckusick leftp = p->exprblock.leftp; 86922848Smckusick rightp = p->exprblock.rightp; 87022848Smckusick leftp = rmcommaop (leftp,sl); 87122848Smckusick if (p->exprblock.opcode == OPCOMMA) 87222848Smckusick { 87322848Smckusick optinsert (SKEQ,leftp,0,0,sl); 87422848Smckusick if (p->exprblock.vleng) 87522848Smckusick free ((charptr) p->exprblock.vleng); 87622848Smckusick free ((charptr) p); 87722848Smckusick p = rmcommaop (rightp,sl); 87822848Smckusick return (p); 87922848Smckusick } 88022848Smckusick p->exprblock.leftp = leftp; 88122848Smckusick p->exprblock.rightp = rmcommaop (rightp,sl); 88222848Smckusick return (p); 88322848Smckusick 88422848Smckusick case TLIST: 88522848Smckusick for (cp = p->listblock.listp; cp; cp = cp->nextp) 88622848Smckusick cp->datap = (tagptr) rmcommaop (cp->datap,sl); 88722848Smckusick return (p); 88822848Smckusick 88922848Smckusick case TADDR: 89022848Smckusick p->addrblock.memoffset = rmcommaop (p->addrblock.memoffset,sl); 89122848Smckusick return (p); 89222848Smckusick 89322848Smckusick default: 89422848Smckusick return (p); 89522848Smckusick } 89622848Smckusick } 89722848Smckusick 89822848Smckusick 89922848Smckusick 90022848Smckusick /* 90122848Smckusick * scans the code buffer, performing common subexpression elimination 90222848Smckusick */ 90322848Smckusick 90422848Smckusick optcse () 90522848Smckusick 90622848Smckusick { 90722848Smckusick Slotp sl; 90822848Smckusick Bblockp bb; 90922848Smckusick 91022848Smckusick if (debugflag[13]) 91122848Smckusick return; 91222848Smckusick 91322848Smckusick cse1count = 0; 91422848Smckusick cse2count = 0; 91522848Smckusick for (sl = firstslot; sl; sl = sl->next) 91622848Smckusick sl->expr = rmcommaop (sl->expr,sl); 91722848Smckusick for (bb = firstblock; bb; bb = bb->next) 91822848Smckusick rewritebb (bb); 91922848Smckusick 92022848Smckusick if (debugflag[0]) 92122848Smckusick fprintf (diagfile, 92222848Smckusick "%d common subexpression use%s eliminated (%d definition%s)\n", 92322848Smckusick cse1count, (cse1count==1 ? "" : "s"), 92422848Smckusick cse2count, (cse2count==1 ? "" : "s")); 92522848Smckusick } 926