gbdk-releases/sdcc/src/SDCCcse.c

1731 lines
48 KiB
C
Raw Permalink Normal View History

2015-01-10 16:25:06 +01:00
/*-------------------------------------------------------------------------
SDCCcse.c - source file for Common Subexpressions and other utility
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.
2015-01-10 16:25:09 +01:00
2015-01-10 16:25:06 +01:00
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.
2015-01-10 16:25:09 +01:00
2015-01-10 16:25:06 +01:00
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.
2015-01-10 16:25:09 +01:00
2015-01-10 16:25:06 +01:00
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
2015-01-10 16:25:09 +01:00
what you give them. Help stamp out software-hoarding!
2015-01-10 16:25:06 +01:00
-------------------------------------------------------------------------*/
#include "common.h"
2015-01-10 16:25:09 +01:00
#include "newalloc.h"
2015-01-10 16:25:06 +01:00
/*-----------------------------------------------------------------*/
/* newCseDef - new cseDef */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
cseDef *
newCseDef (operand * sym, iCode * ic)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
cseDef *cdp;
assert (sym);
cdp = Safe_alloc (sizeof (cseDef));
cdp->sym = sym;
cdp->diCode = ic;
cdp->key = sym->key;
return cdp;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* int isCseDefEqual - two definitions are equal */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
int
isCseDefEqual (void *vsrc, void *vdest)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
cseDef *src = vsrc;
cseDef *dest = vdest;
if (src == dest)
return 1;
return (src->key == dest->key &&
src->diCode == dest->diCode);
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* pcseDef - in the cseDef */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
int
pcseDef (void *item, va_list ap)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
cseDef *cdp = item;
iCodeTable *icTab;
(void) ap;
if (!cdp->sym)
fprintf (stdout, "**null op**");
printOperand (cdp->sym, stdout);
icTab = getTableEntry (cdp->diCode->op);
icTab->iCodePrint (stdout, cdp->diCode, icTab->printName);
return 1;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* replaceAllSymBySym - replaces all operands by operand in an */
/* instruction chain */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
void
replaceAllSymBySym (iCode * ic, operand * from, operand * to, bitVect ** ndpset)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
iCode *lic;
for (lic = ic; lic; lic = lic->next)
{
int siaddr;
/* do the special cases first */
if (lic->op == IFX)
{
if (IS_SYMOP (to) &&
IC_COND (lic)->key == from->key)
{
bitVectUnSetBit (OP_USES (from), lic->key);
OP_USES (to) = bitVectSetBit (OP_USES (to), lic->key);
siaddr = IC_COND (lic)->isaddr;
IC_COND (lic) = operandFromOperand (to);
IC_COND (lic)->isaddr = siaddr;
}
continue;
2015-01-10 16:25:07 +01:00
}
2015-01-10 16:25:09 +01:00
if (lic->op == JUMPTABLE)
{
if (IS_SYMOP (to) &&
IC_JTCOND (lic)->key == from->key)
{
bitVectUnSetBit (OP_USES (from), lic->key);
OP_USES (to) = bitVectSetBit (OP_USES (to), lic->key);
siaddr = IC_COND (lic)->isaddr;
IC_JTCOND (lic) = operandFromOperand (to);
IC_JTCOND (lic)->isaddr = siaddr;
}
continue;
2015-01-10 16:25:07 +01:00
}
2015-01-10 16:25:09 +01:00
if (IC_RESULT (lic) && IC_RESULT (lic)->key == from->key)
{
/* maintain du chains */
if (POINTER_SET (lic))
{
bitVectUnSetBit (OP_USES (from), lic->key);
OP_USES (to) = bitVectSetBit (OP_USES (to), lic->key);
/* also check if the "from" was in the non-dominating
pointer sets and replace it with "to" in the bitVector */
if (bitVectBitValue (*ndpset, from->key))
{
bitVectUnSetBit (*ndpset, from->key);
bitVectSetBit (*ndpset, to->key);
2015-01-10 16:25:08 +01:00
}
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
else
{
bitVectUnSetBit (OP_DEFS (from), lic->key);
OP_DEFS (to) = bitVectSetBit (OP_DEFS (to), lic->key);
}
siaddr = IC_RESULT (lic)->isaddr;
IC_RESULT (lic) = operandFromOperand (to);
IC_RESULT (lic)->isaddr = siaddr;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
if (IS_SYMOP (to) &&
IC_RIGHT (lic) && IC_RIGHT (lic)->key == from->key)
{
bitVectUnSetBit (OP_USES (from), lic->key);
OP_USES (to) = bitVectSetBit (OP_USES (to), lic->key);
siaddr = IC_RIGHT (lic)->isaddr;
IC_RIGHT (lic) = operandFromOperand (to);
IC_RIGHT (lic)->isaddr = siaddr;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
if (IS_SYMOP (to) &&
IC_LEFT (lic) && IC_LEFT (lic)->key == from->key)
{
bitVectUnSetBit (OP_USES (from), lic->key);
OP_USES (to) = bitVectSetBit (OP_USES (to), lic->key);
siaddr = IC_LEFT (lic)->isaddr;
IC_LEFT (lic) = operandFromOperand (to);
IC_LEFT (lic)->isaddr = siaddr;
}
2015-01-10 16:25:06 +01:00
}
}
/*-----------------------------------------------------------------*/
/* iCodeKeyIs - if the icode keys match then return 1 */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
DEFSETFUNC (iCodeKeyIs)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
cseDef *cdp = item;
V_ARG (int, key);
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (cdp->diCode->key == key)
return 1;
else
return 0;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* removeFromInExprs - removes an icode from inexpressions */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
DEFSETFUNC (removeFromInExprs)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
eBBlock *ebp = item;
V_ARG (iCode *, ic);
V_ARG (operand *, from);
V_ARG (operand *, to);
V_ARG (eBBlock *, cbp);
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (ebp->visited)
return 0;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
ebp->visited = 1;
deleteItemIf (&ebp->inExprs, iCodeKeyIs, ic->key);
if (ebp != cbp && !bitVectBitValue (cbp->domVect, ebp->bbnum))
replaceAllSymBySym (ebp->sch, from, to, &ebp->ndompset);
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
applyToSet (ebp->succList, removeFromInExprs, ic, from, to, cbp);
return 0;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* isGlobalInNearSpace - return TRUE if valriable is a globalin data */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
static bool
isGlobalInNearSpace (operand * op)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
sym_link *type = getSpec (operandType (op));
/* this is 8051 specific: optimization
suggested by Jean-Louis VERN, with 8051s we have no
advantage of putting variables in near space into
registers */
if (isOperandGlobal (op) && !IN_FARSPACE (SPEC_OCLS (type)) &&
IN_DIRSPACE (SPEC_OCLS (type)))
return TRUE;
else
return FALSE;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* findCheaperOp - cseBBlock support routine, will check to see if */
/* we have a operand previously defined */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
DEFSETFUNC (findCheaperOp)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
cseDef *cdp = item;
V_ARG (operand *, cop);
V_ARG (operand **, opp);
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
/* if we have already found it */
if (*opp)
return 1;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
/* not found it yet check if this is the one */
/* and this is not the defining one */
if (cop->key == cdp->key)
{
/* do a special check this will help in */
/* constant propagation & dead code elim */
/* for assignments only */
if (cdp->diCode->op == '=') {
/* if the result is volatile then return result */
if (IS_OP_VOLATILE (IC_RESULT (cdp->diCode)))
*opp = IC_RESULT (cdp->diCode);
else
/* if this is a straight assignment and
left is a temp then prefer the temporary to the
true symbol */
if (!POINTER_SET (cdp->diCode) &&
IS_ITEMP (IC_RESULT (cdp->diCode)) &&
IS_TRUE_SYMOP (IC_RIGHT (cdp->diCode)))
*opp = IC_RESULT (cdp->diCode);
else {
/* if straight assignement && and both
are temps then prefer the one that
will not need extra space to spil, also
take into consideration if right side
an induction variable
*/
if (!POINTER_SET (cdp->diCode) &&
IS_ITEMP (IC_RESULT (cdp->diCode)) &&
IS_ITEMP (IC_RIGHT (cdp->diCode)) &&
!OP_SYMBOL (IC_RIGHT (cdp->diCode))->isind &&
((!SPIL_LOC (IC_RIGHT (cdp->diCode)) &&
SPIL_LOC (IC_RESULT (cdp->diCode))) ||
(SPIL_LOC (IC_RESULT (cdp->diCode)) &&
SPIL_LOC (IC_RESULT (cdp->diCode)) ==
SPIL_LOC (IC_RIGHT (cdp->diCode)))))
*opp = IC_RESULT (cdp->diCode);
2015-01-10 16:25:06 +01:00
else
2015-01-10 16:25:09 +01:00
*opp = IC_RIGHT (cdp->diCode);
}
}
else
*opp = IC_RESULT (cdp->diCode);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* if this is an assign to a temp. then check
if the right side is this then return this */
if (IS_TRUE_SYMOP (cop) &&
cdp->diCode->op == '=' &&
!POINTER_SET (cdp->diCode) &&
cop->key == IC_RIGHT (cdp->diCode)->key &&
!isGlobalInNearSpace (IC_RIGHT (cdp->diCode)) &&
IS_ITEMP (IC_RESULT (cdp->diCode)))
*opp = IC_RESULT (cdp->diCode);
if ((*opp) &&
(isOperandLiteral(*opp) ||
(SPEC_USIGN(operandType (cop))==SPEC_USIGN(operandType (*opp)) &&
(SPEC_LONG(operandType (cop))==SPEC_LONG(operandType (*opp))))))
{
if ((isGlobalInNearSpace (cop) &&
!isOperandLiteral (*opp)) ||
isOperandVolatile (*opp, FALSE)
)
{
*opp = NULL;
return 0;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
if (cop->key == (*opp)->key)
{
*opp = NULL;
return 0;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
if ((*opp)->isaddr != cop->isaddr && IS_ITEMP (cop))
{
*opp = operandFromOperand (*opp);
(*opp)->isaddr = cop->isaddr;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
return 1;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
*opp=NULL;
return 0;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* findPointerSet - finds the right side of a pointer set op */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
DEFSETFUNC (findPointerSet)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
cseDef *cdp = item;
V_ARG (operand *, op);
V_ARG (operand **, opp);
V_ARG (operand *, rop);
if (POINTER_SET (cdp->diCode) &&
IC_RESULT (cdp->diCode)->key == op->key &&
!isOperandVolatile (IC_RESULT (cdp->diCode), TRUE) &&
!isOperandVolatile (IC_RIGHT (cdp->diCode), TRUE) &&
getSize (operandType (IC_RIGHT (cdp->diCode))) ==
getSize (operandType (rop)))
{
*opp = IC_RIGHT (cdp->diCode);
return 1;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
return 0;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* findPrevIc - cseBBlock support function will return the iCode */
/* which matches the current one */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
DEFSETFUNC (findPrevIc)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
cseDef *cdp = item;
V_ARG (iCode *, ic);
V_ARG (iCode **, icp);
/* if already found */
if (*icp)
return 1;
/* if the iCodes are the same */
if (isiCodeEqual (ic, cdp->diCode) &&
isOperandEqual (cdp->sym, IC_RESULT (cdp->diCode)))
{
*icp = cdp->diCode;
return 1;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* if iCodes are not the same */
/* see the operands maybe interchanged */
if (ic->op == cdp->diCode->op &&
(ic->op == '+' || ic->op == '*') &&
isOperandEqual (IC_LEFT (ic), IC_RIGHT (cdp->diCode)) &&
isOperandEqual (IC_RIGHT (ic), IC_LEFT (cdp->diCode)))
{
*icp = cdp->diCode;
return 1;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
return 0;
}
/*-------------------------------------------------------------------*/
/* ifAssignedFromGlobal - if definition is an assignment from global */
/*-------------------------------------------------------------------*/
DEFSETFUNC (ifAssignedFromGlobal)
{
cseDef *cdp = item;
iCode *dic=cdp->diCode;
if (dic->op=='=' && isOperandGlobal(IC_RIGHT(dic))) {
return 1;
}
return 0;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* ifDefGlobal - if definition is global */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
DEFSETFUNC (ifDefGlobal)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
cseDef *cdp = item;
return (isOperandGlobal (cdp->sym));
}
/*-----------------------------------------------------------------*/
/* ifAnyGetPointer - if get pointer icode */
/*-----------------------------------------------------------------*/
DEFSETFUNC (ifAnyGetPointer)
{
cseDef *cdp = item;
if (cdp->diCode && POINTER_GET (cdp->diCode))
return 1;
return 0;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* ifOperandsHave - if any of the operand are the same as this */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
DEFSETFUNC (ifOperandsHave)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
cseDef *cdp = item;
V_ARG (operand *, op);
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (IC_LEFT (cdp->diCode) &&
IS_SYMOP (IC_LEFT (cdp->diCode)) &&
IC_LEFT (cdp->diCode)->key == op->key)
return 1;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (IC_RIGHT (cdp->diCode) &&
IS_SYMOP (IC_RIGHT (cdp->diCode)) &&
IC_RIGHT (cdp->diCode)->key == op->key)
return 1;
/* or if any of the operands are volatile */
if (IC_LEFT (cdp->diCode) &&
IS_OP_VOLATILE (IC_LEFT (cdp->diCode)))
return 1;
if (IC_RIGHT (cdp->diCode) &&
IS_OP_VOLATILE (IC_RIGHT (cdp->diCode)))
return 1;
if (IC_RESULT (cdp->diCode) &&
IS_OP_VOLATILE (IC_RESULT (cdp->diCode)))
return 1;
return 0;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* ifDefSymIs - if a definition is found in the set */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
int
ifDefSymIs (set * cseSet, operand * sym)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
cseDef *loop;
set *sl;
if (!sym || !IS_SYMOP (sym))
2015-01-10 16:25:06 +01:00
return 0;
2015-01-10 16:25:09 +01:00
for (sl = cseSet; sl; sl = sl->next)
{
loop = sl->item;
if (loop->sym->key == sym->key)
return 1;
}
return 0;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* ifDefSymIsX - will return 1 if the symbols match */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
DEFSETFUNC (ifDefSymIsX)
{
cseDef *cdp = item;
V_ARG (operand *, op);
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (op && cdp->sym)
return cdp->sym->key == op->key;
else
return (isOperandEqual (cdp->sym, op));
}
2015-01-10 16:25:06 +01:00
/*-----------------------------------------------------------------*/
/* ifDiCodeIs - returns truw if diCode is same */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
int
ifDiCodeIs (set * cseSet, iCode * ic)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
cseDef *loop;
set *sl;
if (!ic)
2015-01-10 16:25:06 +01:00
return 0;
2015-01-10 16:25:09 +01:00
for (sl = cseSet; sl; sl = sl->next)
{
loop = sl->item;
if (loop->diCode == ic)
return 1;
}
return 0;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* ifPointerGet - returns true if the icode is pointer get sym */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
DEFSETFUNC (ifPointerGet)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
cseDef *cdp = item;
V_ARG (operand *, op);
iCode *dic = cdp->diCode;
operand *left = IC_LEFT (cdp->diCode);
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (POINTER_GET (dic) && left->key == op->key)
return 1;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
return 0;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* ifPointerSet - returns true if the icode is pointer set sym */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
DEFSETFUNC (ifPointerSet)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
cseDef *cdp = item;
V_ARG (operand *, op);
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (POINTER_SET (cdp->diCode) &&
IC_RESULT (cdp->diCode)->key == op->key)
return 1;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
return 0;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* ifDiCodeIsX - will return 1 if the symbols match */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
DEFSETFUNC (ifDiCodeIsX)
{
cseDef *cdp = item;
V_ARG (iCode *, ic);
return cdp->diCode == ic;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* algebraicOpts - does some algebraic optimizations */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
void
algebraicOpts (iCode * ic)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
/* we don't deal with the following iCodes
here */
if (ic->op == IFX ||
ic->op == IPUSH ||
ic->op == IPOP ||
ic->op == CALL ||
ic->op == PCALL ||
ic->op == RETURN ||
POINTER_GET (ic))
return;
/* if both operands present & ! IFX */
/* then if they are both literal we */
/* perform the operation right now */
if (IC_RESULT (ic) &&
IC_RIGHT (ic) &&
IC_LEFT (ic) &&
IS_OP_LITERAL (IC_LEFT (ic)) &&
IS_OP_LITERAL (IC_RIGHT (ic)))
{
IC_RIGHT (ic) = operandOperation (IC_LEFT (ic),
IC_RIGHT (ic),
ic->op,
operandType (IC_RESULT (ic)));
ic->op = '=';
IC_LEFT (ic) = NULL;
SET_RESULT_RIGHT (ic);
return;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* if not ifx & only one operand present */
if (IC_RESULT (ic) &&
IC_LEFT (ic) &&
IS_OP_LITERAL (IC_LEFT (ic)) &&
!IC_RIGHT (ic))
{
IC_RIGHT (ic) = operandOperation (IC_LEFT (ic),
IC_RIGHT (ic),
ic->op,
operandType (IC_RESULT (ic)));
ic->op = '=';
IC_LEFT (ic) = NULL;
SET_RESULT_RIGHT (ic);
return;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* a special case : or in short a kludgy solution will think
about a better solution over a glass of wine someday */
if (ic->op == GET_VALUE_AT_ADDRESS)
{
if (IS_ITEMP (IC_RESULT (ic)) &&
IS_TRUE_SYMOP (IC_LEFT (ic)))
{
ic->op = '=';
IC_RIGHT (ic) = operandFromOperand (IC_LEFT (ic));
IC_RIGHT (ic)->isaddr = 0;
IC_LEFT (ic) = NULL;
IC_RESULT (ic) = operandFromOperand (IC_RESULT (ic));
IC_RESULT (ic)->isaddr = 0;
setOperandType (IC_RESULT (ic), operandType (IC_RIGHT (ic)));
return;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
if (IS_ITEMP (IC_LEFT (ic)) &&
IS_ITEMP (IC_RESULT (ic)) &&
/* !OP_SYMBOL(IC_RESULT(ic))->isreqv && */
/* !OP_SYMBOL(IC_LEFT(ic))->isreqv && */
!IC_LEFT (ic)->isaddr)
{
ic->op = '=';
IC_RIGHT (ic) = operandFromOperand (IC_LEFT (ic));
IC_RIGHT (ic)->isaddr = 0;
IC_RESULT (ic) = operandFromOperand (IC_RESULT (ic));
IC_RESULT (ic)->isaddr = 0;
IC_LEFT (ic) = NULL;
return;
2015-01-10 16:25:06 +01:00
}
}
2015-01-10 16:25:09 +01:00
/* depending on the operation */
switch (ic->op)
{
case '+':
/* if adding the same thing change to left shift by 1 */
if (IC_LEFT (ic)->key == IC_RIGHT (ic)->key &&
!IS_FLOAT (operandType (IC_RESULT (ic))))
{
ic->op = LEFT_OP;
IC_RIGHT (ic) = operandFromLit (1);
return;
}
/* if addition then check if one of them is a zero */
/* if yes turn it into assignmnt */
if (IS_OP_LITERAL (IC_LEFT (ic)) &&
operandLitValue (IC_LEFT (ic)) == 0.0)
{
ic->op = '=';
IC_LEFT (ic) = NULL;
SET_ISADDR (IC_RESULT (ic), 0);
SET_ISADDR (IC_RIGHT (ic), 0);
return;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
if (IS_OP_LITERAL (IC_RIGHT (ic)) &&
operandLitValue (IC_RIGHT (ic)) == 0.0)
{
ic->op = '=';
IC_RIGHT (ic) = IC_LEFT (ic);
IC_LEFT (ic) = 0;
SET_ISADDR (IC_RIGHT (ic), 0);
SET_ISADDR (IC_RESULT (ic), 0);
return;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
break;
case '-':
/* if subtracting the the same thing then zero */
if (IC_LEFT (ic)->key == IC_RIGHT (ic)->key)
{
ic->op = '=';
IC_RIGHT (ic) = operandFromLit (0);
IC_LEFT (ic) = NULL;
IC_RESULT (ic) = operandFromOperand (IC_RESULT (ic));
IC_RESULT (ic)->isaddr = 0;
return;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* if subtraction then check if one of the operand */
/* is zero then depending on which operand change */
/* to assignment or unary minus */
if (IS_OP_LITERAL (IC_RIGHT (ic)) &&
operandLitValue (IC_RIGHT (ic)) == 0.0)
{
/* right size zero change to assignment */
ic->op = '=';
IC_RIGHT (ic) = IC_LEFT (ic);
IC_LEFT (ic) = NULL;
SET_ISADDR (IC_RIGHT (ic), 0);
SET_ISADDR (IC_RESULT (ic), 0);
return;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
if (IS_OP_LITERAL (IC_LEFT (ic)) &&
operandLitValue (IC_LEFT (ic)) == 0.0)
{
/* left zero turn into an unary minus */
ic->op = UNARYMINUS;
IC_LEFT (ic) = IC_RIGHT (ic);
IC_RIGHT (ic) = NULL;
return;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
break;
/* if multiplication then check if either of */
/* them is zero then the result is zero */
/* if either of them is one then result is */
/* the other one */
case '*':
if (IS_OP_LITERAL (IC_LEFT (ic)))
{
if (operandLitValue (IC_LEFT (ic)) == 0.0)
{
ic->op = '=';
IC_RIGHT (ic) = IC_LEFT (ic);
IC_LEFT (ic) = NULL;
SET_RESULT_RIGHT (ic);
return;
}
if (operandLitValue (IC_LEFT (ic)) == 1.0)
{
ic->op = '=';
IC_LEFT (ic) = NULL;
SET_RESULT_RIGHT (ic);
return;
2015-01-10 16:25:06 +01:00
}
}
2015-01-10 16:25:09 +01:00
if (IS_OP_LITERAL (IC_RIGHT (ic)))
{
if (operandLitValue (IC_RIGHT (ic)) == 0.0)
{
ic->op = '=';
IC_LEFT (ic) = NULL;
SET_RESULT_RIGHT (ic);
return;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
if (operandLitValue (IC_RIGHT (ic)) == 1.0)
{
ic->op = '=';
IC_RIGHT (ic) = IC_LEFT (ic);
IC_LEFT (ic) = NULL;
SET_RESULT_RIGHT (ic);
return;
2015-01-10 16:25:06 +01:00
}
}
2015-01-10 16:25:09 +01:00
break;
2015-01-10 16:25:06 +01:00
case '/':
2015-01-10 16:25:09 +01:00
/* if division by self then 1 */
if (IC_LEFT (ic)->key == IC_RIGHT (ic)->key)
{
ic->op = '=';
IC_RIGHT (ic) = operandFromLit (1);
IC_LEFT (ic) = NULL;
IC_RESULT (ic) = operandFromOperand (IC_RESULT (ic));
IC_RESULT (ic)->isaddr = 0;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* if this is a division then check if right */
/* is one then change it to an assignment */
if (IS_OP_LITERAL (IC_RIGHT (ic)) &&
operandLitValue (IC_RIGHT (ic)) == 1.0)
{
ic->op = '=';
IC_RIGHT (ic) = IC_LEFT (ic);
IC_LEFT (ic) = NULL;
SET_RESULT_RIGHT (ic);
return;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
break;
/* if both are the same for an comparison operators */
case EQ_OP:
case LE_OP:
case GE_OP:
if (isOperandEqual (IC_LEFT (ic), IC_RIGHT (ic)))
{
ic->op = '=';
IC_RIGHT (ic) = operandFromLit (1);
IC_LEFT (ic) = NULL;
SET_RESULT_RIGHT (ic);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
break;
case NE_OP:
case '>':
case '<':
if (isOperandEqual (IC_LEFT (ic), IC_RIGHT (ic)))
{
ic->op = '=';
IC_RIGHT (ic) = operandFromLit (0);
IC_LEFT (ic) = NULL;
SET_RESULT_RIGHT (ic);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
break;
case CAST:
{
sym_link *otype = operandType(IC_RIGHT(ic));
sym_link *ctype = operandType(IC_LEFT(ic));
/* if this is a cast of a literal value */
if (IS_OP_LITERAL (IC_RIGHT (ic)) &&
!(IS_GENPTR(ctype) && (IS_PTR(otype) && !IS_GENPTR(otype)))) {
ic->op = '=';
IC_RIGHT (ic) =
operandFromValue (valCastLiteral (operandType (IC_LEFT (ic)),
operandLitValue (IC_RIGHT (ic))));
IC_LEFT (ic) = NULL;
SET_ISADDR (IC_RESULT (ic), 0);
}
/* if casting to the same */
if (compareType (operandType (IC_RESULT (ic)),
operandType (IC_RIGHT (ic))) == 1) {
ic->op = '=';
IC_LEFT (ic) = NULL;
SET_ISADDR (IC_RESULT (ic), 0);
}
}
break;
case '!':
if (IS_OP_LITERAL (IC_LEFT (ic)))
{
ic->op = '=';
IC_RIGHT (ic) =
(operandLitValue (IC_LEFT (ic)) == 0 ?
operandFromLit (1) : operandFromLit (0));
IC_LEFT (ic) = NULL;
SET_ISADDR (IC_RESULT (ic), 0);
2015-01-10 16:25:06 +01:00
}
}
2015-01-10 16:25:09 +01:00
return;
2015-01-10 16:25:06 +01:00
}
#define OTHERS_PARM(s) (s->_isparm && !s->ismyparm)
/*-----------------------------------------------------------------*/
/* updateSpillLocation - keeps track of register spill location */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
void
updateSpillLocation (iCode * ic, int induction)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
sym_link *setype;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (POINTER_SET (ic))
return;
if (ic->nosupdate)
return;
/* for the form true_symbol := iTempNN */
if (ASSIGN_ITEMP_TO_SYM (ic) &&
!SPIL_LOC (IC_RIGHT (ic))) {
setype = getSpec (operandType (IC_RESULT (ic)));
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (!OP_SYMBOL(IC_RIGHT (ic))->noSpilLoc &&
!IS_VOLATILE (setype) &&
!IN_FARSPACE (SPEC_OCLS (setype)) &&
!OTHERS_PARM (OP_SYMBOL (IC_RESULT (ic))))
SPIL_LOC (IC_RIGHT (ic)) =
IC_RESULT (ic)->operand.symOperand;
}
if (ASSIGN_ITEMP_TO_ITEMP (ic)) {
if (!SPIL_LOC (IC_RIGHT (ic)) &&
!bitVectBitsInCommon (OP_DEFS (IC_RIGHT (ic)), OP_USES (IC_RESULT (ic))) &&
OP_SYMBOL (IC_RESULT (ic))->isreqv) {
setype = getSpec (operandType (IC_RESULT (ic)));
if (!OP_SYMBOL(IC_RIGHT (ic))->noSpilLoc &&
!IS_VOLATILE (setype) &&
!IN_FARSPACE (SPEC_OCLS (setype)) &&
!OTHERS_PARM (OP_SYMBOL (IC_RESULT (ic))))
SPIL_LOC (IC_RIGHT (ic)) =
SPIL_LOC (IC_RESULT (ic));
}
/* special case for inductions */
if (induction &&
OP_SYMBOL(IC_RIGHT(ic))->isreqv &&
!OP_SYMBOL(IC_RESULT (ic))->noSpilLoc &&
!SPIL_LOC(IC_RESULT(ic))) {
SPIL_LOC (IC_RESULT (ic)) = SPIL_LOC (IC_RIGHT (ic));
}
}
}
2015-01-10 16:25:06 +01:00
/*-----------------------------------------------------------------*/
/* setUsesDef - sets the uses def bitvector for a given operand */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
void
setUsesDefs (operand * op, bitVect * bdefs,
bitVect * idefs, bitVect ** oud)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
/* compute the definitions alive at this point */
bitVect *adefs = bitVectUnion (bdefs, idefs);
/* of these definitions find the ones that are */
/* for this operand */
adefs = bitVectIntersect (adefs, OP_DEFS (op));
/* these are the definitions that this operand can use */
op->usesDefs = adefs;
/* the out defs is an union */
*oud = bitVectUnion (*oud, adefs);
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* unsetDefsAndUses - clear this operation for the operands */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
void
unsetDefsAndUses (iCode * ic)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
if (ic->op == JUMPTABLE)
return;
/* take away this definition from the def chain of the */
/* result & take away from use set of the operands */
if (ic->op != IFX)
{
/* turn off def set */
if (IS_SYMOP (IC_RESULT (ic)))
{
if (!POINTER_SET (ic))
bitVectUnSetBit (OP_DEFS (IC_RESULT (ic)), ic->key);
else
bitVectUnSetBit (OP_USES (IC_RESULT (ic)), ic->key);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* turn off the useSet for the operands */
if (IS_SYMOP (IC_LEFT (ic)))
bitVectUnSetBit (OP_USES (IC_LEFT (ic)), ic->key);
if (IS_SYMOP (IC_RIGHT (ic)))
bitVectUnSetBit (OP_USES (IC_RIGHT (ic)), ic->key);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
else
/* must be ifx turn off the use */ if (IS_SYMOP (IC_COND (ic)))
bitVectUnSetBit (OP_USES (IC_COND (ic)), ic->key);
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* ifxOptimize - changes ifx conditions if it can */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
void
ifxOptimize (iCode * ic, set * cseSet,
int computeOnly,
eBBlock * ebb, int *change,
eBBlock ** ebbs, int count)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
operand *pdop;
symbol *label;
/* if the condition can be replaced */
if (!computeOnly)
{
pdop = NULL;
applyToSetFTrue (cseSet, findCheaperOp, IC_COND (ic), &pdop);
if (pdop)
{
IC_COND (ic) = pdop;
(*change)++;
2015-01-10 16:25:06 +01:00
}
}
2015-01-10 16:25:09 +01:00
/* if the conditional is a literal then */
if (IS_OP_LITERAL (IC_COND (ic)))
{
if ((operandLitValue (IC_COND (ic)) != 0.0) && IC_TRUE (ic))
{
/* change to a goto */
ic->op = GOTO;
IC_LABEL (ic) = IC_TRUE (ic);
(*change)++;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
else
{
if (!operandLitValue (IC_COND (ic)) && IC_FALSE (ic))
{
ic->op = GOTO;
IC_LABEL (ic) = IC_FALSE (ic);
(*change)++;
}
else
{
/* then kill this if condition */
remiCodeFromeBBlock (ebb, ic);
}
}
/* now we need to recompute the control flow */
/* since the control flow has changed */
/* this is very expensive but it does not happen */
/* too often, if it does happen then the user pays */
/* the price */
computeControlFlow (ebbs, count, 1);
if (!options.lessPedantic) {
werror (W_CONTROL_FLOW, ic->filename, ic->lineno);
}
return;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* if there is only one successor and that successor
is the same one we are conditionally going to then
we can remove this conditional statement */
label = (IC_TRUE (ic) ? IC_TRUE (ic) : IC_FALSE (ic));
if (elementsInSet (ebb->succList) == 1 &&
isinSet (ebb->succList, eBBWithEntryLabel (ebbs, label, count)))
{
remiCodeFromeBBlock (ebb, ic);
computeControlFlow (ebbs, count, 1);
if (!options.lessPedantic) {
werror (W_CONTROL_FLOW, ic->filename, ic->lineno);
}
return;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* if it remains an IFX the update the use Set */
OP_USES (IC_COND (ic)) = bitVectSetBit (OP_USES (IC_COND (ic)), ic->key);
setUsesDefs (IC_COND (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs);
return;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* diCodeForSym - finds the definiting instruction for a symbol */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
DEFSETFUNC (diCodeForSym)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
cseDef *cdp = item;
V_ARG (operand *, sym);
V_ARG (iCode **, dic);
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
/* if already found */
if (*dic)
return 0;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
/* if not if this is the defining iCode */
if (sym->key == cdp->key)
{
*dic = cdp->diCode;
return 1;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
return 0;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* constFold - does some constant folding */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
int
constFold (iCode * ic, set * cseSet)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
iCode *dic = NULL;
iCode *ldic = NULL;
/* this routine will change
a = b + 10;
c = a + 10;
to
c = b + 20; */
/* deal with only + & - */
if (ic->op != '+' &&
ic->op != '-')
return 0;
/* this check is a hueristic to prevent live ranges
from becoming too long */
if (IS_PTR (operandType (IC_RESULT (ic))))
return 0;
/* check if operation with a literal */
if (!IS_OP_LITERAL (IC_RIGHT (ic)))
return 0;
/* check if we can find a definition for the
right hand side */
if (!(applyToSet (cseSet, diCodeForSym, IC_LEFT (ic), &dic)))
return 0;
/* check that this is also a +/- */
if (dic->op != '+' && dic->op != '-')
return 0;
/* with a literal */
if (!IS_OP_LITERAL (IC_RIGHT (dic)))
return 0;
/* find the definition of the left operand
of dic.then check if this defined with a
get_pointer return 0 if the pointer size is
less than 2 (MCS51 specific) */
if (!(applyToSet (cseSet, diCodeForSym, IC_LEFT (dic), &ldic)))
return 0;
if (POINTER_GET (ldic) && getSize (operandType (IC_LEFT (ldic))) <= 1)
return 0;
/* it is if the operations are the same */
/* the literal parts need to be added */
IC_LEFT (ic) = operandFromOperand (IC_LEFT (dic));
if (ic->op == dic->op)
IC_RIGHT (ic) = operandFromLit (operandLitValue (IC_RIGHT (ic)) +
operandLitValue (IC_RIGHT (dic)));
else
IC_RIGHT (ic) = operandFromLit (operandLitValue (IC_RIGHT (ic)) -
operandLitValue (IC_RIGHT (dic)));
if (IS_ITEMP (IC_RESULT (ic)))
{
SPIL_LOC (IC_RESULT (ic)) = NULL;
OP_SYMBOL(IC_RESULT (ic))->noSpilLoc = 1;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
return 1;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* deleteGetPointers - called when a pointer is passed as parm */
/* will delete from cseSet all get pointers computed from this */
/* pointer. A simple ifOperandsHave is not good enough here */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
static void
deleteGetPointers (set ** cseSet, set ** pss, operand * op, eBBlock * ebb)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
set *compItems = NULL;
cseDef *cdp;
operand *cop;
/* easy return */
if (!*cseSet && !*pss)
return;
/* first find all items computed from this operand .
This done fairly simply go thru the list and find
those that are computed by arthimetic with this
op */
for (cdp = setFirstItem (*cseSet); cdp; cdp = setNextItem (*cseSet))
{
if (IS_ARITHMETIC_OP (cdp->diCode))
{
if (isOperandEqual (IC_LEFT (cdp->diCode), op) ||
isOperandEqual (IC_RIGHT (cdp->diCode), op))
{
/* save it in our list of items */
addSet (&compItems, IC_RESULT (cdp->diCode));
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* also check for those computed from our computed
list . This will take care of situations like
iTemp1 = iTemp0 + 8;
iTemp2 = iTemp1 + 8; */
if (isinSetWith (compItems, (void*)IC_LEFT (cdp->diCode),
(insetwithFunc)isOperandEqual) ||
isinSetWith (compItems, (void*)IC_RIGHT (cdp->diCode),
(insetwithFunc)isOperandEqual))
{
addSet (&compItems, IC_RESULT (cdp->diCode));
2015-01-10 16:25:06 +01:00
}
}
}
2015-01-10 16:25:09 +01:00
/* now delete all pointer gets with this op */
deleteItemIf (cseSet, ifPointerGet, op);
deleteItemIf (pss, ifPointerSet, op);
/* set the bit vector used by dataFlow computation later */
ebb->ptrsSet = bitVectSetBit (ebb->ptrsSet, op->key);
/* now for the computed items */
for (cop = setFirstItem (compItems); cop; cop = setNextItem (compItems))
{
ebb->ptrsSet = bitVectSetBit (ebb->ptrsSet, cop->key);
deleteItemIf (cseSet, ifPointerGet, cop);
deleteItemIf (pss, ifPointerSet, cop);
2015-01-10 16:25:06 +01:00
}
}
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
/* delGetPointerSucc - delete get pointer from inExprs of succ with */
2015-01-10 16:25:06 +01:00
/* dfnum > supplied */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
DEFSETFUNC (delGetPointerSucc)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
eBBlock *ebp = item;
V_ARG (operand *, op);
V_ARG (int, dfnum);
if (ebp->visited)
return 0;
ebp->visited = 1;
if (ebp->dfnum > dfnum)
{
deleteItemIf (&ebp->inExprs, ifPointerGet, op);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
return applyToSet (ebp->succList, delGetPointerSucc, op, dfnum);
}
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:08 +01:00
/*-----------------------------------------------------------------*/
/* fixUpTypes - KLUGE HACK fixup a lowering problem */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
static void
fixUpTypes (iCode * ic)
2015-01-10 16:25:08 +01:00
{
2015-01-10 16:25:09 +01:00
sym_link *t1 = operandType (IC_LEFT (ic)), *t2;
/* if (TARGET_IS_DS390) */
if (options.model == MODEL_FLAT24)
{
/* hack-o-matic! */
return;
}
/* for pointer_gets if the types of result & left r the
same then change it type of result to next */
if (IS_PTR (t1) &&
compareType (t2 = operandType (IC_RESULT (ic)), t1) == 1)
{
setOperandType (IC_RESULT (ic), t2->next);
}
2015-01-10 16:25:08 +01:00
}
2015-01-10 16:25:06 +01:00
/*-----------------------------------------------------------------*/
/* cseBBlock - common subexpression elimination for basic blocks */
/* this is the hackiest kludgiest routine in the whole */
/* system. also the most important, since almost all */
/* data flow related information is computed by it */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
int
cseBBlock (eBBlock * ebb, int computeOnly,
eBBlock ** ebbs, int count)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
set *cseSet;
iCode *ic;
int change = 0;
int i;
set *ptrSetSet = NULL;
/* if this block is not reachable */
if (ebb->noPath)
return change;
/* set of common subexpressions */
cseSet = setFromSet (ebb->inExprs);
/* these will be computed by this routine */
setToNull ((void **) &ebb->outDefs);
setToNull ((void **) &ebb->defSet);
setToNull ((void **) &ebb->usesDefs);
setToNull ((void **) &ebb->ptrsSet);
setToNull ((void **) &ebb->addrOf);
setToNull ((void **) &ebb->ldefs);
ebb->outDefs = bitVectCopy (ebb->inDefs);
bitVectDefault = iCodeKey;
ebb->defSet = newBitVect (iCodeKey);
ebb->usesDefs = newBitVect (iCodeKey);
/* for all the instructions in this block do */
for (ic = ebb->sch; ic; ic = ic->next)
{
iCode *pdic;
operand *pdop;
iCode *defic;
if (SKIP_IC2 (ic))
continue;
/* if this is an assignment from true symbol
to a temp then do pointer post inc/dec optimzation */
if (ic->op == '=' && !POINTER_SET (ic) &&
IS_PTR (operandType (IC_RESULT (ic))))
{
ptrPostIncDecOpt (ic);
2015-01-10 16:25:07 +01:00
}
2015-01-10 16:25:09 +01:00
/* clear the def & use chains for the operands involved */
/* in this operation . since it can change due to opts */
unsetDefsAndUses (ic);
if (ic->op == PCALL || ic->op == CALL || ic->op == RECEIVE)
{
/* add to defSet of the symbol */
OP_DEFS (IC_RESULT (ic)) =
bitVectSetBit (OP_DEFS (IC_RESULT (ic)), ic->key);
/* add to the definition set of this block */
ebb->defSet = bitVectSetBit (ebb->defSet, ic->key);
ebb->ldefs = bitVectSetBit (ebb->ldefs, ic->key);
ebb->outDefs = bitVectCplAnd (ebb->outDefs, OP_DEFS (IC_RESULT (ic)));
setUsesDefs (IC_RESULT (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs);
/* delete global variables from the cseSet
since they can be modified by the function call */
deleteItemIf (&cseSet, ifDefGlobal);
/* and also itemps assigned from globals */
deleteItemIf (&cseSet, ifAssignedFromGlobal);
/* delete all getpointer iCodes from cseSet, this should
be done only for global arrays & pointers but at this
point we don't know if globals, so to be safe do all */
deleteItemIf (&cseSet, ifAnyGetPointer);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* for pcall & ipush we need to add to the useSet */
if ((ic->op == PCALL ||
ic->op == IPUSH ||
ic->op == IPOP ||
ic->op == SEND) &&
IS_SYMOP (IC_LEFT (ic)))
{
/* check if they can be replaced */
if (!computeOnly)
{
pdop = NULL;
applyToSetFTrue (cseSet, findCheaperOp, IC_LEFT (ic), &pdop);
if (pdop)
IC_LEFT (ic) = pdop;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* the lookup could have changed it */
if (IS_SYMOP (IC_LEFT (ic)))
{
OP_USES (IC_LEFT (ic)) =
bitVectSetBit (OP_USES (IC_LEFT (ic)), ic->key);
setUsesDefs (IC_LEFT (ic), ebb->defSet,
ebb->outDefs, &ebb->usesDefs);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* if we a sending a pointer as a parameter
then kill all cse since the pointed to item
might be changed in the function being called */
if ((ic->op == IPUSH || ic->op == SEND) &&
IS_PTR (operandType (IC_LEFT (ic))))
{
deleteGetPointers (&cseSet, &ptrSetSet, IC_LEFT (ic), ebb);
ebb->ptrsSet = bitVectSetBit (ebb->ptrsSet, IC_LEFT (ic)->key);
for (i = 0; i < count; ebbs[i++]->visited = 0);
applyToSet (ebb->succList, delGetPointerSucc,
IC_LEFT (ic), ebb->dfnum);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
continue;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* if jumptable then mark the usage */
if (ic->op == JUMPTABLE)
{
OP_USES (IC_JTCOND (ic)) =
bitVectSetBit (OP_USES (IC_JTCOND (ic)), ic->key);
setUsesDefs (IC_JTCOND (ic), ebb->defSet,
ebb->outDefs, &ebb->usesDefs);
continue;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
if (SKIP_IC (ic))
continue;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
/* do some algebraic optimizations if possible */
algebraicOpts (ic);
while (constFold (ic, cseSet));
/* small klugde */
if (POINTER_GET (ic) && !IS_PTR (operandType (IC_LEFT (ic))))
{
setOperandType (IC_LEFT (ic),
aggrToPtr (operandType (IC_LEFT (ic)), FALSE));
fixUpTypes (ic);
2015-01-10 16:25:08 +01:00
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
if (POINTER_SET (ic) && !IS_PTR (operandType (IC_RESULT (ic))))
{
setOperandType (IC_RESULT (ic),
aggrToPtr (operandType (IC_RESULT (ic)), FALSE));
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* if this is a condition statment then */
/* check if the condition can be replaced */
if (ic->op == IFX)
{
ifxOptimize (ic, cseSet, computeOnly,
ebb, &change,
ebbs, count);
continue;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* if the assignment & result is a temp */
/* see if we can replace it */
if (ic->op == '=')
{
/* update the spill location for this */
updateSpillLocation (ic,0);
if (POINTER_SET (ic) &&
!(IS_BITFIELD (OP_SYMBOL (IC_RESULT (ic))->etype)))
{
pdop = NULL;
applyToSetFTrue (cseSet, findCheaperOp, IC_RESULT (ic), &pdop);
if (pdop && IS_ITEMP (pdop) && !computeOnly)
IC_RESULT (ic) = pdop;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
}
/* do the operand lookup i.e. for both the */
/* right & left operand : check the cseSet */
/* to see if they have been replaced if yes */
/* then replace them with those from cseSet */
/* left operand */
/* and left is a symbol */
if (IS_SYMOP (IC_LEFT (ic)) &&
!computeOnly && ic->op != ADDRESS_OF)
{
pdop = NULL;
applyToSetFTrue (cseSet, findCheaperOp, IC_LEFT (ic), &pdop);
if (pdop)
{
if (POINTER_GET (ic))
{
if (IS_ITEMP (pdop) || IS_OP_LITERAL (pdop))
{
IC_LEFT (ic) = pdop;
change = 1;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* check if there is a pointer set
for the same pointer visible if yes
then change this into an assignment */
pdop = NULL;
if (applyToSetFTrue (cseSet, findPointerSet, IC_LEFT (ic), &pdop, IC_RESULT (ic)) &&
!bitVectBitValue (ebb->ptrsSet, pdop->key))
{
ic->op = '=';
IC_LEFT (ic) = NULL;
IC_RIGHT (ic) = pdop;
SET_ISADDR (IC_RESULT (ic), 0);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
else
{
IC_LEFT (ic) = pdop;
change = 1;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
}
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/*right operand */
if (IS_SYMOP (IC_RIGHT (ic)) && !computeOnly)
{
pdop = NULL;
applyToSetFTrue (cseSet, findCheaperOp, IC_RIGHT (ic), &pdop);
if (pdop)
{
IC_RIGHT (ic) = pdop;
change = 1;
2015-01-10 16:25:06 +01:00
}
}
2015-01-10 16:25:09 +01:00
/* if left or right changed then do algebraic */
if (change)
{
algebraicOpts (ic);
while (constFold (ic, cseSet));
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* if after all this it becomes a assignment to self
then delete it and continue */
if (ASSIGNMENT_TO_SELF (ic))
{
remiCodeFromeBBlock (ebb, ic);
continue;
}
/* now we will check to see if the entire */
/* operation has been performed before */
/* and is available */
/* don't do assignments they will be killed */
/* by dead code elimination if required do */
/* it only if result is a temporary */
pdic = NULL;
if (!(POINTER_GET (ic) &&
(IS_BITFIELD (OP_SYMBOL (IC_RESULT (ic))->etype) ||
isOperandVolatile (IC_LEFT (ic), TRUE) ||
bitVectBitValue (ebb->ndompset, IC_LEFT (ic)->key))) &&
!ASSIGNMENT (ic) &&
IS_ITEMP (IC_RESULT (ic)) &&
!computeOnly)
{
applyToSet (cseSet, findPrevIc, ic, &pdic);
if (pdic && compareType (operandType (IC_RESULT (pdic)),
operandType (IC_RESULT (ic))) != 1)
pdic = NULL;
}
#if 0
/* if found then eliminate this and add to */
/* to cseSet an element containing result */
/* of this with previous opcode */
if (pdic)
{
if (IS_ITEMP (IC_RESULT (ic)))
{
/* replace in the remaining of this block */
replaceAllSymBySym (ic->next, IC_RESULT (ic), IC_RESULT (pdic), &ebb->ndompset);
/* remove this iCode from inexpressions of all
its successors, it cannot be in the in expressions
of any of the predecessors */
for (i = 0; i < count; ebbs[i++]->visited = 0);
applyToSet (ebb->succList, removeFromInExprs, ic, IC_RESULT (ic),
IC_RESULT (pdic), ebb);
/* if this was moved from another block */
/* then replace in those blocks too */
if (ic->movedFrom)
{
eBBlock *owner;
for (owner = setFirstItem (ic->movedFrom); owner;
owner = setNextItem (ic->movedFrom))
replaceAllSymBySym (owner->sch, IC_RESULT (ic), IC_RESULT (pdic), &owner->ndompset);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
pdic->movedFrom = unionSets (pdic->movedFrom, ic->movedFrom, THROW_NONE);
}
else
addSetHead (&cseSet, newCseDef (IC_RESULT (ic), pdic));
if (!computeOnly)
/* eliminate this */
remiCodeFromeBBlock (ebb, ic);
defic = pdic;
change++;
if (IS_ITEMP (IC_RESULT (ic)))
continue;
}
else
{
/* just add this as a previous expression except in */
/* case of a pointer access in which case this is a */
/* usage not a definition */
if (!(POINTER_SET (ic)) && IC_RESULT (ic))
{
deleteItemIf (&cseSet, ifDefSymIsX, IC_RESULT (ic));
addSetHead (&cseSet, newCseDef (IC_RESULT (ic), ic));
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
defic = ic;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
#else
/* Alternate code */
if (pdic && IS_ITEMP(IC_RESULT(ic))) {
/* if previous definition found change this to an assignment */
ic->op = '=';
IC_LEFT(ic) = NULL;
IC_RIGHT(ic) = operandFromOperand(IC_RESULT(pdic));
SET_ISADDR(IC_RESULT(ic),0);
SET_ISADDR(IC_RIGHT (ic),0);
}
if (!(POINTER_SET (ic)) && IC_RESULT (ic)) {
deleteItemIf (&cseSet, ifDefSymIsX, IC_RESULT (ic));
addSetHead (&cseSet, newCseDef (IC_RESULT (ic), ic));
}
defic = ic;
#endif
/* if assignment to a parameter which is not
mine and type is a pointer then delete
pointerGets to take care of aliasing */
if (ASSIGNMENT (ic) &&
OTHERS_PARM (OP_SYMBOL (IC_RESULT (ic))) &&
IS_PTR (operandType (IC_RESULT (ic))))
{
deleteGetPointers (&cseSet, &ptrSetSet, IC_RIGHT (ic), ebb);
for (i = 0; i < count; ebbs[i++]->visited = 0);
applyToSet (ebb->succList, delGetPointerSucc, IC_RIGHT (ic), ebb->dfnum);
ebb->ptrsSet = bitVectSetBit (ebb->ptrsSet, IC_RIGHT (ic)->key);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* if this is a pointerget then see if we can replace
this with a previously assigned pointer value */
if (POINTER_GET (ic) &&
!(IS_BITFIELD (OP_SYMBOL (IC_RESULT (ic))->etype) ||
isOperandVolatile (IC_LEFT (ic), TRUE)))
{
pdop = NULL;
applyToSet (ptrSetSet, findPointerSet, IC_LEFT (ic), &pdop, IC_RESULT (ic));
/* if we find it then locally replace all
references to the result with what we assigned */
if (pdop)
{
replaceAllSymBySym (ic->next, IC_RESULT (ic), pdop, &ebb->ndompset);
2015-01-10 16:25:06 +01:00
}
}
2015-01-10 16:25:09 +01:00
/* delete from the cseSet anything that has */
/* operands matching the result of this */
/* except in case of pointer access */
if (!(POINTER_SET (ic)) && IC_RESULT (ic))
{
deleteItemIf (&cseSet, ifOperandsHave, IC_RESULT (ic));
/* delete any previous definitions */
ebb->defSet = bitVectCplAnd (ebb->defSet, OP_DEFS (IC_RESULT (ic)));
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* add the left & right to the defUse set */
if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)))
{
OP_USES (IC_LEFT (ic)) =
bitVectSetBit (OP_USES (IC_LEFT (ic)), ic->key);
setUsesDefs (IC_LEFT (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)))
{
OP_USES (IC_RIGHT (ic)) =
bitVectSetBit (OP_USES (IC_RIGHT (ic)), ic->key);
setUsesDefs (IC_RIGHT (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* for the result it is special case, put the result */
/* in the defuseSet if it a pointer or array access */
if (POINTER_SET (defic))
{
OP_USES (IC_RESULT (ic)) =
bitVectSetBit (OP_USES (IC_RESULT (ic)), ic->key);
setUsesDefs (IC_RESULT (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs);
deleteItemIf (&cseSet, ifPointerGet, IC_RESULT (ic));
ebb->ptrsSet = bitVectSetBit (ebb->ptrsSet, IC_RESULT (ic)->key);
/* delete from inexpressions of all successors which
have dfNum > than this block */
for (i = 0; i < count; ebbs[i++]->visited = 0);
applyToSet (ebb->succList, delGetPointerSucc, IC_RESULT (ic), ebb->dfnum);
/* delete from cseSet all other pointer sets
for this operand */
deleteItemIf (&ptrSetSet, ifPointerSet, IC_RESULT (ic));
/* add to the local pointerset set */
addSetHead (&ptrSetSet, newCseDef (IC_RESULT (ic), ic));
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
else
/* add the result to defintion set */ if (IC_RESULT (ic))
{
OP_DEFS (IC_RESULT (ic)) =
bitVectSetBit (OP_DEFS (IC_RESULT (ic)), ic->key);
ebb->defSet = bitVectSetBit (ebb->defSet, ic->key);
ebb->outDefs = bitVectCplAnd (ebb->outDefs, OP_DEFS (IC_RESULT (ic)));
ebb->ldefs = bitVectSetBit (ebb->ldefs, ic->key);
}
/* if this is an addressof instruction then */
/* put the symbol in the address of list & */
/* delete it from the cseSet */
if (defic->op == ADDRESS_OF)
{
addSetHead (&ebb->addrOf, IC_LEFT (ic));
deleteItemIf (&cseSet, ifDefSymIsX, IC_LEFT (ic));
2015-01-10 16:25:06 +01:00
}
}
2015-01-10 16:25:09 +01:00
setToNull ((void **) &ebb->outExprs);
ebb->outExprs = cseSet;
ebb->outDefs = bitVectUnion (ebb->outDefs, ebb->defSet);
ebb->ptrsSet = bitVectUnion (ebb->ptrsSet, ebb->inPtrsSet);
return change;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
/* cseAllBlocks - will sequentially go thru & do cse for all blocks */
2015-01-10 16:25:06 +01:00
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
int
cseAllBlocks (eBBlock ** ebbs, int count)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
int i;
int change = 0;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
/* if optimization turned off */
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
for (i = 0; i < count; i++)
change += cseBBlock (ebbs[i], FALSE, ebbs, count);
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
return change;
2015-01-10 16:25:06 +01:00
}