* src/SDCCsymt.c (initCSupport): fix compile warning on Cygwin
[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                   change = 1;
699                   gchange++;
700                   /* eliminate this */
701                   remiCodeFromeBBlock (ebbs[i], ic);
702
703                   /* now delete from defUseSet */
704                   deleteItemIf (&ebbs[i]->outExprs, ifDiCodeIsX, ic);
705                   bitVectUnSetBit (ebbs[i]->outDefs, ic->key);
706
707                   /* and defset of the block */
708                   bitVectUnSetBit (ebbs[i]->defSet, ic->key);
709
710                   /* for the left & right remove the usage */
711                   if (IS_SYMOP (IC_LEFT (ic)))
712                     bitVectUnSetBit (OP_USES (IC_LEFT (ic)), ic->key);
713
714                   if (IS_SYMOP (IC_RIGHT (ic)))
715                     bitVectUnSetBit (OP_USES (IC_RIGHT (ic)), ic->key);
716                 }
717
718             }                   /* end of all instructions */
719
720           if (!ebbs[i]->sch && !ebbs[i]->noPath)
721             disconBBlock (ebbs[i], ebbs, count);
722
723         }                       /* end of for all blocks */
724
725       if (!change)
726         break;
727     }                           /* end of while(1) */
728
729   return gchange;
730 }
731
732 /*-----------------------------------------------------------------*/
733 /* printCyclomatic - prints the cyclomatic information             */
734 /*-----------------------------------------------------------------*/
735 static void 
736 printCyclomatic (eBBlock ** ebbs, int count)
737 {
738   int nEdges = elementsInSet (graphEdges);
739   int i, nNodes = 0;
740
741   for (i = 0; i < count; i++)
742     nNodes += (!ebbs[i]->noPath);
743
744   /* print the information */
745   werror (I_CYCLOMATIC, currFunc->name, nEdges, nNodes, nEdges - nNodes + 2);
746 }
747
748 /*-----------------------------------------------------------------*/
749 /* discardDeadParamReceives - remove any RECEIVE opcodes which     */
750 /* refer to dead variables.                                        */
751 /*-----------------------------------------------------------------*/
752 static void 
753 discardDeadParamReceives (eBBlock ** ebbs, int count)
754 {
755   int i;
756   iCode *ic;
757   iCode dummyIcode;
758
759   for (i = 0; i < count; i++)
760     {
761       for (ic = ebbs[i]->sch; ic; ic = ic->next)
762         {
763           if (ic->op == RECEIVE)
764             {
765               if (IC_RESULT (ic) && OP_SYMBOL (IC_RESULT (ic))
766                   && !OP_SYMBOL (IC_RESULT (ic))->used)
767                 {
768 #if 0
769                   fprintf (stderr, "discarding dead receive for %s\n",
770                            OP_SYMBOL (IC_RESULT (ic))->name);
771 #endif
772                   dummyIcode.next = ic->next;
773                   remiCodeFromeBBlock (ebbs[i], ic);
774                   ic = &dummyIcode;
775                 }
776             }
777         }
778     }
779 }
780
781 /*-----------------------------------------------------------------*/
782 /* eBBlockFromiCode - creates extended basic blocks from iCode     */
783 /*                    will return an array of eBBlock pointers     */
784 /*-----------------------------------------------------------------*/
785 eBBlock **
786 eBBlockFromiCode (iCode * ic)
787 {
788   eBBlock **ebbs = NULL;
789   int count = 0;
790   int saveCount = 0;
791   int change = 1;
792   int lchange = 0;
793   int kchange = 0;
794   hTab *loops;
795
796   /* if nothing passed then return nothing */
797   if (!ic)
798     return NULL;
799
800   count = 0;
801   eBBNum = 0;
802
803   /* optimize the chain for labels & gotos 
804      this will eliminate redundant labels and
805      will change jump to jumps by jumps */
806   ic = iCodeLabelOptimize (ic);
807
808   /* break it down into basic blocks */
809   ebbs = iCodeBreakDown (ic, &count);
810   saveCount = count;
811
812   /* compute the control flow */
813   computeControlFlow (ebbs, count, 0);
814
815   /* dumpraw if asked for */
816   if (options.dump_raw)
817     dumpEbbsToFileExt (DUMP_RAW0, ebbs, count);
818
819   /* replace the local variables with their
820      register equivalents : the liveRange computation
821      along with the register allocation will determine
822      if it finally stays in the registers */
823   replaceRegEqv (ebbs, count);
824
825   /* create loop regions */
826   loops = createLoopRegions (ebbs, count);
827
828   /* dumpraw if asked for */
829   if (options.dump_raw)
830     dumpEbbsToFileExt (DUMP_RAW1, ebbs, count);
831
832   /* do common subexpression elimination for each block */
833   change = cseAllBlocks (ebbs, saveCount);
834
835   /* dumpraw if asked for */
836   if (options.dump_raw)
837     dumpEbbsToFileExt (DUMP_CSE, ebbs, count);
838
839   /* compute the data flow */
840   computeDataFlow (ebbs, saveCount);
841
842   /* dumpraw if asked for */
843   if (options.dump_raw)
844     dumpEbbsToFileExt (DUMP_DFLOW, ebbs, count);
845
846   /* global common subexpression elimination  */
847   if (optimize.global_cse)
848     {
849       change += cseAllBlocks (ebbs, saveCount);
850       if (options.dump_gcse)
851         dumpEbbsToFileExt (DUMP_GCSE, ebbs, saveCount);
852     }
853   /* kill dead code */
854   kchange = killDeadCode (ebbs, saveCount);
855
856   if (options.dump_kill)
857     dumpEbbsToFileExt (DUMP_DEADCODE, ebbs, count);
858
859   /* do loop optimizations */
860   change += (lchange = loopOptimizations (loops, ebbs, count));
861   if (options.dump_loop)
862     dumpEbbsToFileExt (DUMP_LOOP, ebbs, count);
863
864   /* recompute the data flow and apply global cse again 
865      if loops optimizations or dead code caused a change:
866      loops will brings out of the loop which then may be
867      available for use in the later blocks: dead code
868      elimination could potentially disconnect some blocks
869      conditional flow may be efected so we need to apply
870      subexpression once more */
871   if (lchange || kchange)
872     {
873       computeDataFlow (ebbs, saveCount);
874       change += cseAllBlocks (ebbs, saveCount);
875       if (options.dump_loop)
876         dumpEbbsToFileExt (DUMP_LOOPG, ebbs, count);
877
878       /* if loop optimizations caused a change then do
879          dead code elimination once more : this will
880          get rid of the extra assignments to the induction
881          variables created during loop optimizations */
882       killDeadCode (ebbs, saveCount);
883
884       if (options.dump_loop)
885         dumpEbbsToFileExt (DUMP_LOOPD, ebbs, count);
886
887     }
888
889   /* sort it back by block number */
890   qsort (ebbs, saveCount, sizeof (eBBlock *), bbNumCompare);
891
892   /* if cyclomatic info requested then print it */
893   if (options.cyclomatic)
894     printCyclomatic (ebbs, saveCount);
895
896   /* convert operations with support routines
897      written in C to function calls : Iam doing
898      this at this point since I want all the
899      operations to be as they are for optimzations */
900   convertToFcall (ebbs, count);
901
902   /* compute the live ranges */
903   computeLiveRanges (ebbs, count);
904
905   if (options.dump_range)
906     dumpEbbsToFileExt (DUMP_RANGE, ebbs, count);
907
908   /* Now that we have the live ranges, discard parameter
909    * receives for unused parameters.
910    */
911   discardDeadParamReceives (ebbs, count);
912
913   /* allocate registers & generate code */
914   port->assignRegisters (ebbs, count);
915
916   /* throw away blocks */
917   setToNull ((void **) &graphEdges);
918   ebbs = NULL;
919
920   return NULL;
921 }
922
923
924 /* (add-hook 'c-mode-hook (lambda () (setq c-basic-offset 4))) */