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