fixed bug #460088
[fw/sdcc] / src / SDCCopt.c
1 /*-------------------------------------------------------------------------
2   SDCCopt.c - calls all the optimizations routines and does some of the
3               hackier transformations, these include translating iCodes
4               to function calls and replacing local variables with their
5               register equivalents etc. Also contains the driver routine
6               for dead code elimination
7
8              Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
9
10    This program is free software; you can redistribute it and/or modify it
11    under the terms of the GNU General Public License as published by the
12    Free Software Foundation; either version 2, or (at your option) any
13    later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23    
24    In other words, you are welcome to use, share and improve this program.
25    You are forbidden to forbid anyone else to use, share and improve
26    what you give them.   Help stamp out software-hoarding!  
27 -------------------------------------------------------------------------*/
28
29 #include "common.h"
30
31 /*-----------------------------------------------------------------*/
32 /* global variables */
33 int cseDefNum = 0;
34
35 char flowChanged = 0;
36
37
38 /*-----------------------------------------------------------------*/
39 /* printSymName - prints the symbol names                          */
40 /*-----------------------------------------------------------------*/
41 int 
42 printSymName (void *vsym)
43 {
44   symbol *sym = vsym;
45   fprintf (stdout, " %s ", sym->name);
46   return 0;
47 }
48
49 /*-----------------------------------------------------------------*/
50 /* cnvToFcall - does the actual conversion to function call        */
51 /*-----------------------------------------------------------------*/
52 static void 
53 cnvToFcall (iCode * ic, eBBlock * ebp)
54 {
55   iCode *ip;
56   iCode *newic;
57   operand *left;
58   operand *right;
59   symbol *func = NULL;
60   int lineno = ic->lineno;
61   int bytesPushed=0;
62
63   ip = ic->next;                /* insertion point */
64   /* remove it from the iCode */
65   remiCodeFromeBBlock (ebp, ic);
66
67   left = IC_LEFT (ic);
68   right = IC_RIGHT (ic);
69
70   switch (ic->op)
71     {
72     case '+':
73       func = __fsadd;
74       break;
75     case '-':
76       func = __fssub;
77       break;
78     case '/':
79       func = __fsdiv;
80       break;
81     case '*':
82       func = __fsmul;
83       break;
84     case EQ_OP:
85       func = __fseq;
86       break;
87     case NE_OP:
88       func = __fsneq;
89       break;
90     case '<':
91       func = __fslt;
92       break;
93     case '>':
94       func = __fsgt;
95       break;
96     case LE_OP:
97       func = __fslteq;
98       break;
99     case GE_OP:
100       func = __fsgteq;
101       break;
102     }
103
104   /* if float support routines NOT compiled as reentrant */
105   if (!options.float_rent)
106     {
107
108       /* first one */
109       if (IS_REGPARM (FUNC_ARGS(func->type)->etype))
110         {
111           newic = newiCode (SEND, IC_LEFT (ic), NULL);
112           newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype);
113         }
114       else
115         {
116           newic = newiCode ('=', NULL, IC_LEFT (ic));
117           IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type));
118         }
119
120       addiCodeToeBBlock (ebp, newic, ip);
121       newic->lineno = lineno;
122
123       /* second one */
124       if (IS_REGPARM (FUNC_ARGS(func->type)->next->etype))
125         {
126           newic = newiCode (SEND, IC_RIGHT (ic), NULL);
127           newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->next->etype);
128         }
129       else
130         {
131           newic = newiCode ('=', NULL, IC_RIGHT (ic));
132           IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)->next);
133         }
134       addiCodeToeBBlock (ebp, newic, ip);
135       newic->lineno = lineno;
136
137     }
138   else
139     {
140
141       /* push right */
142       if (IS_REGPARM (FUNC_ARGS(func->type)->next->etype))
143         {
144           newic = newiCode (SEND, right, NULL);
145           newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->next->etype);
146         }
147       else
148         {
149           newic = newiCode (IPUSH, right, NULL);
150           newic->parmPush = 1;
151           bytesPushed+=4;
152         }
153
154       addiCodeToeBBlock (ebp, newic, ip);
155       newic->lineno = lineno;
156
157       /* insert push left */
158       if (IS_REGPARM (FUNC_ARGS(func->type)->etype))
159         {
160           newic = newiCode (SEND, left, NULL);
161           newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype);
162         }
163       else
164         {
165           newic = newiCode (IPUSH, left, NULL);
166           newic->parmPush = 1;
167           bytesPushed+=4;
168         }
169       addiCodeToeBBlock (ebp, newic, ip);
170       newic->lineno = lineno;
171     }
172   /* insert the call */
173   newic = newiCode (CALL, operandFromSymbol (func), NULL);
174   IC_RESULT (newic) = IC_RESULT (ic);
175   newic->lineno = lineno;
176   newic->parmBytes+=bytesPushed;
177   addiCodeToeBBlock (ebp, newic, ip);
178 }
179
180 /*-----------------------------------------------------------------*/
181 /* cnvToFloatCast - converts casts to floats to function calls     */
182 /*-----------------------------------------------------------------*/
183 static void 
184 cnvToFloatCast (iCode * ic, eBBlock * ebp)
185 {
186   iCode *ip, *newic;
187   symbol *func = NULL;
188   sym_link *type = operandType (IC_RIGHT (ic));
189   int linenno = ic->lineno;
190   int bwd, su;
191
192   ip = ic->next;
193   /* remove it from the iCode */
194   remiCodeFromeBBlock (ebp, ic);
195   /* depending on the type */
196   for (bwd = 0; bwd < 3; bwd++)
197     {
198       for (su = 0; su < 2; su++)
199         {
200           if (compareType (type, __multypes[bwd][su]) == 1)
201             {
202               func = __conv[0][bwd][su];
203               goto found;
204             }
205         }
206     }
207   assert (0);
208 found:
209
210   /* if float support routines NOT compiled as reentrant */
211   if (!options.float_rent)
212     {
213       /* first one */
214         if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) 
215             {
216                 newic = newiCode (SEND, IC_RIGHT (ic), NULL);
217                 newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype);
218             }
219       else
220         {
221           newic = newiCode ('=', NULL, IC_RIGHT (ic));
222           IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type));
223         }
224       addiCodeToeBBlock (ebp, newic, ip);
225       newic->lineno = linenno;
226
227     }
228   else
229     {
230       /* push the left */
231         if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) {
232             newic = newiCode (SEND, IC_RIGHT (ic), NULL);
233             newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype);
234         }
235       else
236         {
237           newic = newiCode (IPUSH, IC_RIGHT (ic), NULL);
238           newic->parmPush = 1;
239         }
240       addiCodeToeBBlock (ebp, newic, ip);
241       newic->lineno = linenno;
242
243     }
244
245   /* make the call */
246   newic = newiCode (CALL, operandFromSymbol (func), NULL);
247   IC_RESULT (newic) = IC_RESULT (ic);
248   addiCodeToeBBlock (ebp, newic, ip);
249   newic->lineno = linenno;
250
251 }
252
253 /*-----------------------------------------------------------------*/
254 /* cnvFromFloatCast - converts casts From floats to function calls */
255 /*-----------------------------------------------------------------*/
256 static void 
257 cnvFromFloatCast (iCode * ic, eBBlock * ebp)
258 {
259   iCode *ip, *newic;
260   symbol *func = NULL;
261   sym_link *type = operandType (IC_LEFT (ic));
262   int lineno = ic->lineno;
263   int bwd, su;
264
265   ip = ic->next;
266   /* remove it from the iCode */
267   remiCodeFromeBBlock (ebp, ic);
268
269   /* depending on the type */
270   for (bwd = 0; bwd < 3; bwd++)
271     {
272       for (su = 0; su < 2; su++)
273         {
274           if (compareType (type, __multypes[bwd][su]) == 1)
275             {
276               func = __conv[1][bwd][su];
277               goto found;
278             }
279         }
280     }
281   assert (0);
282 found:
283
284   /* if float support routines NOT compiled as reentrant */
285   if (!options.float_rent)
286     {
287       /* first one */
288         if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) {
289             newic = newiCode (SEND, IC_RIGHT (ic), NULL);
290             newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype);
291         }
292       else
293         {
294           newic = newiCode ('=', NULL, IC_RIGHT (ic));
295           IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type));
296         }
297       addiCodeToeBBlock (ebp, newic, ip);
298       newic->lineno = lineno;
299
300     }
301   else
302     {
303
304       /* push the left */
305         if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) {
306             newic = newiCode (SEND, IC_RIGHT (ic), NULL);
307             newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype);
308         }
309       else
310         {
311           newic = newiCode (IPUSH, IC_RIGHT (ic), NULL);
312           newic->parmPush = 1;
313         }
314       addiCodeToeBBlock (ebp, newic, ip);
315       newic->lineno = lineno;
316
317     }
318
319   /* make the call */
320   newic = newiCode (CALL, operandFromSymbol (func), NULL);
321   IC_RESULT (newic) = IC_RESULT (ic);
322   addiCodeToeBBlock (ebp, newic, ip);
323   newic->lineno = lineno;
324
325 }
326
327 /*-----------------------------------------------------------------*/
328 /* convilong - converts int or long mults or divs to fcalls        */
329 /*-----------------------------------------------------------------*/
330 static void 
331 convilong (iCode * ic, eBBlock * ebp, sym_link * type, int op)
332 {
333   symbol *func = NULL;
334   iCode *ip = ic->next;
335   iCode *newic;
336   int lineno = ic->lineno;
337   int bwd;
338   int su;
339   int bytesPushed=0;
340
341   remiCodeFromeBBlock (ebp, ic);
342
343   /* depending on the type */
344   for (bwd = 0; bwd < 3; bwd++)
345     {
346       for (su = 0; su < 2; su++)
347         {
348           if (compareType (type, __multypes[bwd][su]) == 1)
349             {
350               if (op == '*')
351                 func = __muldiv[0][bwd][su];
352               else if (op == '/')
353                 func = __muldiv[1][bwd][su];
354               else if (op == '%')
355                 func = __muldiv[2][bwd][su];
356               else if (op == RRC)
357                 func = __rlrr[1][bwd][su];
358               else if (op == RLC)
359                 func = __rlrr[0][bwd][su];
360               else if (op == RIGHT_OP)
361                 func = __rlrr[1][bwd][su];
362               else if (op == LEFT_OP)
363                 func = __rlrr[0][bwd][su];
364               else
365                 assert (0);
366               goto found;
367             }
368         }
369     }
370   assert (0);
371 found:
372   /* if int & long support routines NOT compiled as reentrant */
373   if (!options.intlong_rent)
374     {
375       /* first one */
376         if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) {
377             newic = newiCode (SEND, IC_LEFT (ic), NULL);
378             newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype);
379         }
380       else
381         {
382           newic = newiCode ('=', NULL, IC_LEFT (ic));
383           IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type));
384         }
385       addiCodeToeBBlock (ebp, newic, ip);
386       newic->lineno = lineno;
387
388       /* second one */
389       if (IS_REGPARM (FUNC_ARGS(func->type)->next->etype)) {
390           newic = newiCode (SEND, IC_RIGHT (ic), NULL);
391           newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->next->etype);
392       }
393       else
394         {
395           newic = newiCode ('=', NULL, IC_RIGHT (ic));
396           IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)->next);
397         }
398       addiCodeToeBBlock (ebp, newic, ip);
399       newic->lineno = lineno;
400
401     }
402   else
403     {
404       /* compiled as reentrant then push */
405       /* push right */
406       if (IS_REGPARM (FUNC_ARGS(func->type)->next->etype))
407         {
408           newic = newiCode (SEND, IC_RIGHT (ic), NULL);
409           newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->next->etype);
410         }
411       else
412         {
413           newic = newiCode (IPUSH, IC_RIGHT (ic), NULL);
414           newic->parmPush = 1;
415
416           bytesPushed += getSize(operandType(IC_RIGHT(ic)));
417         }
418       addiCodeToeBBlock (ebp, newic, ip);
419       newic->lineno = lineno;
420
421       /* insert push left */
422       if (IS_REGPARM (FUNC_ARGS(func->type)->etype))
423         {
424           newic = newiCode (SEND, IC_LEFT (ic), NULL);
425           newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype);
426         }
427       else
428         {
429           newic = newiCode (IPUSH, IC_LEFT (ic), NULL);
430           newic->parmPush = 1;
431
432           bytesPushed += getSize(operandType(IC_LEFT(ic)));
433         }
434       addiCodeToeBBlock (ebp, newic, ip);
435       newic->lineno = lineno;
436
437     }
438
439   /* for the result */
440   newic = newiCode (CALL, operandFromSymbol (func), NULL);
441   IC_RESULT (newic) = IC_RESULT (ic);
442   newic->lineno = lineno;
443   newic->parmBytes+=bytesPushed; // to clear the stack after the call
444   addiCodeToeBBlock (ebp, newic, ip);
445 }
446
447 /*-----------------------------------------------------------------*/
448 /* convertToFcall - converts some operations to fcalls             */
449 /*-----------------------------------------------------------------*/
450 static void 
451 convertToFcall (eBBlock ** ebbs, int count)
452 {
453   int i;
454
455   /* for all blocks do */
456   for (i = 0; i < count; i++)
457     {
458       iCode *ic;
459
460       /* for all instructions in the block do */
461       for (ic = ebbs[i]->sch; ic; ic = ic->next)
462         {
463
464           /* floating point operations are
465              converted to function calls */
466           if ((IS_CONDITIONAL (ic) ||
467                IS_ARITHMETIC_OP (ic)) &&
468               (IS_FLOAT (operandType (IC_RIGHT (ic)))))
469             {
470
471               cnvToFcall (ic, ebbs[i]);
472             }
473
474           /* casting is a little different */
475           if (ic->op == CAST)
476             {
477               if (IS_FLOAT (operandType (IC_RIGHT (ic))))
478                 cnvFromFloatCast (ic, ebbs[i]);
479               else if (IS_FLOAT (operandType (IC_LEFT (ic))))
480                 cnvToFloatCast (ic, ebbs[i]);
481             }
482
483           /* if long / int mult or divide or mod */
484           if (ic->op == '*' || ic->op == '/' || ic->op == '%')
485             {
486               sym_link *leftType = operandType (IC_LEFT (ic));
487
488               if (IS_INTEGRAL (leftType) && getSize (leftType) > port->support.muldiv)
489                 {
490                   sym_link *rightType = operandType (IC_RIGHT (ic));
491
492                   if (port->hasNativeMulFor != NULL &&
493                       port->hasNativeMulFor (ic, leftType, rightType))
494                     {
495                       /* Leave as native */
496                     }
497                   else
498                     {
499                       convilong (ic, ebbs[i], leftType, ic->op);
500                     }
501                 }
502             }
503           
504           if (ic->op == RRC || ic->op == RLC || ic->op == LEFT_OP || ic->op == RIGHT_OP)
505             {
506               sym_link *type = operandType (IC_LEFT (ic));
507
508               if (IS_INTEGRAL (type) && getSize (type) > port->support.shift && port->support.shift >= 0)
509                 {
510                   convilong (ic, ebbs[i], type, ic->op);
511                 }
512             }
513         }
514     }
515 }
516
517 /*-----------------------------------------------------------------*/
518 /* replaceRegEqv - replace all local variables with their reqv     */
519 /*-----------------------------------------------------------------*/
520 static void 
521 replaceRegEqv (eBBlock ** ebbs, int count)
522 {
523   int i;
524
525   for (i = 0; i < count; i++)
526     {
527
528       iCode *ic;
529
530       for (ic = ebbs[i]->sch; ic; ic = ic->next)
531         {
532
533           if (SKIP_IC2 (ic))
534             continue;
535
536           if (ic->op == IFX)
537             {
538
539               if (IS_TRUE_SYMOP (IC_COND (ic)) &&
540                   OP_REQV (IC_COND (ic)))
541                 IC_COND (ic) = opFromOpWithDU (OP_REQV (IC_COND (ic)),
542                                              OP_SYMBOL (IC_COND (ic))->defs,
543                                             OP_SYMBOL (IC_COND (ic))->uses);
544
545               continue;
546             }
547
548           if (ic->op == JUMPTABLE)
549             {
550               if (IS_TRUE_SYMOP (IC_JTCOND (ic)) &&
551                   OP_REQV (IC_JTCOND (ic)))
552                 IC_JTCOND (ic) = opFromOpWithDU (OP_REQV (IC_JTCOND (ic)),
553                                            OP_SYMBOL (IC_JTCOND (ic))->defs,
554                                           OP_SYMBOL (IC_JTCOND (ic))->uses);
555               continue;
556             }
557
558           if (ic->op == RECEIVE)
559             {
560               if (OP_SYMBOL (IC_RESULT (ic))->addrtaken)
561                 OP_SYMBOL (IC_RESULT (ic))->isspilt = 1;
562             }
563
564           /* general case */
565           if (IC_RESULT (ic) &&
566               IS_TRUE_SYMOP (IC_RESULT (ic)) &&
567               OP_REQV (IC_RESULT (ic)))
568             {
569               if (POINTER_SET (ic))
570                 {
571                   IC_RESULT (ic) = opFromOpWithDU (OP_REQV (IC_RESULT (ic)),
572                                            OP_SYMBOL (IC_RESULT (ic))->defs,
573                                           OP_SYMBOL (IC_RESULT (ic))->uses);
574                   IC_RESULT (ic)->isaddr = 1;
575                 }
576               else
577                 IC_RESULT (ic) = opFromOpWithDU (OP_REQV (IC_RESULT (ic)),
578                                            OP_SYMBOL (IC_RESULT (ic))->defs,
579                                           OP_SYMBOL (IC_RESULT (ic))->uses);
580             }
581
582           if (IC_RIGHT (ic) &&
583               IS_TRUE_SYMOP (IC_RIGHT (ic)) &&
584               OP_REQV (IC_RIGHT (ic)))
585             {
586               IC_RIGHT (ic) = opFromOpWithDU (OP_REQV (IC_RIGHT (ic)),
587                                             OP_SYMBOL (IC_RIGHT (ic))->defs,
588                                            OP_SYMBOL (IC_RIGHT (ic))->uses);
589               IC_RIGHT (ic)->isaddr = 0;
590             }
591
592           if (IC_LEFT (ic) &&
593               IS_TRUE_SYMOP (IC_LEFT (ic)) &&
594               OP_REQV (IC_LEFT (ic)))
595             {
596               IC_LEFT (ic) = opFromOpWithDU (OP_REQV (IC_LEFT (ic)),
597                                              OP_SYMBOL (IC_LEFT (ic))->defs,
598                                              OP_SYMBOL (IC_LEFT (ic))->uses);
599               IC_LEFT (ic)->isaddr = 0;
600             }
601         }
602     }
603 }
604
605 /*-----------------------------------------------------------------*/
606 /* killDeadCode - eliminates dead assignments                      */
607 /*-----------------------------------------------------------------*/
608 int 
609 killDeadCode (eBBlock ** ebbs, int count)
610 {
611   int change = 1;
612   int gchange = 0;
613   int i = 0;
614
615
616   /* basic algorithm :-                                          */
617   /* first the exclusion rules :-                                */
618   /*  1. if result is a global or volatile then skip             */
619   /*  2. if assignment and result is a temp & isaddr  then skip  */
620   /*     since this means array & pointer access, will be taken  */
621   /*     care of by alias analysis.                              */
622   /*  3. if the result is used in the remainder of the block skip */
623   /*  4. if this definition does not reach the end of the block  */
624   /*     i.e. the result is not present in the outExprs then KILL */
625   /*  5. if it reaches the end of block & is used by some success */
626   /*     or then skip                                            */
627   /*     else            KILL                                    */
628   /* this whole process is carried on iteratively till no change */
629   while (1)
630     {
631
632       change = 0;
633       /* for all blocks do */
634       for (i = 0; i < count; i++)
635         {
636           iCode *ic;
637
638           /* for all instructions in the block do */
639           for (ic = ebbs[i]->sch; ic; ic = ic->next)
640             {
641               int kill, j;
642               kill = 0;
643
644               if (SKIP_IC (ic) ||
645                   ic->op == IFX ||
646                   ic->op == RETURN)
647                 continue;
648
649               /* if the result is volatile then continue */
650               if (IC_RESULT (ic) && isOperandVolatile (IC_RESULT (ic), FALSE))
651                 continue;
652
653               /* if the result is a temp & isaddr then skip */
654               if (IC_RESULT (ic) && POINTER_SET (ic))
655                 continue;
656
657               /* if the result is used in the remainder of the */
658               /* block then skip */
659               if (usedInRemaining (IC_RESULT (ic), ic->next))
660                 continue;
661
662               /* does this definition reach the end of the block 
663                  or the usage is zero then we can kill */
664               if (!bitVectBitValue (ebbs[i]->outDefs, ic->key))
665                 kill = 1;       /* if not we can kill it */
666               else
667                 {
668                   /* if this is a global variable or function parameter */
669                   /* we cannot kill anyway             */
670                   if (isOperandGlobal (IC_RESULT (ic)) ||
671                       (OP_SYMBOL (IC_RESULT (ic))->_isparm &&
672                        !OP_SYMBOL (IC_RESULT (ic))->ismyparm))
673                     continue;
674
675                   /* if we are sure there are no usages */
676                   if (bitVectIsZero (OP_USES (IC_RESULT (ic))))
677                     {
678                       kill = 1;
679                       goto kill;
680                     }
681
682                   /* reset visited flag */
683                   for (j = 0; j < count; ebbs[j++]->visited = 0);
684
685                   /* find out if this definition is alive */
686                   if (applyToSet (ebbs[i]->succList,
687                                   isDefAlive,
688                                   ic))
689                     continue;
690
691                   kill = 1;
692                 }
693
694             kill:
695               /* kill this one if required */
696               if (kill)
697                 {
698                   printf ("kill ic %d\n", ic->key);
699                   change = 1;
700                   gchange++;
701                   /* eliminate this */
702                   remiCodeFromeBBlock (ebbs[i], ic);
703
704                   /* now delete from defUseSet */
705                   deleteItemIf (&ebbs[i]->outExprs, ifDiCodeIsX, ic);
706                   bitVectUnSetBit (ebbs[i]->outDefs, ic->key);
707
708                   /* and defset of the block */
709                   bitVectUnSetBit (ebbs[i]->defSet, ic->key);
710
711                   /* for the left & right remove the usage */
712                   if (IS_SYMOP (IC_LEFT (ic)))
713                     bitVectUnSetBit (OP_USES (IC_LEFT (ic)), ic->key);
714
715                   if (IS_SYMOP (IC_RIGHT (ic)))
716                     bitVectUnSetBit (OP_USES (IC_RIGHT (ic)), ic->key);
717                 }
718
719             }                   /* end of all instructions */
720
721           if (!ebbs[i]->sch && !ebbs[i]->noPath)
722             disconBBlock (ebbs[i], ebbs, count);
723
724         }                       /* end of for all blocks */
725
726       if (!change)
727         break;
728     }                           /* end of while(1) */
729
730   return gchange;
731 }
732
733 /*-----------------------------------------------------------------*/
734 /* printCyclomatic - prints the cyclomatic information             */
735 /*-----------------------------------------------------------------*/
736 static void 
737 printCyclomatic (eBBlock ** ebbs, int count)
738 {
739   int nEdges = elementsInSet (graphEdges);
740   int i, nNodes = 0;
741
742   for (i = 0; i < count; i++)
743     nNodes += (!ebbs[i]->noPath);
744
745   /* print the information */
746   werror (I_CYCLOMATIC, currFunc->name, nEdges, nNodes, nEdges - nNodes + 2);
747 }
748
749 /*-----------------------------------------------------------------*/
750 /* discardDeadParamReceives - remove any RECEIVE opcodes which     */
751 /* refer to dead variables.                                        */
752 /*-----------------------------------------------------------------*/
753 static void 
754 discardDeadParamReceives (eBBlock ** ebbs, int count)
755 {
756   int i;
757   iCode *ic;
758   iCode dummyIcode;
759
760   for (i = 0; i < count; i++)
761     {
762       for (ic = ebbs[i]->sch; ic; ic = ic->next)
763         {
764           if (ic->op == RECEIVE)
765             {
766               if (IC_RESULT (ic) && OP_SYMBOL (IC_RESULT (ic))
767                   && !OP_SYMBOL (IC_RESULT (ic))->used)
768                 {
769 #if 0
770                   fprintf (stderr, "discarding dead receive for %s\n",
771                            OP_SYMBOL (IC_RESULT (ic))->name);
772 #endif
773                   dummyIcode.next = ic->next;
774                   remiCodeFromeBBlock (ebbs[i], ic);
775                   ic = &dummyIcode;
776                 }
777             }
778         }
779     }
780 }
781
782 /*-----------------------------------------------------------------*/
783 /* eBBlockFromiCode - creates extended basic blocks from iCode     */
784 /*                    will return an array of eBBlock pointers     */
785 /*-----------------------------------------------------------------*/
786 eBBlock **
787 eBBlockFromiCode (iCode * ic)
788 {
789   eBBlock **ebbs = NULL;
790   int count = 0;
791   int saveCount = 0;
792   int change = 1;
793   int lchange = 0;
794   int kchange = 0;
795   hTab *loops;
796
797   /* if nothing passed then return nothing */
798   if (!ic)
799     return NULL;
800
801   count = 0;
802   eBBNum = 0;
803
804   /* optimize the chain for labels & gotos 
805      this will eliminate redundant labels and
806      will change jump to jumps by jumps */
807   ic = iCodeLabelOptimize (ic);
808
809   /* break it down into basic blocks */
810   ebbs = iCodeBreakDown (ic, &count);
811   saveCount = count;
812
813   /* compute the control flow */
814   computeControlFlow (ebbs, count, 0);
815
816   /* dumpraw if asked for */
817   if (options.dump_raw)
818     dumpEbbsToFileExt (DUMP_RAW0, ebbs, count);
819
820   /* replace the local variables with their
821      register equivalents : the liveRange computation
822      along with the register allocation will determine
823      if it finally stays in the registers */
824   replaceRegEqv (ebbs, count);
825
826   /* create loop regions */
827   loops = createLoopRegions (ebbs, count);
828
829   /* dumpraw if asked for */
830   if (options.dump_raw)
831     dumpEbbsToFileExt (DUMP_RAW1, ebbs, count);
832
833   /* do common subexpression elimination for each block */
834   change = cseAllBlocks (ebbs, saveCount, FALSE);
835
836   /* dumpraw if asked for */
837   if (options.dump_raw)
838     dumpEbbsToFileExt (DUMP_CSE, ebbs, count);
839
840   /* compute the data flow */
841   computeDataFlow (ebbs, saveCount);
842
843   /* dumpraw if asked for */
844   if (options.dump_raw)
845     dumpEbbsToFileExt (DUMP_DFLOW, ebbs, count);
846
847   /* global common subexpression elimination  */
848   if (optimize.global_cse)
849     {
850       change += cseAllBlocks (ebbs, saveCount, TRUE);
851       if (options.dump_gcse)
852         dumpEbbsToFileExt (DUMP_GCSE, ebbs, saveCount);
853     }
854   else
855     {
856       // compute the dataflow only
857       assert(cseAllBlocks (ebbs, saveCount, FALSE)==0);
858     }
859   /* kill dead code */
860   kchange = killDeadCode (ebbs, saveCount);
861
862   if (options.dump_kill)
863     dumpEbbsToFileExt (DUMP_DEADCODE, ebbs, count);
864
865   /* do loop optimizations */
866   change += (lchange = loopOptimizations (loops, ebbs, count));
867   if (options.dump_loop)
868     dumpEbbsToFileExt (DUMP_LOOP, ebbs, count);
869
870   /* recompute the data flow and apply global cse again 
871      if loops optimizations or dead code caused a change:
872      loops will brings out of the loop which then may be
873      available for use in the later blocks: dead code
874      elimination could potentially disconnect some blocks
875      conditional flow may be efected so we need to apply
876      subexpression once more */
877   if (lchange || kchange)
878     {
879       computeDataFlow (ebbs, saveCount);
880       change += cseAllBlocks (ebbs, saveCount, TRUE);
881       if (options.dump_loop)
882         dumpEbbsToFileExt (DUMP_LOOPG, ebbs, count);
883
884       /* if loop optimizations caused a change then do
885          dead code elimination once more : this will
886          get rid of the extra assignments to the induction
887          variables created during loop optimizations */
888       killDeadCode (ebbs, saveCount);
889
890       if (options.dump_loop)
891         dumpEbbsToFileExt (DUMP_LOOPD, ebbs, count);
892
893     }
894
895   /* sort it back by block number */
896   qsort (ebbs, saveCount, sizeof (eBBlock *), bbNumCompare);
897
898   if (!options.lessPedantic) {
899     // this is a good place to check missing return values
900     if (currFunc) {
901       if (!IS_VOID(currFunc->etype)) {
902         eBBlock *bp;
903         // make sure all predecessors of the last block end in a return
904         for (bp=setFirstItem(ebbs[saveCount-1]->predList); 
905              bp; 
906              bp=setNextItem(ebbs[saveCount-1]->predList)) {
907           if (bp->ech->op != RETURN) {
908             werror (W_VOID_FUNC, currFunc->name);
909           }
910         }
911       }
912     }
913   }
914
915   /* if cyclomatic info requested then print it */
916   if (options.cyclomatic)
917     printCyclomatic (ebbs, saveCount);
918
919   /* convert operations with support routines
920      written in C to function calls : Iam doing
921      this at this point since I want all the
922      operations to be as they are for optimzations */
923   convertToFcall (ebbs, count);
924
925   /* compute the live ranges */
926   computeLiveRanges (ebbs, count);
927
928   if (options.dump_range)
929     dumpEbbsToFileExt (DUMP_RANGE, ebbs, count);
930
931   /* Now that we have the live ranges, discard parameter
932    * receives for unused parameters.
933    */
934   discardDeadParamReceives (ebbs, count);
935
936   /* allocate registers & generate code */
937   port->assignRegisters (ebbs, count);
938
939   /* throw away blocks */
940   setToNull ((void **) &graphEdges);
941   ebbs = NULL;
942   
943   currFunc=NULL;
944
945   return NULL;
946 }
947
948
949 /* (add-hook 'c-mode-hook (lambda () (setq c-basic-offset 4))) */