summaryrefslogtreecommitdiff
path: root/src/SDCCBBlock.c
diff options
context:
space:
mode:
authorXavier ASUS <xavi92psx@gmail.com>2019-10-18 00:31:54 +0200
committerXavier ASUS <xavi92psx@gmail.com>2019-10-18 00:31:54 +0200
commit268a53de823a6750d6256ee1fb1e7707b4b45740 (patch)
tree42c1799a9a82b2f7d9790ee9fe181d72a7274751 /src/SDCCBBlock.c
downloadsdcc-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/SDCCBBlock.c')
-rw-r--r--src/SDCCBBlock.c889
1 files changed, 889 insertions, 0 deletions
diff --git a/src/SDCCBBlock.c b/src/SDCCBBlock.c
new file mode 100644
index 0000000..37c6fdb
--- /dev/null
+++ b/src/SDCCBBlock.c
@@ -0,0 +1,889 @@
+/*-------------------------------------------------------------------------
+
+ SDCCBBlock.c - routines to manipulate basic Blocks
+
+ 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"
+#include "dbuf_string.h"
+
+int eBBNum = 0;
+set *graphEdges = NULL; /* list of edges in this flow graph */
+
+struct _dumpFiles dumpFiles[] = {
+ {DUMP_RAW0, ".dumpraw0", NULL},
+ {DUMP_RAW1, ".dumpraw1", NULL},
+ {DUMP_CSE, ".dumpcse", NULL},
+ {DUMP_DFLOW, ".dumpdflow", NULL},
+ {DUMP_GCSE, ".dumpgcse", NULL},
+ {DUMP_DEADCODE, ".dumpdeadcode", NULL},
+ {DUMP_LOOP, ".dumploop", NULL},
+ {DUMP_LOOPG, ".dumploopg", NULL},
+ {DUMP_LOOPD, ".dumploopd", NULL},
+ {DUMP_RANGE, ".dumprange", NULL},
+ {DUMP_PACK, ".dumppack", NULL},
+ {DUMP_RASSGN, ".dumprassgn", NULL},
+ {DUMP_LRANGE, ".dumplrange", NULL},
+ {DUMP_LOSPRE, ".dumplospre", NULL},
+ {DUMP_CUSTOM, ".dumpcustom", NULL},
+ {0, NULL, NULL}
+};
+
+/*-----------------------------------------------------------------*/
+/* printEntryLabel - prints entry label of a ebblock */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC (printEntryLabel)
+{
+ eBBlock *bp = item;
+
+ fprintf (stdout, " %-20s ", bp->entryLabel->name);
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* neweBBlock - allocate & return a new extended basic block */
+/*-----------------------------------------------------------------*/
+eBBlock *
+neweBBlock ()
+{
+ eBBlock *ebb;
+
+ ebb = Safe_alloc (sizeof (eBBlock));
+ return ebb;
+}
+
+/*-----------------------------------------------------------------*/
+/* newEdge - allocates & initialises an edge to given values */
+/*-----------------------------------------------------------------*/
+edge *
+newEdge (eBBlock * from, eBBlock * to)
+{
+ edge *ep;
+
+ ep = Safe_alloc (sizeof (edge));
+
+ ep->from = from;
+ ep->to = to;
+ return ep;
+}
+
+/*-----------------------------------------------------------------*/
+/* createDumpFile - create the dump file */
+/*-----------------------------------------------------------------*/
+FILE *
+createDumpFile (int id)
+{
+ struct _dumpFiles *dumpFilesPtr = dumpFiles;
+ static int dumpIndex = 0;
+ static char dumpIndexStr[32];
+
+ while (dumpFilesPtr->id)
+ {
+ if (dumpFilesPtr->id == id)
+ break;
+ dumpFilesPtr++;
+ }
+
+ if (!dumpFilesPtr->id)
+ {
+ fprintf (stdout, "internal error: createDumpFile: unknown dump file.\n");
+ exit (1);
+ }
+
+ sprintf (dumpIndexStr, ".%d", dumpIndex);
+ dumpIndex++;
+
+ if (!dumpFilesPtr->filePtr)
+ {
+ // not used before, create it
+ struct dbuf_s dumpFileName;
+
+ dbuf_init (&dumpFileName, PATH_MAX);
+ dbuf_append_str (&dumpFileName, dstFileName);
+#ifdef _DEBUG
+ dbuf_append_str (&dumpFileName, dumpIndexStr);
+#endif
+ dbuf_append_str (&dumpFileName, dumpFilesPtr->ext);
+ if (!(dumpFilesPtr->filePtr = fopen (dbuf_c_str (&dumpFileName), "w")))
+ {
+ werror (E_FILE_OPEN_ERR, dbuf_c_str (&dumpFileName));
+ dbuf_destroy (&dumpFileName);
+ exit (1);
+ }
+ dbuf_destroy (&dumpFileName);
+ }
+
+#if 0
+ fprintf (dumpFilesPtr->filePtr, "Dump file index: %d\n", dumpIndex);
+#endif
+
+ return dumpFilesPtr->filePtr;
+}
+
+/*-----------------------------------------------------------------*/
+/* closeDumpFiles - close possible opened dumpfiles */
+/*-----------------------------------------------------------------*/
+void
+closeDumpFiles ()
+{
+ struct _dumpFiles *dumpFilesPtr;
+
+ for (dumpFilesPtr = dumpFiles; dumpFilesPtr->id; dumpFilesPtr++)
+ {
+ if (dumpFilesPtr->filePtr)
+ {
+ fclose (dumpFilesPtr->filePtr);
+ }
+ }
+}
+
+/*-----------------------------------------------------------------*/
+/* dumpLiveRanges - dump liverange information into a file */
+/*-----------------------------------------------------------------*/
+void
+dumpLiveRanges (int id, hTab * liveRanges)
+{
+ FILE *file;
+ symbol *sym;
+ int k;
+
+ if (id)
+ {
+ file = createDumpFile (id);
+ }
+ else
+ {
+ file = stdout;
+ }
+
+ if (currFunc)
+ fprintf (file, "------------- Func %s -------------\n", currFunc->name);
+ for (sym = hTabFirstItem (liveRanges, &k); sym; sym = hTabNextItem (liveRanges, &k))
+ {
+
+ fprintf (file, "%s [k%d lr%d:%d so:%d]{ re%d rm%d}",
+ (sym->rname[0] ? sym->rname : sym->name),
+ sym->key, sym->liveFrom, sym->liveTo, sym->stack, sym->isreqv, sym->remat);
+
+ fprintf (file, "{");
+ printTypeChain (sym->type, file);
+ if (sym->usl.spillLoc)
+ {
+ fprintf (file, "}{ sir@ %s", sym->usl.spillLoc->rname);
+ }
+ fprintf (file, "} clashes with ");
+ bitVectDebugOn (sym->clashes, file);
+ fprintf (file, "\n");
+ }
+
+ fflush (file);
+}
+
+
+/*-----------------------------------------------------------------*/
+/* dumpEbbsToFileExt - write all the basic blocks to a file */
+/*-----------------------------------------------------------------*/
+void
+dumpEbbsToFileExt (int id, ebbIndex * ebbi)
+{
+ FILE *of;
+ int i, d;
+ eBBlock *bb;
+ set *cseSet;
+ eBBlock **ebbs = ebbi->dfOrder ? ebbi->dfOrder : ebbi->bbOrder;
+ int count = ebbi->count;
+
+ if (id)
+ {
+ of = createDumpFile (id);
+ }
+ else
+ {
+ of = stdout;
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ fprintf (of, "\n----------------------------------------------------------------\n");
+ fprintf (of, "Basic Block %s (df:%d bb:%d lvl:%ld:%ld): loopDepth=%d%s%s%s\n",
+ ebbs[i]->entryLabel->name,
+ ebbs[i]->dfnum, ebbs[i]->bbnum,
+ ebbs[i]->entryLabel->level / LEVEL_UNIT, ebbs[i]->entryLabel->level % LEVEL_UNIT,
+ ebbs[i]->depth,
+ ebbs[i]->noPath ? " noPath" : "",
+ ebbs[i]->partOfLoop ? " partOfLoop" : "", ebbs[i]->isLastInLoop ? " isLastInLoop" : "");
+
+ // a --nolabelopt makes this more readable
+ fprintf (of, "\nsuccessors: ");
+ for (bb = setFirstItem (ebbs[i]->succList); bb; bb = setNextItem (ebbs[i]->succList))
+ {
+ fprintf (of, "%s ", bb->entryLabel->name);
+ }
+ fprintf (of, "\npredecessors: ");
+ for (bb = setFirstItem (ebbs[i]->predList); bb; bb = setNextItem (ebbs[i]->predList))
+ {
+ fprintf (of, "%s ", bb->entryLabel->name);
+ }
+ fprintf (of, "\ndominators: ");
+ for (d = 0; d < ebbs[i]->domVect->size; d++)
+ {
+ if (bitVectBitValue (ebbs[i]->domVect, d))
+ {
+ fprintf (of, "%s ", ebbi->bbOrder[d]->entryLabel->name); //ebbs[d]->entryLabel->name);
+ }
+ }
+ fprintf (of, "\n");
+
+ fprintf (of, "\ndefines bitVector :");
+ bitVectDebugOn (ebbs[i]->defSet, of);
+ fprintf (of, "\nlocal defines bitVector :");
+ bitVectDebugOn (ebbs[i]->ldefs, of);
+ fprintf (of, "\npointers Set bitvector :");
+ bitVectDebugOn (ebbs[i]->ptrsSet, of);
+#if 0
+ fprintf (of, "\nin coming definitions :");
+ bitVectDebugOn (ebbs[i]->inDefs, of);
+ fprintf (of, "\nout going definitions :");
+ bitVectDebugOn (ebbs[i]->outDefs, of);
+ fprintf (of, "\ndefines used :");
+ bitVectDebugOn (ebbs[i]->usesDefs, of);
+#endif
+
+ if (ebbs[i]->isLastInLoop)
+ {
+ fprintf (of, "\nInductions Set bitvector :");
+ bitVectDebugOn (ebbs[i]->linds, of);
+ }
+
+ fprintf (of, "\ninExprs:");
+ for (cseSet = ebbs[i]->inExprs; cseSet; cseSet = cseSet->next)
+ {
+ cseDef *item = cseSet->item;
+ fprintf (of, " %s(%d)", OP_SYMBOL (item->sym)->name, item->diCode->key);
+ if (item->fromGlobal)
+ fprintf (of, "g");
+ }
+ fprintf (of, "\noutExprs:");
+ for (cseSet = ebbs[i]->outExprs; cseSet; cseSet = cseSet->next)
+ {
+ cseDef *item = cseSet->item;
+ fprintf (of, " %s(%d)", OP_SYMBOL (item->sym)->name, item->diCode->key);
+ if (item->fromGlobal)
+ fprintf (of, "g");
+ }
+ fprintf (of, "\nkilledExprs:");
+ for (cseSet = ebbs[i]->killedExprs; cseSet; cseSet = cseSet->next)
+ {
+ cseDef *item = cseSet->item;
+ fprintf (of, " %s(%d)", OP_SYMBOL (item->sym)->name, item->diCode->key);
+ if (item->fromGlobal)
+ fprintf (of, "g");
+ }
+
+ fprintf (of, "\n----------------------------------------------------------------\n");
+ printiCChain (ebbs[i]->sch, of);
+ }
+ fflush (of);
+}
+
+/*-----------------------------------------------------------------*/
+/* iCode2eBBlock - converts a sequnce till label to a ebb */
+/*-----------------------------------------------------------------*/
+eBBlock *
+iCode2eBBlock (iCode * ic)
+{
+ iCode *loop;
+ eBBlock *ebb = neweBBlock (); /* allocate an entry */
+
+ /* put the first one unconditionally */
+ ebb->sch = ic;
+ ic->seq = 0;
+
+ /* if this is a label then */
+ if (ic->op == LABEL)
+ ebb->entryLabel = ic->label;
+ else
+ {
+ struct dbuf_s dbuf;
+
+ dbuf_init (&dbuf, 128);
+ dbuf_printf (&dbuf, "_eBBlock%d", eBBNum++);
+ ebb->entryLabel = newSymbol (dbuf_c_str (&dbuf), 1);
+ dbuf_destroy (&dbuf);
+ ebb->entryLabel->key = labelKey++;
+ }
+
+ if (ic && (ic->op == GOTO || ic->op == JUMPTABLE || ic->op == IFX))
+ {
+ ebb->ech = ebb->sch;
+ return ebb;
+ }
+
+ /* if this is a function call */
+ if (ic->op == CALL || ic->op == PCALL)
+ {
+ sym_link *type = operandType (IC_LEFT (ic));
+ ebb->hasFcall = 1;
+ if (currFunc)
+ FUNC_HASFCALL (currFunc->type) = 1;
+ if (IS_FUNCPTR (type))
+ type = type->next;
+ if (type && FUNC_ISNORETURN (type))
+ {
+ ebb->ech = ebb->sch;
+ return ebb;
+ }
+ }
+
+ if ((ic->next && ic->next->op == LABEL) || !ic->next)
+ {
+ ebb->ech = ebb->sch;
+ return ebb;
+ }
+
+ /* loop thru till we find one with a label */
+ for (loop = ic->next; loop; loop = loop->next)
+ {
+ loop->seq = 0;
+
+ /* if this is the last one */
+ if (!loop->next)
+ break;
+ /* if this is a function call */
+ if (loop->op == CALL || loop->op == PCALL)
+ {
+ sym_link *type = operandType (IC_LEFT (loop));
+ ebb->hasFcall = 1;
+ if (currFunc)
+ FUNC_HASFCALL (currFunc->type) = 1;
+ if (IS_FUNCPTR (type))
+ type = type->next;
+ if (type && FUNC_ISNORETURN (type))
+ break;
+ }
+
+ /* if the next one is a label */
+ /* if this is a goto or ifx */
+ if (loop->next->op == LABEL || loop->op == GOTO || loop->op == JUMPTABLE || loop->op == IFX)
+ break;
+ }
+
+ /* mark the end of the chain */
+ ebb->ech = loop;
+
+ return ebb;
+}
+
+/*-----------------------------------------------------------------*/
+/* eBBWithEntryLabel - finds the basic block with the entry label */
+/*-----------------------------------------------------------------*/
+eBBlock *
+eBBWithEntryLabel (ebbIndex* ebbi, const symbol *eLabel)
+{
+ eBBlock **ebbs = ebbi->bbOrder;
+ int count = ebbi->count;
+ int i;
+
+ for (i = 0; i < count; i++)
+ {
+ if (isSymbolEqual (ebbs[i]->entryLabel, eLabel))
+ return ebbs[i];
+ }
+
+ return NULL;
+}
+
+
+/*-----------------------------------------------------------------*/
+/* ifFromIs - will return 1 if the from block matches this */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC (ifFromIs)
+{
+ edge *ep = item;
+ V_ARG (eBBlock *, this);
+
+ if (ep->from == this)
+ return 1;
+
+ return 0;
+}
+
+
+/*-----------------------------------------------------------------*/
+/* edgesTo - returns a set of edges with to == supplied value */
+/*-----------------------------------------------------------------*/
+set *
+edgesTo (eBBlock * to)
+{
+ set *result = NULL;
+ edge *loop;
+
+ for (loop = setFirstItem (graphEdges); loop; loop = setNextItem (graphEdges))
+ if (loop->to == to && !loop->from->noPath)
+ addSet (&result, loop->from);
+
+ return result;
+}
+
+
+/*-----------------------------------------------------------------*/
+/* addiCodeToeBBlock - will add an iCode to the end of a block */
+/*-----------------------------------------------------------------*/
+void
+addiCodeToeBBlock (eBBlock * ebp, iCode * ic, iCode * ip)
+{
+ ic->prev = ic->next = NULL;
+ /* if the insert point is given */
+ if (ip)
+ {
+ ic->filename = ip->filename;
+ ic->lineno = ip->lineno;
+ ic->eBBlockNum = ip->eBBlockNum;
+ ic->prev = ip->prev;
+ ip->prev = ic;
+ ic->next = ip;
+ if (!ic->prev)
+ ebp->sch = ic;
+ else
+ ic->prev->next = ic;
+ return;
+ }
+
+ /* if the block has no instructions */
+ if (ebp->ech == NULL)
+ {
+ ebp->sch = ebp->ech = ic;
+ ic->next = NULL;
+ return;
+ }
+
+ /* if the last instruction is a goto */
+ /* we add it just before the goto */
+ if (ebp->ech->op == GOTO || ebp->ech->op == JUMPTABLE || ebp->ech->op == RETURN)
+ {
+ ic->filename = ebp->ech->filename;
+ ic->lineno = ebp->ech->lineno;
+ ic->prev = ebp->ech->prev;
+ ebp->ech->prev = ic;
+ ic->next = ebp->ech;
+ if (!ic->prev) /* was the last only on in the block */
+ ebp->sch = ic;
+ else
+ ic->prev->next = ic;
+ return;
+ }
+
+ /* if the last one was a ifx statement we check to see */
+ /* if the condition was defined in the previous instruction */
+ /* if this is true then we put it before the condition else */
+ /* we put it before if, this is to reduce register pressure, */
+ /* we don't have to hold condition too long in a register */
+
+ /* loop induction sometimes appends a GOTO instruction, */
+ /* it must be at the very end */
+ if (ebp->ech->op == IFX && ic->op != GOTO)
+ {
+ iCode *ipoint;
+
+/* if ( !ebp->ech->prev ) */
+/* ipoint = ebp->ech ; */
+/* else */
+/* if (!IC_RESULT(ebp->ech->prev)) */
+/* ipoint = ebp->ech ; */
+/* else */
+/* if (IC_COND(ebp->ech)->key == IC_RESULT(ebp->ech->prev)->key) */
+/* ipoint = ebp->ech->prev; */
+/* else */
+/* ipoint = ebp->ech ; */
+ ipoint = ebp->ech;
+ ic->filename = ipoint->filename;
+ ic->lineno = ipoint->lineno;
+ ic->prev = ipoint->prev;
+ ipoint->prev = ic;
+ ic->next = ipoint;
+ if (!ic->prev)
+ ebp->sch = ic;
+ else
+ ic->prev->next = ic;
+ return;
+ }
+
+ /* will add it to the very end */
+ ip = ebp->ech;
+ ip->next = ic;
+ ic->prev = ip;
+ ic->next = NULL;
+ ebp->ech = ic;
+
+ return;
+}
+
+/*-----------------------------------------------------------------*/
+/* remiCodeFromeBBlock - remove an iCode from BBlock */
+/*-----------------------------------------------------------------*/
+void
+remiCodeFromeBBlock (eBBlock * ebb, iCode * ic)
+{
+ wassert (ic->seq >= ebb->fSeq && ic->seq <= ebb->lSeq);
+ if (ic->prev)
+ ic->prev->next = ic->next;
+ else
+ ebb->sch = ic->next;
+
+ if (ic->next)
+ ic->next->prev = ic->prev;
+ else
+ ebb->ech = ic->prev;
+}
+
+/*-----------------------------------------------------------------*/
+/* iCodeBreakDown : breakDown iCode chain to blocks */
+/*-----------------------------------------------------------------*/
+ebbIndex *
+iCodeBreakDown (iCode * ic)
+{
+ eBBlock **ebbs = NULL;
+ iCode *loop = ic;
+ ebbIndex *ebbi;
+
+ ebbi = Safe_alloc (sizeof (ebbIndex));
+ ebbi->count = 0;
+ ebbi->dfOrder = NULL; /* no depth first order information yet */
+
+ /* allocate for the first entry */
+
+ ebbs = Safe_alloc (sizeof (eBBlock *));
+ ebbi->bbOrder = ebbs;
+
+ while (loop)
+ {
+
+ /* convert 2 block */
+ eBBlock *ebb = iCode2eBBlock (loop);
+ loop = ebb->ech->next;
+
+ ebb->ech->next = NULL; /* mark the end of this chain */
+ if (loop)
+ loop->prev = NULL;
+ ebb->bbnum = ebbi->count; /* save this block number */
+ /* put it in the array */
+ ebbs[(ebbi->count)++] = ebb;
+
+ /* allocate for the next one. Remember to clear the new */
+ /* pointer at the end, that was created by realloc. */
+
+ ebbs = Safe_realloc (ebbs, (ebbi->count + 1) * sizeof (eBBlock *));
+ ebbi->bbOrder = ebbs;
+
+ ebbs[ebbi->count] = 0;
+
+ /* if this one ends in a goto or a conditional */
+ /* branch then check if the block it is going */
+ /* to already exists, if yes then this could */
+ /* be a loop, add a preheader to the block it */
+ /* goes to if it does not already have one */
+ if (ebbs[(ebbi->count) - 1]->ech && (ebbs[(ebbi->count) - 1]->ech->op == GOTO || ebbs[(ebbi->count) - 1]->ech->op == IFX))
+ {
+
+ symbol *label;
+ eBBlock *destBlock;
+
+ if (ebbs[(ebbi->count) - 1]->ech->op == GOTO)
+ label = IC_LABEL (ebbs[(ebbi->count) - 1]->ech);
+ else if (!(label = IC_TRUE (ebbs[(ebbi->count) - 1]->ech)))
+ label = IC_FALSE (ebbs[(ebbi->count) - 1]->ech);
+
+ if ((destBlock = eBBWithEntryLabel (ebbi, label)) &&
+ destBlock->preHeader == NULL && otherPathsPresent (ebbs, destBlock))
+ {
+
+ symbol *preHeaderLabel = newiTempLoopHeaderLabel (1);
+ int i, j;
+ eBBlock *pBlock;
+
+ /* go thru all block replacing the entryLabel with new label */
+ /* till we reach the block , then we insert a new ebblock */
+ for (i = 0; i < (ebbi->count); i++)
+ {
+ if (ebbs[i] == destBlock)
+ break;
+ replaceLabel (ebbs[i], label, preHeaderLabel);
+ }
+
+ (ebbi->count)++;
+
+ /* if we have stopped at the block , allocate for an extra one */
+
+ ebbs = Safe_realloc (ebbs, (ebbi->count + 1) * sizeof (eBBlock *));
+ ebbi->bbOrder = ebbs;
+
+ ebbs[ebbi->count] = 0;
+
+ /* then move the block down one count */
+ pBlock = ebbs[j = i];
+ for (i += 1; i < (ebbi->count); i++)
+ {
+ eBBlock *xBlock;
+
+ xBlock = ebbs[i];
+ ebbs[i] = pBlock;
+ ebbs[i]->bbnum = i;
+ pBlock = xBlock;
+ }
+
+ destBlock->preHeader = ebbs[j] = neweBBlock ();
+ ebbs[j]->bbnum = j;
+ ebbs[j]->entryLabel = preHeaderLabel;
+ ebbs[j]->sch = ebbs[j]->ech = newiCodeLabelGoto (LABEL, preHeaderLabel);
+ ebbs[j]->sch->filename = destBlock->sch->filename;
+ ebbs[j]->sch->lineno = destBlock->sch->lineno;
+ }
+ }
+ }
+
+ /* mark the end */
+ ebbs[ebbi->count] = NULL;
+
+ return ebbi;
+}
+
+/*-----------------------------------------------------------------*/
+/* replaceSymBySym : - replace operand by operand in blocks */
+/* replaces only left & right in blocks */
+/*-----------------------------------------------------------------*/
+void
+replaceSymBySym (set * sset, operand * src, operand * dest)
+{
+ set *loop;
+ eBBlock *rBlock;
+
+ /* for all blocks in the set do */
+ for (loop = sset; loop; loop = loop->next)
+ {
+ iCode *ic;
+
+ rBlock = loop->item;
+ /* for all instructions in this block do */
+ for (ic = rBlock->sch; ic; ic = ic->next)
+ {
+
+ /* if we find usage */
+ if (ic->op == IFX && isOperandEqual (src, IC_COND (ic)))
+ {
+ bitVectUnSetBit (OP_USES (IC_COND (ic)), ic->key);
+ IC_COND (ic) = operandFromOperand (dest);
+ OP_USES (dest) = bitVectSetBit (OP_USES (dest), ic->key);
+ continue;
+ }
+
+ if (isOperandEqual (IC_RIGHT (ic), src))
+ {
+ bitVectUnSetBit (OP_USES (IC_RIGHT (ic)), ic->key);
+ IC_RIGHT (ic) = operandFromOperand (dest);
+ IC_RIGHT (ic)->isaddr = 0;
+ OP_USES (dest) = bitVectSetBit (OP_USES (dest), ic->key);
+ }
+
+ if (isOperandEqual (IC_LEFT (ic), src))
+ {
+ bitVectUnSetBit (OP_USES (IC_LEFT (ic)), ic->key);
+ if (POINTER_GET (ic) && IS_ITEMP (dest))
+ {
+ IC_LEFT (ic) = operandFromOperand (dest);
+ IC_LEFT (ic)->isaddr = 1;
+ }
+ else
+ {
+ IC_LEFT (ic) = operandFromOperand (dest);
+ IC_LEFT (ic)->isaddr = 0;
+ }
+ OP_USES (dest) = bitVectSetBit (OP_USES (dest), ic->key);
+ }
+
+ /* special case for pointer sets */
+ if (POINTER_SET (ic) && isOperandEqual (IC_RESULT (ic), src))
+ {
+ bitVectUnSetBit (OP_USES (IC_RESULT (ic)), ic->key);
+ IC_RESULT (ic) = operandFromOperand (dest);
+ IC_RESULT (ic)->isaddr = 1;
+ OP_USES (dest) = bitVectSetBit (OP_USES (dest), ic->key);
+ }
+ }
+ }
+}
+
+/*-----------------------------------------------------------------*/
+/* replaceLabel - replace reference to one label by another */
+/*-----------------------------------------------------------------*/
+void
+replaceLabel (eBBlock *ebp, symbol *fromLbl, symbol *toLbl)
+{
+ iCode *ic;
+
+ if (!ebp)
+ return;
+
+ for (ic = ebp->sch; ic; ic = ic->next)
+ {
+ switch (ic->op)
+ {
+
+ case GOTO:
+ if (isSymbolEqual (IC_LABEL (ic), fromLbl))
+ IC_LABEL (ic) = toLbl;
+ break;
+
+ case IFX:
+ if (IC_TRUE (ic) && isSymbolEqual (IC_TRUE (ic), fromLbl))
+ IC_TRUE (ic) = toLbl;
+ else if (isSymbolEqual (IC_FALSE (ic), fromLbl))
+ IC_FALSE (ic) = toLbl;
+ break;
+
+ case JUMPTABLE:
+ replaceSetItem (IC_JTLABELS (ic), fromLbl, toLbl);
+ }
+ }
+
+ return;
+
+}
+
+
+/*-----------------------------------------------------------------*/
+/* iCodeFromeBBlock - convert basic block to iCode chain */
+/*-----------------------------------------------------------------*/
+iCode *
+iCodeFromeBBlock (eBBlock ** ebbs, int count)
+{
+ int i = 1;
+ iCode *ric = ebbs[0]->sch;
+ iCode *lic = ebbs[0]->ech;
+
+ for (; i < count; i++)
+ {
+ if (ebbs[i]->sch == NULL)
+ continue;
+
+ if (ebbs[i]->noPath && optimize.label4 && (ebbs[i]->entryLabel != entryLabel && ebbs[i]->entryLabel != returnLabel))
+ {
+ iCode *ic = NULL;
+ bool foundNonlabel = 0;
+ ic = ebbs[i]->sch;
+ do
+ {
+ if (ic->op != LABEL)
+ {
+ foundNonlabel = 1;
+ break;
+ }
+ if (ic == ebbs[i]->ech)
+ break;
+ ic = ic->next;
+ }
+ while (ic);
+ if (foundNonlabel && ic)
+ {
+ werrorfl (ic->filename, ic->lineno, W_CODE_UNREACH);
+ continue;
+ }
+ }
+
+ lic->next = ebbs[i]->sch;
+ lic->next->prev = lic;
+ lic = ebbs[i]->ech;
+
+ }
+
+ return ric;
+}
+
+/*-----------------------------------------------------------------*/
+/* otherPathsPresent - determines if there is a path from _entry */
+/* to this block in a half constructed set of blocks */
+/*-----------------------------------------------------------------*/
+int
+otherPathsPresent (eBBlock ** ebbs, eBBlock * this)
+{
+ int i;
+
+ /* for all blocks preceding this block */
+ for (i = 0; i < this->bbnum; i++)
+ {
+ iCode *ic;
+
+ /* if there is a reference to the entry label of this block */
+ for (ic = ebbs[i]->sch; ic; ic = ic->next)
+ {
+ switch (ic->op)
+ {
+ case GOTO:
+ if (IC_LABEL (ic)->key == this->entryLabel->key)
+ return 1;
+ break;
+
+ case IFX:
+ if (IC_TRUE (ic))
+ {
+ if (IC_TRUE (ic)->key == this->entryLabel->key)
+ return 1;
+ }
+ else if (IC_FALSE (ic)->key == this->entryLabel->key)
+ return 1;
+ break;
+ }
+ }
+ }
+
+ /* comes here means we have not found it yet */
+ /* in this case check if the previous block */
+ /* ends in a goto if it does then we have no */
+ /* path else we have a path */
+ if (this->bbnum && ebbs[this->bbnum - 1]->ech && ebbs[this->bbnum - 1]->ech->op == GOTO)
+ return 0;
+ else
+ return 1;
+}
+
+
+/*-----------------------------------------------------------------*/
+/* freeBBlockData - Deallocate data structures associated with */
+/* the current blocks. They will all be recomputed if the */
+/* iCode chain is divided into blocks again later. */
+/*-----------------------------------------------------------------*/
+void
+freeeBBlockData(ebbIndex * ebbi)
+{
+ int i;
+ eBBlock ** ebbs = ebbi->bbOrder;
+
+ for (i=0; i < ebbi->count; i++)
+ {
+ deleteSet (&ebbs[i]->succList);
+ deleteSet (&ebbs[i]->predList);
+ freeBitVect (ebbs[i]->succVect);
+ freeBitVect (ebbs[i]->domVect);
+
+ freeCSEdata(ebbs[i]);
+ }
+}
+