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