* support/Util/NewAlloc.c (freeTrace): Changed free for the gc case to not free...
[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->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);
117         }
118
119       addiCodeToeBBlock (ebp, newic, ip);
120       newic->lineno = lineno;
121
122       /* second one */
123       if (IS_REGPARM (func->args->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->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->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->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->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);
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->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->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);
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->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->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);
369         }
370       addiCodeToeBBlock (ebp, newic, ip);
371       newic->lineno = lineno;
372
373       /* second one */
374       if (IS_REGPARM (func->args->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->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->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->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 *type = operandType (IC_LEFT (ic));
468               if (IS_INTEGRAL (type) && getSize (type) > port->support.muldiv)
469                 {
470                   convilong (ic, ebbs[i], type, ic->op);
471                 }
472             }
473           
474           if (ic->op == RRC || ic->op == RLC || ic->op == LEFT_OP || ic->op == RIGHT_OP)
475             {
476               sym_link *type = operandType (IC_LEFT (ic));
477
478               if (IS_INTEGRAL (type) && getSize (type) > port->support.shift && port->support.shift >= 0)
479                 {
480                   convilong (ic, ebbs[i], type, ic->op);
481                 }
482             }
483         }
484     }
485 }
486
487 /*-----------------------------------------------------------------*/
488 /* replaceRegEqv - replace all local variables with their reqv     */
489 /*-----------------------------------------------------------------*/
490 static void 
491 replaceRegEqv (eBBlock ** ebbs, int count)
492 {
493   int i;
494
495   for (i = 0; i < count; i++)
496     {
497
498       iCode *ic;
499
500       for (ic = ebbs[i]->sch; ic; ic = ic->next)
501         {
502
503           if (SKIP_IC2 (ic))
504             continue;
505
506           if (ic->op == IFX)
507             {
508
509               if (IS_TRUE_SYMOP (IC_COND (ic)) &&
510                   OP_REQV (IC_COND (ic)))
511                 IC_COND (ic) = opFromOpWithDU (OP_REQV (IC_COND (ic)),
512                                              OP_SYMBOL (IC_COND (ic))->defs,
513                                             OP_SYMBOL (IC_COND (ic))->uses);
514
515               continue;
516             }
517
518           if (ic->op == JUMPTABLE)
519             {
520               if (IS_TRUE_SYMOP (IC_JTCOND (ic)) &&
521                   OP_REQV (IC_JTCOND (ic)))
522                 IC_JTCOND (ic) = opFromOpWithDU (OP_REQV (IC_JTCOND (ic)),
523                                            OP_SYMBOL (IC_JTCOND (ic))->defs,
524                                           OP_SYMBOL (IC_JTCOND (ic))->uses);
525               continue;
526             }
527
528           if (ic->op == RECEIVE)
529             {
530               if (OP_SYMBOL (IC_RESULT (ic))->addrtaken)
531                 OP_SYMBOL (IC_RESULT (ic))->isspilt = 1;
532             }
533
534           /* general case */
535           if (IC_RESULT (ic) &&
536               IS_TRUE_SYMOP (IC_RESULT (ic)) &&
537               OP_REQV (IC_RESULT (ic)))
538             {
539               if (POINTER_SET (ic))
540                 {
541                   IC_RESULT (ic) = opFromOpWithDU (OP_REQV (IC_RESULT (ic)),
542                                            OP_SYMBOL (IC_RESULT (ic))->defs,
543                                           OP_SYMBOL (IC_RESULT (ic))->uses);
544                   IC_RESULT (ic)->isaddr = 1;
545                 }
546               else
547                 IC_RESULT (ic) = opFromOpWithDU (OP_REQV (IC_RESULT (ic)),
548                                            OP_SYMBOL (IC_RESULT (ic))->defs,
549                                           OP_SYMBOL (IC_RESULT (ic))->uses);
550             }
551
552           if (IC_RIGHT (ic) &&
553               IS_TRUE_SYMOP (IC_RIGHT (ic)) &&
554               OP_REQV (IC_RIGHT (ic)))
555             {
556               IC_RIGHT (ic) = opFromOpWithDU (OP_REQV (IC_RIGHT (ic)),
557                                             OP_SYMBOL (IC_RIGHT (ic))->defs,
558                                            OP_SYMBOL (IC_RIGHT (ic))->uses);
559               IC_RIGHT (ic)->isaddr = 0;
560             }
561
562           if (IC_LEFT (ic) &&
563               IS_TRUE_SYMOP (IC_LEFT (ic)) &&
564               OP_REQV (IC_LEFT (ic)))
565             {
566               IC_LEFT (ic) = opFromOpWithDU (OP_REQV (IC_LEFT (ic)),
567                                              OP_SYMBOL (IC_LEFT (ic))->defs,
568                                              OP_SYMBOL (IC_LEFT (ic))->uses);
569               IC_LEFT (ic)->isaddr = 0;
570             }
571         }
572     }
573 }
574
575 /*-----------------------------------------------------------------*/
576 /* killDeadCode - eliminates dead assignments                      */
577 /*-----------------------------------------------------------------*/
578 int 
579 killDeadCode (eBBlock ** ebbs, int count)
580 {
581   int change = 1;
582   int gchange = 0;
583   int i = 0;
584
585
586   /* basic algorithm :-                                          */
587   /* first the exclusion rules :-                                */
588   /*  1. if result is a global or volatile then skip             */
589   /*  2. if assignment and result is a temp & isaddr  then skip  */
590   /*     since this means array & pointer access, will be taken  */
591   /*     care of by alias analysis.                              */
592   /*  3. if the result is used in the remainder of the block skip */
593   /*  4. if this definition does not reach the end of the block  */
594   /*     i.e. the result is not present in the outExprs then KILL */
595   /*  5. if it reaches the end of block & is used by some success */
596   /*     or then skip                                            */
597   /*     else            KILL                                    */
598   /* this whole process is carried on iteratively till no change */
599   while (1)
600     {
601
602       change = 0;
603       /* for all blocks do */
604       for (i = 0; i < count; i++)
605         {
606           iCode *ic;
607
608           /* for all instructions in the block do */
609           for (ic = ebbs[i]->sch; ic; ic = ic->next)
610             {
611               int kill, j;
612               kill = 0;
613
614               if (SKIP_IC (ic) ||
615                   ic->op == IFX ||
616                   ic->op == RETURN)
617                 continue;
618
619               /* if the result is volatile then continue */
620               if (IC_RESULT (ic) && isOperandVolatile (IC_RESULT (ic), FALSE))
621                 continue;
622
623               /* if the result is a temp & isaddr then skip */
624               if (IC_RESULT (ic) && POINTER_SET (ic))
625                 continue;
626
627               /* if the result is used in the remainder of the */
628               /* block then skip */
629               if (usedInRemaining (IC_RESULT (ic), ic->next))
630                 continue;
631
632               /* does this definition reach the end of the block 
633                  or the usage is zero then we can kill */
634               if (!bitVectBitValue (ebbs[i]->outDefs, ic->key))
635                 kill = 1;       /* if not we can kill it */
636               else
637                 {
638                   /* if this is a global variable or function parameter */
639                   /* we cannot kill anyway             */
640                   if (isOperandGlobal (IC_RESULT (ic)) ||
641                       (OP_SYMBOL (IC_RESULT (ic))->_isparm &&
642                        !OP_SYMBOL (IC_RESULT (ic))->ismyparm))
643                     continue;
644
645                   /* if we are sure there are no usages */
646                   if (bitVectIsZero (OP_USES (IC_RESULT (ic))))
647                     {
648                       kill = 1;
649                       goto kill;
650                     }
651
652                   /* reset visited flag */
653                   for (j = 0; j < count; ebbs[j++]->visited = 0);
654
655                   /* find out if this definition is alive */
656                   if (applyToSet (ebbs[i]->succList,
657                                   isDefAlive,
658                                   ic))
659                     continue;
660
661                   kill = 1;
662                 }
663
664             kill:
665               /* kill this one if required */
666               if (kill)
667                 {
668                   change = 1;
669                   gchange++;
670                   /* eliminate this */
671                   remiCodeFromeBBlock (ebbs[i], ic);
672
673                   /* now delete from defUseSet */
674                   deleteItemIf (&ebbs[i]->outExprs, ifDiCodeIsX, ic);
675                   bitVectUnSetBit (ebbs[i]->outDefs, ic->key);
676
677                   /* and defset of the block */
678                   bitVectUnSetBit (ebbs[i]->defSet, ic->key);
679
680                   /* for the left & right remove the usage */
681                   if (IS_SYMOP (IC_LEFT (ic)))
682                     bitVectUnSetBit (OP_USES (IC_LEFT (ic)), ic->key);
683
684                   if (IS_SYMOP (IC_RIGHT (ic)))
685                     bitVectUnSetBit (OP_USES (IC_RIGHT (ic)), ic->key);
686                 }
687
688             }                   /* end of all instructions */
689
690           if (!ebbs[i]->sch && !ebbs[i]->noPath)
691             disconBBlock (ebbs[i], ebbs, count);
692
693         }                       /* end of for all blocks */
694
695       if (!change)
696         break;
697     }                           /* end of while(1) */
698
699   return gchange;
700 }
701
702 /*-----------------------------------------------------------------*/
703 /* printCyclomatic - prints the cyclomatic information             */
704 /*-----------------------------------------------------------------*/
705 static void 
706 printCyclomatic (eBBlock ** ebbs, int count)
707 {
708   int nEdges = elementsInSet (graphEdges);
709   int i, nNodes = 0;
710
711   for (i = 0; i < count; i++)
712     nNodes += (!ebbs[i]->noPath);
713
714   /* print the information */
715   werror (I_CYCLOMATIC, currFunc->name, nEdges, nNodes, nEdges - nNodes + 2);
716 }
717
718 /*-----------------------------------------------------------------*/
719 /* discardDeadParamReceives - remove any RECEIVE opcodes which     */
720 /* refer to dead variables.                                        */
721 /*-----------------------------------------------------------------*/
722 static void 
723 discardDeadParamReceives (eBBlock ** ebbs, int count)
724 {
725   int i;
726   iCode *ic;
727   iCode dummyIcode;
728
729   for (i = 0; i < count; i++)
730     {
731       for (ic = ebbs[i]->sch; ic; ic = ic->next)
732         {
733           if (ic->op == RECEIVE)
734             {
735               if (IC_RESULT (ic) && OP_SYMBOL (IC_RESULT (ic))
736                   && !OP_SYMBOL (IC_RESULT (ic))->used)
737                 {
738 #if 0
739                   fprintf (stderr, "discarding dead receive for %s\n",
740                            OP_SYMBOL (IC_RESULT (ic))->name);
741 #endif
742                   dummyIcode.next = ic->next;
743                   remiCodeFromeBBlock (ebbs[i], ic);
744                   ic = &dummyIcode;
745                 }
746             }
747         }
748     }
749 }
750
751 /*-----------------------------------------------------------------*/
752 /* eBBlockFromiCode - creates extended basic blocks from iCode     */
753 /*                    will return an array of eBBlock pointers     */
754 /*-----------------------------------------------------------------*/
755 eBBlock **
756 eBBlockFromiCode (iCode * ic)
757 {
758   eBBlock **ebbs = NULL;
759   int count = 0;
760   int saveCount = 0;
761   int change = 1;
762   int lchange = 0;
763   int kchange = 0;
764   hTab *loops;
765
766   /* if nothing passed then return nothing */
767   if (!ic)
768     return NULL;
769
770   count = 0;
771   eBBNum = 0;
772
773   /* optimize the chain for labels & gotos 
774      this will eliminate redundant labels and
775      will change jump to jumps by jumps */
776   ic = iCodeLabelOptimize (ic);
777
778   /* break it down into basic blocks */
779   ebbs = iCodeBreakDown (ic, &count);
780   saveCount = count;
781
782   /* compute the control flow */
783   computeControlFlow (ebbs, count, 0);
784
785   /* dumpraw if asked for */
786   if (options.dump_raw)
787     dumpEbbsToFileExt (DUMP_RAW0, ebbs, count);
788
789   /* replace the local variables with their
790      register equivalents : the liveRange computation
791      along with the register allocation will determine
792      if it finally stays in the registers */
793   replaceRegEqv (ebbs, count);
794
795   /* create loop regions */
796   loops = createLoopRegions (ebbs, count);
797
798   /* dumpraw if asked for */
799   if (options.dump_raw)
800     dumpEbbsToFileExt (DUMP_RAW1, ebbs, count);
801
802   /* do common subexpression elimination for each block */
803   change = cseAllBlocks (ebbs, saveCount);
804
805   /* dumpraw if asked for */
806   if (options.dump_raw)
807     dumpEbbsToFileExt (DUMP_CSE, ebbs, count);
808
809   /* compute the data flow */
810   computeDataFlow (ebbs, saveCount);
811
812   /* dumpraw if asked for */
813   if (options.dump_raw)
814     dumpEbbsToFileExt (DUMP_DFLOW, ebbs, count);
815
816   /* global common subexpression elimination  */
817   if (optimize.global_cse)
818     {
819       change += cseAllBlocks (ebbs, saveCount);
820       if (options.dump_gcse)
821         dumpEbbsToFileExt (DUMP_GCSE, ebbs, saveCount);
822     }
823   /* kill dead code */
824   kchange = killDeadCode (ebbs, saveCount);
825
826   if (options.dump_kill)
827     dumpEbbsToFileExt (DUMP_DEADCODE, ebbs, count);
828
829   /* do loop optimizations */
830   change += (lchange = loopOptimizations (loops, ebbs, count));
831   if (options.dump_loop)
832     dumpEbbsToFileExt (DUMP_LOOP, ebbs, count);
833
834   /* recompute the data flow and apply global cse again 
835      if loops optimizations or dead code caused a change:
836      loops will brings out of the loop which then may be
837      available for use in the later blocks: dead code
838      elimination could potentially disconnect some blocks
839      conditional flow may be efected so we need to apply
840      subexpression once more */
841   if (lchange || kchange)
842     {
843       computeDataFlow (ebbs, saveCount);
844       change += cseAllBlocks (ebbs, saveCount);
845       if (options.dump_loop)
846         dumpEbbsToFileExt (DUMP_LOOPG, ebbs, count);
847
848       /* if loop optimizations caused a change then do
849          dead code elimination once more : this will
850          get rid of the extra assignments to the induction
851          variables created during loop optimizations */
852       killDeadCode (ebbs, saveCount);
853
854       if (options.dump_loop)
855         dumpEbbsToFileExt (DUMP_LOOPD, ebbs, count);
856
857     }
858
859   /* sort it back by block number */
860   qsort (ebbs, saveCount, sizeof (eBBlock *), bbNumCompare);
861
862   /* if cyclomatic info requested then print it */
863   if (options.cyclomatic)
864     printCyclomatic (ebbs, saveCount);
865
866   /* convert operations with support routines
867      written in C to function calls : Iam doing
868      this at this point since I want all the
869      operations to be as they are for optimzations */
870   convertToFcall (ebbs, count);
871
872   /* compute the live ranges */
873   computeLiveRanges (ebbs, count);
874
875   if (options.dump_range)
876     dumpEbbsToFileExt (DUMP_RANGE, ebbs, count);
877
878   /* Now that we have the live ranges, discard parameter
879    * receives for unused parameters.
880    */
881   discardDeadParamReceives (ebbs, count);
882
883   /* allocate registers & generate code */
884   port->assignRegisters (ebbs, count);
885
886   /* throw away blocks */
887   setToNull ((void **) &graphEdges);
888   ebbs = NULL;
889
890   return NULL;
891 }
892
893
894 /* (add-hook 'c-mode-hook (lambda () (setq c-basic-offset 4))) */