diff options
| author | Xavier ASUS <xavi92psx@gmail.com> | 2019-10-18 00:31:54 +0200 |
|---|---|---|
| committer | Xavier ASUS <xavi92psx@gmail.com> | 2019-10-18 00:31:54 +0200 |
| commit | 268a53de823a6750d6256ee1fb1e7707b4b45740 (patch) | |
| tree | 42c1799a9a82b2f7d9790ee9fe181d72a7274751 /src/SDCCdflow.c | |
| download | sdcc-gas-268a53de823a6750d6256ee1fb1e7707b4b45740.tar.gz | |
sdcc-3.9.0 fork implementing GNU assembler syntax
This fork aims to provide better support for stm8-binutils
Diffstat (limited to 'src/SDCCdflow.c')
| -rw-r--r-- | src/SDCCdflow.c | 405 |
1 files changed, 405 insertions, 0 deletions
diff --git a/src/SDCCdflow.c b/src/SDCCdflow.c new file mode 100644 index 0000000..019a07e --- /dev/null +++ b/src/SDCCdflow.c @@ -0,0 +1,405 @@ +/*------------------------------------------------------------------------- + + SDCCdflow.c - source file for data flow analysis and other utility + routines related to data flow. + + Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998) + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! +-------------------------------------------------------------------------*/ + +#include "common.h" + +/*-----------------------------------------------------------------*/ +/* ifKilledInBlock - will return 1 if the symbol is redefined in B */ +/*-----------------------------------------------------------------*/ +DEFSETFUNC (ifKilledInBlock) +{ + cseDef *cdp = item; + V_ARG (eBBlock *, src); + bitVect *outs; + + /* if this is a global variable and this block + has a function call then delete it */ + if (isOperandGlobal (cdp->sym) && src->hasFcall) + return 1; + + /* if this is pointer get then it will be killed + if there is a pointer set for the same pointer + in this block */ + if (POINTER_GET (cdp->diCode) && + bitVectBitValue (src->ptrsSet, + IC_LEFT (cdp->diCode)->key)) + return 1; + + /* if assignment to iTmep then if right is defined + elsewhere kill this one */ + if (ASSIGNMENT (cdp->diCode) && + !POINTER_SET (cdp->diCode) && + IS_ITEMP (IC_RESULT (cdp->diCode)) && + IS_SYMOP (IC_RIGHT (cdp->diCode)) && + bitVectBitsInCommon (src->outDefs, OP_DEFS (IC_RIGHT (cdp->diCode)))) + return 1; + + /* if we find it in the defSet of this block */ + if (bitVectBitsInCommon (src->defSet, OP_DEFS (cdp->sym))) + return 1; + + /* if in the outdef we find a definition other than this one */ + /* to do this we make a copy of the out definitions and turn */ + /* this one off then check if there are other definitions */ + bitVectUnSetBit (outs = bitVectCopy (src->outDefs), + cdp->diCode->key); + if (bitVectBitsInCommon (outs, OP_DEFS (cdp->sym))) + { + freeBitVect (outs); + return 1; + } + + freeBitVect (outs); + + /* if the operands of this one was changed in the block */ + /* then delete it */ + if (cdp->diCode && + ((IS_SYMOP (IC_LEFT (cdp->diCode)) && + bitVectBitsInCommon (src->defSet, OP_DEFS (IC_LEFT (cdp->diCode)))) || + (IS_SYMOP (IC_RIGHT (cdp->diCode)) && + bitVectBitsInCommon (src->defSet, OP_DEFS (IC_RIGHT (cdp->diCode)))))) + return 1; + + /* kill if cseBBlock() found a case we missed here */ + if (isinSetWith(src->killedExprs, cdp, isCseDefEqual)) + return 1; + + return 0; +} + +/*-----------------------------------------------------------------*/ +/* mergeInExprs - copy the in expression if it dominates */ +/*-----------------------------------------------------------------*/ +DEFSETFUNC (mergeInExprs) +{ + eBBlock *ebp = item; + V_ARG (eBBlock *, dest); + V_ARG (int *, firstTime); + + dest->killedExprs = unionSets (dest->killedExprs, ebp->killedExprs, THROW_DEST); + + /* if in the dominator list then */ + if (bitVectBitValue (dest->domVect, ebp->bbnum) && dest != ebp) + { + /* if already present then intersect */ + if (!dest->inExprs && *firstTime) + { + dest->inExprs = setFromSet (ebp->outExprs); + /* copy the pointer set from the dominator */ + dest->inPtrsSet = bitVectCopy (ebp->ptrsSet); + dest->ndompset = bitVectCopy (ebp->ndompset); + } + else + { + dest->inExprs = intersectSets (dest->inExprs, + ebp->outExprs, + THROW_DEST); + dest->inPtrsSet = bitVectInplaceUnion (dest->inPtrsSet, ebp->ptrsSet); + dest->ndompset = bitVectInplaceUnion (dest->ndompset, ebp->ndompset); + } + } + else + { + //if (dest != ebp) + // dest->inExprs = intersectSets (dest->inExprs, ebp->outExprs, THROW_DEST); + + /* delete only if killed in this block*/ + deleteItemIf (&dest->inExprs, ifKilledInBlock, ebp); + /* union the ndompset with pointers set in this block */ + dest->ndompset = bitVectInplaceUnion (dest->ndompset, ebp->ptrsSet); + } + *firstTime = 0; + + return 0; +} + + +/*-----------------------------------------------------------------*/ +/* mergeInDefs - merge in incoming definitions */ +/*-----------------------------------------------------------------*/ +DEFSETFUNC (mergeInDefs) +{ + eBBlock *ebp = item; + V_ARG (eBBlock *, dest); + V_ARG (int *, firstTime); + + /* the in definition is the union of the out */ + /* of all blocks that come to this block */ + if (!dest->inDefs && *firstTime) + dest->inDefs = bitVectCopy (ebp->outDefs); + else + dest->inDefs = bitVectInplaceUnion (dest->inDefs, ebp->outDefs); + + *firstTime = 0; + + return 0; +} + + +/*------------------------------------------------------------------*/ +/* computeDataFlow - does computations for data flow accross blocks */ +/*------------------------------------------------------------------*/ +void +computeDataFlow (ebbIndex * ebbi) +{ + eBBlock ** ebbs = ebbi->dfOrder; + int count = ebbi->count; + int i; + int change; + + for (i = 0; i < count; i++) + deleteSet (&ebbs[i]->killedExprs); + + do + { + change = 0; + + /* for all blocks */ + for (i = 0; i < count; i++) + { + set *pred; + set *oldOutExprs = NULL; + set *oldKilledExprs = NULL; + bitVect *oldOutDefs = NULL; + int firstTime; + eBBlock *pBlock; + + /* if this is the entry block then continue */ + /* since entry block can never have any inExprs */ + if (ebbs[i]->noPath) + continue; + + /* get blocks that can come to this block */ + pred = edgesTo (ebbs[i]); + + /* make a copy of the outExpressions and outDefs : to be */ + /* used for iteration */ + if (optimize.global_cse) + { + oldOutExprs = setFromSet (ebbs[i]->outExprs); + oldKilledExprs = setFromSet (ebbs[i]->killedExprs); + } + oldOutDefs = bitVectCopy (ebbs[i]->outDefs); + freeBitVect(ebbs[i]->inDefs); ebbs[i]->inDefs = NULL; + + /* indefitions are easy just merge them by union */ + /* these are the definitions that can possibly */ + /* reach this block */ + firstTime = 1; + applyToSet (pred, mergeInDefs, ebbs[i], &firstTime); + + /* if none of the edges coming to this block */ + /* dominate this block then add the immediate dominator */ + /* of this block to the list of predecessors */ + for (pBlock = setFirstItem (pred); pBlock; + pBlock = setNextItem (pred)) + { + if (bitVectBitValue (ebbs[i]->domVect, pBlock->bbnum)) + break; + } + + /* get the immediate dominator and put it there */ + if (!pBlock) + { + eBBlock *idom = immedDom (ebbi, ebbs[i]); + if (idom) + addSetHead (&pred, idom); + } + + /* figure out the incoming expressions */ + /* this is a little more complex */ + //setToNull ((void *) &ebbs[i]->inExprs); + deleteSet (&ebbs[i]->inExprs); + if (optimize.global_cse) + { + firstTime = 1; + applyToSet (pred, mergeInExprs, ebbs[i], &firstTime); + } + setToNull ((void *) &pred); + + /* do cse with computeOnly flag set to TRUE */ + /* this is by far the quickest way of computing */ + cseBBlock (ebbs[i], TRUE, ebbi); + + /* if it change we will need to iterate */ + if (optimize.global_cse) + { + change += !isSetsEqualWith (ebbs[i]->outExprs, oldOutExprs, isCseDefEqual); + change += !isSetsEqualWith (ebbs[i]->killedExprs, oldKilledExprs, isCseDefEqual); + } + change += !bitVectEqual (ebbs[i]->outDefs, oldOutDefs); + freeBitVect (oldOutDefs); + deleteSet (&oldOutExprs); + deleteSet (&oldKilledExprs); + } + } + while (change); /* iterate till no change */ + + return; +} + +/*-----------------------------------------------------------------*/ +/* usedBetweenPoints - used between start & end */ +/*-----------------------------------------------------------------*/ +int +usedBetweenPoints (operand * op, iCode * start, iCode * end) +{ + iCode *lic = start; + + for (; lic != end; lic = lic->next) + { + /* if the operand is a parameter */ + /* then check for calls and return */ + /* true if there is a call */ + if (IS_PARM (op) && + (lic->op == CALL || lic->op == PCALL)) + { + value *args; + if (lic->op == CALL) + { + args = FUNC_ARGS (OP_SYMBOL (IC_LEFT (lic))->type); + } + else + { + args = FUNC_ARGS (OP_SYMBOL (IC_LEFT (lic))->type->next); + } + if (isParameterToCall (args, op)) + return 1; + } + + if (SKIP_IC2 (lic)) + continue; + + /* if ifx then check the condition */ + if (lic->op == IFX && + IC_COND (lic)->key == op->key) + return 1; + + if (lic->op == JUMPTABLE && + IC_JTCOND (lic)->key == op->key) + return 1; + + if (IC_RIGHT (lic) && + IC_RIGHT (lic)->key == op->key) + return 1; + + if (IC_LEFT (lic) && + IC_LEFT (lic)->key == op->key) + return 1; + + /* for a pointer assignment usage */ + if (POINTER_SET (lic) && + op->key == IC_RESULT (lic)->key) + return 1; + else if (IC_RESULT (lic) && op->key == IC_RESULT (lic)->key) + return 0; + } + + return 0; +} + + +/*------------------------------------------------------------------*/ +/* usedInRemaining - returns point of usage for an operand if found */ +/*------------------------------------------------------------------*/ +iCode * +usedInRemaining (operand * op, iCode * ic) +{ + iCode *lic = ic; + + if (!IS_SYMOP (op)) + return 0; + + for (; lic; lic = lic->next) + { + /* if the operand is a parameter */ + /* then check for calls and return */ + /* true if there is a call */ + /* if this is a global variable then + return true */ + if (lic->op == CALL || lic->op == PCALL) + { + value *args; + if (lic->op == CALL) + args=FUNC_ARGS (operandType (IC_LEFT (lic))); + else + args=FUNC_ARGS (operandType (IC_LEFT (lic))->next); + if ((IS_PARM (op) && isParameterToCall (args, op)) || + isOperandGlobal (op)) + return lic; + } + + if (ic->op == SEND && + isOperandEqual (IC_LEFT (lic), op)) + return lic; + + if (SKIP_IC1 (lic)) + continue; + + /* if ifx then check the condition */ + if (lic->op == IFX && isOperandEqual (IC_COND (lic), op)) + return lic; + + if (lic->op == JUMPTABLE && isOperandEqual (IC_JTCOND (lic), op)) + return lic; + + if (IC_RIGHT (lic) && isOperandEqual (IC_RIGHT (lic), op)) + return lic; + + if (IC_LEFT (lic) && + isOperandEqual (IC_LEFT (lic), op)) + return lic; + + /* for a pointer assignment usage */ + if (POINTER_SET (lic) && isOperandEqual (op, IC_RESULT (lic))) + return lic; + else if (IC_RESULT (lic) && isOperandEqual (IC_RESULT (lic), op)) + return NULL; + } + + return NULL; +} + + +/*-------------------------------------------------------------------*/ +/* isDefAlive - will return true if definiton reaches a block & used */ +/*-------------------------------------------------------------------*/ +DEFSETFUNC (isDefAlive) +{ + eBBlock *ebp = item; + V_ARG (iCode *, diCode); + + if (ebp->visited) + return 0; + + ebp->visited = 1; + + /* if this definition is used in the block */ + if (bitVectBitValue (ebp->usesDefs, diCode->key)) + return 1; + + return applyToSet (ebp->succList, isDefAlive, diCode); +} |
