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