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