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