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