1 /*-------------------------------------------------------------------------
3 SDCCdflow.c - source file for data flow analysis and other utility
4 routines related to data flow.
6 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
25 -------------------------------------------------------------------------*/
28 #include "SDCCglobl.h"
32 #include "SDCChasht.h"
35 #include "SDCCicode.h"
36 #include "SDCClabel.h"
37 #include "SDCCBBlock.h"
40 #include "SDCCcflow.h"
41 #include "SDCCdflow.h"
43 /*-----------------------------------------------------------------*/
44 /* ifKilledInBlock - will return 1 if the symbol is redefined in B */
45 /*-----------------------------------------------------------------*/
46 DEFSETFUNC(ifKilledInBlock)
52 /* if this is a global variable and this block
53 has a function call then delete it */
54 if (isOperandGlobal(cdp->sym) && src->hasFcall)
57 /* if this is pointer get then it will be killed
58 if there is a pointer set for the same pointer
60 if (POINTER_GET(cdp->diCode) &&
61 bitVectBitValue(src->ptrsSet,
62 IC_LEFT(cdp->diCode)->key))
65 /* if assignment to iTmep then if right is defined
66 elsewhere kill this one */
67 if (ASSIGNMENT(cdp->diCode) &&
68 !POINTER_SET(cdp->diCode) &&
69 IS_ITEMP(IC_RESULT(cdp->diCode)) &&
70 IS_SYMOP(IC_RIGHT(cdp->diCode)) &&
71 bitVectBitsInCommon(src->outDefs,OP_DEFS(IC_RIGHT(cdp->diCode))))
74 /* if we find it in the defSet of this block */
75 if (bitVectBitsInCommon(src->defSet,OP_DEFS(cdp->sym)))
78 /* if in the outdef we find a definition other than this one */
79 /* to do this we make a copy of the out definitions and turn */
80 /* this one off then check if there are other definitions */
81 bitVectUnSetBit (outs = bitVectCopy (src->outDefs),
83 if (bitVectBitsInCommon (outs,OP_DEFS(cdp->sym))) {
84 setToNull((void **) &outs);
88 setToNull((void **) &outs);
90 /* if the operands of this one was changed in the block */
93 ( (IS_SYMOP(IC_LEFT(cdp->diCode)) &&
94 bitVectBitsInCommon (src->defSet,OP_DEFS(IC_LEFT(cdp->diCode)))) ||
95 (IS_SYMOP(IC_RIGHT(cdp->diCode)) &&
96 bitVectBitsInCommon (src->defSet,OP_DEFS(IC_RIGHT(cdp->diCode)))) ))
102 /*-----------------------------------------------------------------*/
103 /* mergeInExprs - copy the in expression if it dominates */
104 /*-----------------------------------------------------------------*/
105 DEFSETFUNC(mergeInExprs)
108 V_ARG(eBBlock *,dest);
109 V_ARG(int *,firstTime);
111 /* if in the dominator list then */
112 if (bitVectBitValue(dest->domVect,ebp->bbnum) && dest != ebp) {
113 /* if already present then intersect */
114 if (!dest->inExprs && *firstTime)
115 dest->inExprs = setFromSet(ebp->outExprs);
117 dest->inExprs = intersectSets (dest->inExprs,
120 /* copy the pointer set from the dominator */
121 dest->inPtrsSet = bitVectCopy(ebp->ptrsSet);
124 /* delete only if killed in this block */
125 deleteItemIf (&dest->inExprs,ifKilledInBlock, ebp);
132 /*-----------------------------------------------------------------*/
133 /* mergeInDefs - merge in incoming definitions */
134 /*-----------------------------------------------------------------*/
135 DEFSETFUNC(mergeInDefs)
137 eBBlock *ebp = item ;
138 V_ARG(eBBlock *,dest);
139 V_ARG(int *,firstTime);
141 /* the in definition is the union of the out */
142 /* of all blocks that come to this block */
143 if (!dest->inDefs && *firstTime)
144 dest->inDefs = bitVectCopy (ebp->outDefs);
146 dest->inDefs = bitVectUnion (dest->inDefs,
155 /*-----------------------------------------------------------------*/
156 /* computeDataFlow - does computations for data flow accross blocks*/
157 /*-----------------------------------------------------------------*/
158 void computeDataFlow (eBBlock **ebbs, int count)
168 for ( i = 0 ; i < count ; i++ ) {
175 /* if this is the entry block then continue */
176 /* since entry block can never have any inExprs */
180 /* get blocks that can come to this block */
181 pred = edgesTo(ebbs[i]);
183 /* make a copy of the outExpressions : to be */
184 /* used for iteration */
185 oldOut = setFromSet(ebbs[i]->outExprs);
186 setToNull ((void **)&ebbs[i]->inDefs);
188 /* indefitions are easy just merge them by union */
189 /* these are the definitions that can possibly */
190 /* reach this block */
192 applyToSet(pred,mergeInDefs,ebbs[i],&firstTime);
195 /* if none of the edges coming to this block */
196 /* dominate this block then add the immediate dominator */
197 /* of this block to the list of predecessors */
198 for ( pBlock = setFirstItem(pred); pBlock ;
199 pBlock = setNextItem(pred)) {
200 if (bitVectBitValue(ebbs[i]->domVect,pBlock->bbnum))
204 /* get the immediate dominator and put it there */
206 eBBlock *idom = immedDom(ebbs,ebbs[i]);
208 addSetHead (&pred,idom);
211 /* figure out the incoming expressions */
212 /* this is a little more complex */
213 setToNull ((void **)&ebbs[i]->inExprs);
215 applyToSet(pred,mergeInExprs,ebbs[i],&firstTime);
217 setToNull ((void **)&pred);
219 /* do cse with computeOnly flag set to TRUE */
220 /* this by far the quickest way of computing*/
221 cseBBlock(ebbs[i],TRUE,ebbs,count);
223 /* if it change we will need to iterate */
224 change += ! isSetsEqualWith(ebbs[i]->outExprs,oldOut,isCseDefEqual);
227 if (!change) /* iterate till no change */
234 /*-----------------------------------------------------------------*/
235 /* usedBetweenPoints - used between start & end */
236 /*-----------------------------------------------------------------*/
237 int usedBetweenPoints ( operand *op, iCode *start, iCode *end )
241 for (;lic != end; lic = lic->next) {
243 /* if the operand is a parameter */
244 /* then check for calls and return */
245 /* true if there is a call */
249 if ( isParameterToCall(IC_ARGS(lic),op))
255 /* if ifx then check the condition */
256 if (lic->op == IFX &&
257 IC_COND(lic)->key == op->key )
260 if (lic->op == JUMPTABLE &&
261 IC_JTCOND(lic)->key == op->key )
265 IC_RIGHT(lic)->key == op->key )
269 IC_LEFT(lic)->key == op->key )
272 /* for a pointer assignment usage */
273 if (POINTER_SET(lic) &&
274 op->key == IC_RESULT(lic)->key )
277 if (IC_RESULT(lic) && op->key == IC_RESULT(lic)->key)
286 /*-----------------------------------------------------------------*/
287 /* usedInRemaining - returns point of usage for an operand if found*/
288 /*-----------------------------------------------------------------*/
289 iCode *usedInRemaining (operand *op, iCode *ic)
296 for (;lic; lic = lic->next) {
298 /* if the operand is a parameter */
299 /* then check for calls and return */
300 /* true if there is a call */
301 /* if this is a global variable then
303 if ( lic->op == CALL || lic->op == PCALL ) {
306 isParameterToCall(IC_ARGS(lic),op)) ||
307 isOperandGlobal (op))
311 if (ic->op == SEND &&
312 isOperandEqual (IC_LEFT(lic),op))
318 /* if ifx then check the condition */
319 if (lic->op == IFX &&
320 isOperandEqual (IC_COND(lic),op))
323 if (lic->op == JUMPTABLE &&
324 isOperandEqual (IC_JTCOND(lic),op) )
328 isOperandEqual(IC_RIGHT(lic),op))
332 isOperandEqual(IC_LEFT(lic),op) )
335 /* for a pointer assignment usage */
336 if (POINTER_SET(lic) &&
337 isOperandEqual (op,IC_RESULT(lic)))
340 if (IC_RESULT(lic) && isOperandEqual(IC_RESULT(lic),op))
349 /*-----------------------------------------------------------------*/
350 /* isDefAlive - will return true if definiton reaches a block & used */
351 /*-----------------------------------------------------------------*/
352 DEFSETFUNC(isDefAlive)
355 V_ARG(iCode *,diCode);
362 /* if this definition is used in the block */
363 if (bitVectBitValue(ebp->usesDefs,diCode->key))
366 return applyToSet(ebp->succList,isDefAlive,diCode);