lrh
[fw/sdcc] / src / SDCCBBlock.c
1 /*-------------------------------------------------------------------------
2
3   SDCCBBlock.c - routines to manipulate basic Blocks
4
5              Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
6
7    This program is free software; you can redistribute it and/or modify it
8    under the terms of the GNU General Public License as published by the
9    Free Software Foundation; either version 2, or (at your option) any
10    later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
21    In other words, you are welcome to use, share and improve this program.
22    You are forbidden to forbid anyone else to use, share and improve
23    what you give them.   Help stamp out software-hoarding!
24 -------------------------------------------------------------------------*/
25
26 #include "common.h"
27
28 int eBBNum = 0;
29 set *graphEdges = NULL;         /* list of edges in this flow graph */
30
31 struct _dumpFiles dumpFiles[] = {
32   {DUMP_RAW0, ".dumpraw0", NULL},
33   {DUMP_RAW1, ".dumpraw1", NULL},
34   {DUMP_CSE, ".dumpcse", NULL},
35   {DUMP_DFLOW, ".dumpdflow", NULL},
36   {DUMP_GCSE, ".dumpgcse", NULL},
37   {DUMP_DEADCODE, ".dumpdeadcode", NULL},
38   {DUMP_LOOP, ".dumploop", NULL},
39   {DUMP_LOOPG, ".dumploopg", NULL},
40   {DUMP_LOOPD, ".dumploopd", NULL},
41   {DUMP_RANGE, ".dumprange", NULL},
42   {DUMP_PACK, ".dumppack", NULL},
43   {DUMP_RASSGN, ".dumprassgn", NULL},
44   {DUMP_LRANGE, ".dumplrange", NULL},
45   {0, NULL, NULL}
46 };
47
48 /*-----------------------------------------------------------------*/
49 /* printEntryLabel - prints entry label of a ebblock               */
50 /*-----------------------------------------------------------------*/
51 DEFSETFUNC (printEntryLabel)
52 {
53   eBBlock *bp = item;
54
55   fprintf (stdout, " %-20s ", bp->entryLabel->name);
56   return 0;
57 }
58
59 /*-----------------------------------------------------------------*/
60 /* neweBBlock - allocate & return a new extended basic block       */
61 /*-----------------------------------------------------------------*/
62 eBBlock *
63 neweBBlock ()
64 {
65   eBBlock *ebb;
66
67   ebb = Safe_alloc (sizeof (eBBlock));
68   return ebb;
69 }
70
71 /*-----------------------------------------------------------------*/
72 /* newEdge - allocates & initialises an edge to given values       */
73 /*-----------------------------------------------------------------*/
74 edge *
75 newEdge (eBBlock * from, eBBlock * to)
76 {
77   edge *ep;
78
79   ep = Safe_alloc (sizeof (edge));
80
81   ep->from = from;
82   ep->to = to;
83   return ep;
84 }
85
86 /*-----------------------------------------------------------------*/
87 /* createDumpFile - create the dump file                           */
88 /*-----------------------------------------------------------------*/
89 FILE *createDumpFile (int id) {
90   struct _dumpFiles *dumpFilesPtr=dumpFiles;
91
92   while (dumpFilesPtr->id) {
93     if (dumpFilesPtr->id==id)
94       break;
95     dumpFilesPtr++;
96   }
97
98   if (!dumpFilesPtr->id) {
99     fprintf (stdout, "internal error: createDumpFile: unknown dump file.\n");
100     exit (1);
101   }
102
103   if (!dumpFilesPtr->filePtr) {
104     // not used before, create it
105     strncpyz (scratchFileName, dstFileName, PATH_MAX);
106     strncatz (scratchFileName, dumpFilesPtr->ext, PATH_MAX);
107     if (!(dumpFilesPtr->filePtr = fopen (scratchFileName, "w"))) {
108       werror (E_FILE_OPEN_ERR, scratchFileName);
109       exit (1);
110     }
111   } 
112   return dumpFilesPtr->filePtr;
113 }
114
115 /*-----------------------------------------------------------------*/
116 /* closeDumpFiles - close possible opened dumpfiles                */
117 /*-----------------------------------------------------------------*/
118 void closeDumpFiles() {
119   struct _dumpFiles *dumpFilesPtr;
120
121   for (dumpFilesPtr=dumpFiles; dumpFilesPtr->id; dumpFilesPtr++) {
122     if (dumpFilesPtr->filePtr) {
123       fclose (dumpFilesPtr->filePtr);
124     }
125   }
126 }
127
128 /*-----------------------------------------------------------------*/
129 /* dumpLiveRanges - dump liverange information into a file         */
130 /*-----------------------------------------------------------------*/
131 void 
132 dumpLiveRanges (int id, hTab * liveRanges)
133 {
134   FILE *file;
135   symbol *sym;
136   int k;
137
138   if (id) {
139     file=createDumpFile(id);
140   } else {
141     file = stdout;
142   }
143   
144   if (currFunc) 
145       fprintf(file,"------------- Func %s -------------\n",currFunc->name);
146   for (sym = hTabFirstItem (liveRanges, &k); sym;
147        sym = hTabNextItem (liveRanges, &k))
148     {
149
150       fprintf (file, "%s [k%d lr%d:%d so:%d]{ re%d rm%d}",
151                (sym->rname[0] ? sym->rname : sym->name),
152                sym->key,
153                sym->liveFrom, sym->liveTo,
154                sym->stack,
155                sym->isreqv, sym->remat
156         );
157
158       fprintf (file, "{");
159       printTypeChain (sym->type, file);
160       if (sym->usl.spillLoc)
161         {
162           fprintf (file, "}{ sir@ %s", sym->usl.spillLoc->rname);
163         }
164       fprintf (file, "} clashes with ");
165       bitVectDebugOn(sym->clashes,file);
166       fprintf (file, "\n");
167     }
168
169   fflush(file);
170 }
171
172 /*-----------------------------------------------------------------*/
173 /* dumpEbbsToFileExt - writeall the basic blocks to a file         */
174 /*-----------------------------------------------------------------*/
175 void 
176 dumpEbbsToFileExt (int id, eBBlock ** ebbs, int count)
177 {
178   FILE *of;
179   int i;
180   eBBlock *bb;
181
182   if (id) {
183     of=createDumpFile(id);
184   } else {
185     of = stdout;
186   }
187
188   for (i = 0; i < count; i++)
189     {
190       fprintf (of, "\n----------------------------------------------------------------\n");
191       fprintf (of, "Basic Block %s (df:%d bb:%d lvl:%d): loopDepth=%d%s%s%s\n",
192                ebbs[i]->entryLabel->name,
193                ebbs[i]->dfnum, ebbs[i]->bbnum, ebbs[i]->entryLabel->level,
194                ebbs[i]->depth,
195                ebbs[i]->noPath ? " noPath" : "",
196                ebbs[i]->partOfLoop ? " partOfLoop" : "",
197                ebbs[i]->isLastInLoop ? " isLastInLoop" : "");
198
199       // a --nolabelopt makes this more readable
200       fprintf (of, "\nsuccessors: ");
201       for (bb=setFirstItem(ebbs[i]->succList); 
202            bb; 
203            bb=setNextItem(ebbs[i]->succList)) {
204         fprintf (of, "%s ", bb->entryLabel->name);
205       }
206       fprintf (of, "\npredecessors: ");
207       for (bb=setFirstItem(ebbs[i]->predList); 
208            bb; 
209            bb=setNextItem(ebbs[i]->predList)) {
210         fprintf (of, "%s ", bb->entryLabel->name);
211       }
212       {
213         int d;
214         fprintf (of, "\ndominators: ");
215         for (d=0; d<ebbs[i]->domVect->size; d++) {
216           if (bitVectBitValue(ebbs[i]->domVect, d)) {
217             fprintf (of, "%s ", ebbs[d]->entryLabel->name);
218           }
219         }
220       }
221       fprintf (of, "\n");
222   
223       fprintf (of, "\ndefines bitVector :");
224       bitVectDebugOn (ebbs[i]->defSet, of);
225       fprintf (of, "\nlocal defines bitVector :");
226       bitVectDebugOn (ebbs[i]->ldefs, of);
227       fprintf (of, "\npointers Set bitvector :");
228       bitVectDebugOn (ebbs[i]->ptrsSet, of);
229       if (ebbs[i]->isLastInLoop) {
230               fprintf (of, "\nInductions Set bitvector :");
231               bitVectDebugOn (ebbs[i]->linds, of);
232       }
233       fprintf (of, "\n----------------------------------------------------------------\n");
234       printiCChain (ebbs[i]->sch, of);
235     }
236   fflush(of);
237 }
238
239 /*-----------------------------------------------------------------*/
240 /* iCode2eBBlock - converts a sequnce till label to a ebb          */
241 /*-----------------------------------------------------------------*/
242 eBBlock *
243 iCode2eBBlock (iCode * ic)
244 {
245   iCode *loop;
246   eBBlock *ebb = neweBBlock (); /* allocate an entry */
247
248   /* put the first one unconditionally */
249   ebb->sch = ic;
250
251   /* if this is a label then */
252   if (ic->op == LABEL)
253     ebb->entryLabel = ic->label;
254   else
255     {
256       SNPRINTF (buffer, sizeof(buffer), "_eBBlock%d", eBBNum++);
257       ebb->entryLabel = newSymbol (buffer, 1);
258       ebb->entryLabel->key = labelKey++;
259     }
260
261   if (ic &&
262       (ic->op == GOTO ||
263        ic->op == JUMPTABLE ||
264        ic->op == IFX))
265     {
266       ebb->ech = ebb->sch;
267       return ebb;
268     }
269
270   if ((ic->next && ic->next->op == LABEL) ||
271       !ic->next)
272     {
273       ebb->ech = ebb->sch;
274       return ebb;
275     }
276
277   /* loop thru till we find one with a label */
278   for (loop = ic->next; loop; loop = loop->next)
279     {
280
281       /* if this is the last one */
282       if (!loop->next)
283         break;
284       /* if this is a function call */
285       if (loop->op == CALL || loop->op == PCALL)
286         {
287           ebb->hasFcall = 1;
288           if (currFunc)
289             FUNC_HASFCALL(currFunc->type) = 1;
290         }
291
292       /* if the next one is a label */
293       /* if this is a goto or ifx */
294       if (loop->next->op == LABEL ||
295           loop->op == GOTO ||
296           loop->op == JUMPTABLE ||
297           loop->op == IFX)
298         break;
299     }
300
301   /* mark the end of the chain */
302   ebb->ech = loop;
303
304   return ebb;
305 }
306
307 /*-----------------------------------------------------------------*/
308 /* eBBWithEntryLabel - finds the basic block with the entry label  */
309 /*-----------------------------------------------------------------*/
310 eBBlock *
311 eBBWithEntryLabel (eBBlock ** ebbs, symbol * eLabel, int count)
312 {
313   int i;
314
315   for (i = 0; i < count; i++)
316     {
317       if (isSymbolEqual (ebbs[i]->entryLabel, eLabel))
318         return ebbs[i];
319     }
320
321   return NULL;
322 }
323
324
325 /*-----------------------------------------------------------------*/
326 /* ifFromIs - will return 1 if the from block matches this         */
327 /*-----------------------------------------------------------------*/
328 DEFSETFUNC (ifFromIs)
329 {
330   edge *ep = item;
331   V_ARG (eBBlock *, this);
332
333   if (ep->from == this)
334     return 1;
335
336   return 0;
337 }
338
339
340 /*-----------------------------------------------------------------*/
341 /* edgesTo  - returns a set of edges with to == supplied value     */
342 /*-----------------------------------------------------------------*/
343 set *
344 edgesTo (eBBlock * to)
345 {
346   set *result = NULL;
347   edge *loop;
348
349   for (loop = setFirstItem (graphEdges); loop; loop = setNextItem (graphEdges))
350     if (loop->to == to && !loop->from->noPath)
351       addSet (&result, loop->from);
352
353   return result;
354 }
355
356
357 /*-----------------------------------------------------------------*/
358 /* addiCodeToeBBlock - will add an iCode to the end of a block     */
359 /*-----------------------------------------------------------------*/
360 void 
361 addiCodeToeBBlock (eBBlock * ebp, iCode * ic, iCode * ip)
362 {
363   ic->prev = ic->next = NULL;
364   /* if the insert point is given */
365   if (ip)
366     {
367       ic->lineno = ip->lineno;
368       ic->prev = ip->prev;
369       ip->prev = ic;
370       ic->next = ip;
371       if (!ic->prev)
372         ebp->sch = ic;
373       else
374         ic->prev->next = ic;
375       return;
376     }
377
378   /* if the block has no  instructions */
379   if (ebp->ech == NULL)
380     {
381       ebp->sch = ebp->ech = ic;
382       ic->next = NULL;
383       return;
384     }
385
386   /* if the last instruction is a goto */
387   /* we add it just before the goto    */
388   if (ebp->ech->op == GOTO || ebp->ech->op == JUMPTABLE
389       || ebp->ech->op == RETURN)
390     {
391       ic->lineno = ebp->ech->lineno;
392       ic->prev = ebp->ech->prev;
393       ebp->ech->prev = ic;
394       ic->next = ebp->ech;
395       if (!ic->prev)            /* was the last only on in the block */
396         ebp->sch = ic;
397       else
398         ic->prev->next = ic;
399       return;
400     }
401
402   /* if the last one was a ifx statement we check to see */
403   /* if the condition was defined in the previous instruction */
404   /* if this is true then we put it before the condition else */
405   /* we put it before if, this is to reduce register pressure, */
406   /* we don't have to hold  condition too long in a register  */
407   if (ebp->ech->op == IFX)
408     {
409       iCode *ipoint;
410
411 /*  if ( !ebp->ech->prev )  */
412 /*      ipoint = ebp->ech ; */
413 /*  else  */
414 /*      if (!IC_RESULT(ebp->ech->prev)) */
415 /*    ipoint = ebp->ech ; */
416 /*      else */
417 /*    if (IC_COND(ebp->ech)->key == IC_RESULT(ebp->ech->prev)->key) */
418 /*        ipoint = ebp->ech->prev; */
419 /*    else */
420 /*        ipoint = ebp->ech ; */
421       ipoint = ebp->ech;
422       ic->lineno = ipoint->lineno;
423       ic->prev = ipoint->prev;
424       ipoint->prev = ic;
425       ic->next = ipoint;
426       if (!ic->prev)
427         ebp->sch = ic;
428       else
429         ic->prev->next = ic;
430       return;
431     }
432
433   /* will add it to the very end */
434   ip = ebp->ech;
435   ip->next = ic;
436   ic->prev = ip;
437   ic->next = NULL;
438   ebp->ech = ic;
439
440   return;
441 }
442
443 /*-----------------------------------------------------------------*/
444 /* remiCodeFromeBBlock - remove an iCode from BBlock               */
445 /*-----------------------------------------------------------------*/
446 void 
447 remiCodeFromeBBlock (eBBlock * ebb, iCode * ic)
448 {
449   wassert (ic->seq>=ebb->fSeq && ic->seq<=ebb->lSeq);
450   if (ic->prev)
451     ic->prev->next = ic->next;
452   else
453     ebb->sch = ic->next;
454
455   if (ic->next)
456     ic->next->prev = ic->prev;
457   else
458     ebb->ech = ic->prev;
459 }
460
461 /*-----------------------------------------------------------------*/
462 /* iCodeBreakDown : breakDown iCode chain to blocks                */
463 /*-----------------------------------------------------------------*/
464 eBBlock **
465 iCodeBreakDown (iCode * ic, int *count)
466 {
467   eBBlock **ebbs = NULL;
468   iCode *loop = ic;
469
470   *count = 0;
471
472   /* allocate for the first entry */
473
474   ebbs = Safe_alloc (sizeof (eBBlock **));
475
476   while (loop)
477     {
478
479       /* convert 2 block */
480       eBBlock *ebb = iCode2eBBlock (loop);
481       loop = ebb->ech->next;
482
483       ebb->ech->next = NULL;    /* mark the end of this chain */
484       if (loop)
485         loop->prev = NULL;
486       ebb->bbnum = *count;      /* save this block number     */
487       /* put it in the array */
488       ebbs[(*count)++] = ebb;
489
490       /* allocate for the next one. Remember to clear the new */
491       /*  pointer at the end, that was created by realloc. */
492
493       ebbs = Safe_realloc (ebbs, (*count + 1) * sizeof (eBBlock **));
494
495       ebbs[*count] = 0;
496
497       /* if this one ends in a goto or a conditional */
498       /* branch then check if the block it is going  */
499       /* to already exists, if yes then this could   */
500       /* be a loop, add a preheader to the block it  */
501       /* goes to  if it does not already have one    */
502       if (ebbs[(*count) - 1]->ech &&
503           (ebbs[(*count) - 1]->ech->op == GOTO ||
504            ebbs[(*count) - 1]->ech->op == IFX))
505         {
506
507           symbol *label;
508           eBBlock *destBlock;
509
510           if (ebbs[(*count) - 1]->ech->op == GOTO)
511             label = IC_LABEL (ebbs[(*count) - 1]->ech);
512           else if (!(label = IC_TRUE (ebbs[(*count) - 1]->ech)))
513             label = IC_FALSE (ebbs[(*count) - 1]->ech);
514
515           if ((destBlock = eBBWithEntryLabel (ebbs, label, (*count))) &&
516               destBlock->preHeader == NULL &&
517               otherPathsPresent (ebbs, destBlock))
518             {
519
520               symbol *preHeaderLabel = newiTempPreheaderLabel ();
521               int i, j;
522               eBBlock *pBlock;
523
524               /* go thru all block replacing the entryLabel with new label */
525               /* till we reach the block , then we insert a new ebblock    */
526               for (i = 0; i < (*count); i++)
527                 {
528                   if (ebbs[i] == destBlock)
529                     break;
530                   replaceLabel (ebbs[i], label, preHeaderLabel);
531                 }
532
533               (*count)++;
534
535               /* if we have stopped at the block , allocate for an extra one */
536
537               ebbs = Safe_realloc (ebbs, (*count + 1) * sizeof (eBBlock **));
538
539               ebbs[*count] = 0;
540
541               /* then move the block down one count */
542               pBlock = ebbs[j = i];
543               for (i += 1; i < (*count); i++)
544                 {
545                   eBBlock *xBlock;
546
547                   xBlock = ebbs[i];
548                   ebbs[i] = pBlock;
549                   ebbs[i]->bbnum = i;
550                   pBlock = xBlock;
551                 }
552
553               destBlock->preHeader = ebbs[j] = neweBBlock ();
554               ebbs[j]->bbnum = j;
555               ebbs[j]->entryLabel = preHeaderLabel;
556               ebbs[j]->sch = ebbs[j]->ech = newiCodeLabelGoto (LABEL, preHeaderLabel);
557               ebbs[j]->sch->lineno = destBlock->sch->lineno;
558             }
559         }
560     }
561
562   /* mark the end */
563   ebbs[*count] = NULL;
564
565   return ebbs;
566 }
567
568 /*-----------------------------------------------------------------*/
569 /* replaceSymBySym : - replace operand by operand in blocks        */
570 /*                     replaces only left & right in blocks        */
571 /*-----------------------------------------------------------------*/
572 void 
573 replaceSymBySym (set * sset, operand * src, operand * dest)
574 {
575   set *loop;
576   eBBlock *rBlock;
577
578   /* for all blocks in the set do */
579   for (loop = sset; loop; loop = loop->next)
580     {
581       iCode *ic;
582
583       rBlock = loop->item;
584       /* for all instructions in this block do */
585       for (ic = rBlock->sch; ic; ic = ic->next)
586         {
587
588           /* if we find usage */
589           if (ic->op == IFX && isOperandEqual (src, IC_COND (ic)))
590             {
591               bitVectUnSetBit (OP_USES (IC_COND (ic)), ic->key);
592               IC_COND (ic) = operandFromOperand (dest);
593               OP_USES(dest)=bitVectSetBit (OP_USES (dest), ic->key);
594               continue;
595             }
596
597           if (isOperandEqual (IC_RIGHT (ic), src))
598             {
599               bitVectUnSetBit (OP_USES (IC_RIGHT (ic)), ic->key);
600               IC_RIGHT (ic) = operandFromOperand (dest);
601               IC_RIGHT (ic)->isaddr = 0;
602               OP_USES(dest)=bitVectSetBit (OP_USES (dest), ic->key);
603             }
604
605           if (isOperandEqual (IC_LEFT (ic), src))
606             {
607               bitVectUnSetBit (OP_USES (IC_LEFT (ic)), ic->key);
608               if (POINTER_GET (ic) && IS_ITEMP (dest))
609                 {
610                   IC_LEFT (ic) = operandFromOperand (dest);
611                   IC_LEFT (ic)->isaddr = 1;
612                 }
613               else
614                 {
615                   IC_LEFT (ic) = operandFromOperand (dest);
616                   IC_LEFT (ic)->isaddr = 0;
617                 }
618               OP_USES(dest)=bitVectSetBit (OP_USES (dest), ic->key);
619             }
620
621           /* special case for pointer sets */
622           if (POINTER_SET (ic) &&
623               isOperandEqual (IC_RESULT (ic), src))
624             {
625               bitVectUnSetBit (OP_USES (IC_RESULT (ic)), ic->key);
626               IC_RESULT (ic) = operandFromOperand (dest);
627               IC_RESULT (ic)->isaddr = 1;
628               OP_USES(dest)=bitVectSetBit (OP_USES (dest), ic->key);
629             }
630         }
631     }
632 }
633
634 /*-----------------------------------------------------------------*/
635 /* replaceLabel - replace reference to one label by another        */
636 /*-----------------------------------------------------------------*/
637 void 
638 replaceLabel (eBBlock * ebp, symbol * fromLbl, symbol * toLbl)
639 {
640   iCode *ic;
641
642   if (!ebp)
643     return;
644
645   for (ic = ebp->sch; ic; ic = ic->next)
646     {
647       switch (ic->op)
648         {
649
650         case GOTO:
651           if (isSymbolEqual (IC_LABEL (ic), fromLbl))
652             IC_LABEL (ic) = toLbl;
653           break;
654
655         case IFX:
656           if (IC_TRUE (ic) && isSymbolEqual (IC_TRUE (ic), fromLbl))
657             IC_TRUE (ic) = toLbl;
658           else if (isSymbolEqual (IC_FALSE (ic), fromLbl))
659             IC_FALSE (ic) = toLbl;
660           break;
661         }
662     }
663
664   return;
665
666 }
667
668
669 /*-----------------------------------------------------------------*/
670 /* iCodeFromeBBlock - convert basic block to iCode chain           */
671 /*-----------------------------------------------------------------*/
672 iCode *
673 iCodeFromeBBlock (eBBlock ** ebbs, int count)
674 {
675   int i = 1;
676   iCode *ric = ebbs[0]->sch;
677   iCode *lic = ebbs[0]->ech;
678
679   for (; i < count; i++)
680     {
681       if (ebbs[i]->sch == NULL)
682         continue;
683
684       if (ebbs[i]->noPath &&
685           (ebbs[i]->entryLabel != entryLabel &&
686            ebbs[i]->entryLabel != returnLabel))
687         {
688           werror (W_CODE_UNREACH, ebbs[i]->sch->filename, ebbs[i]->sch->lineno);
689           continue;
690         }
691
692       lic->next = ebbs[i]->sch;
693       lic->next->prev = lic;
694       lic = ebbs[i]->ech;
695     }
696
697   return ric;
698 }
699
700 /*-----------------------------------------------------------------*/
701 /* otherPathsPresent - determines if there is a path from _entry   */
702 /*      to this block in a half constructed set of blocks          */
703 /*-----------------------------------------------------------------*/
704 int 
705 otherPathsPresent (eBBlock ** ebbs, eBBlock * this)
706 {
707   int i;
708
709   /* for all blocks preceding this block */
710   for (i = 0; i < this->bbnum; i++)
711     {
712       iCode *ic;
713
714       /* if there is a reference to the entry label of this block */
715       for (ic = ebbs[i]->sch; ic; ic = ic->next)
716         {
717           switch (ic->op)
718             {
719             case GOTO:
720               if (IC_LABEL (ic)->key == this->entryLabel->key)
721                 return 1;
722               break;
723
724             case IFX:
725               if (IC_TRUE (ic))
726                 {
727                   if (IC_TRUE (ic)->key == this->entryLabel->key)
728                     return 1;
729                 }
730               else if (IC_FALSE (ic)->key == this->entryLabel->key)
731                 return 1;
732               break;
733             }
734         }
735     }
736
737   /* comes here means we have not found it yet */
738   /* in this case check if the previous block  */
739   /* ends in a goto if it does then we have no */
740   /* path else we have a path                  */
741   if (this->bbnum && ebbs[this->bbnum - 1]->ech &&
742       ebbs[this->bbnum - 1]->ech->op == GOTO)
743     return 0;
744   else
745     return 1;
746 }