Enable unused parameter fix
[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 /* discardDeadParamReceives - remove any RECEIVE opcodes which     */
618 /* refer to dead variables.                                        */
619 /*-----------------------------------------------------------------*/
620 static void discardDeadParamReceives(eBBlock **ebbs, int count)
621 {
622     int         i;
623     iCode       *ic;
624     iCode       dummyIcode;
625
626     for (i = 0 ; i < count ; i++)
627     {
628         for ( ic = ebbs[i]->sch ; ic ; ic = ic->next )
629         {
630             if (ic->op == RECEIVE)
631             {
632                 if (IC_RESULT(ic) && OP_SYMBOL(IC_RESULT(ic))
633                  && !OP_SYMBOL(IC_RESULT(ic))->used)
634                 {
635 #if 0                       
636                     fprintf(stderr, "discarding dead receive for %s\n", 
637                             OP_SYMBOL(IC_RESULT(ic))->name);
638 #endif                              
639                     dummyIcode.next = ic->next;
640                     remiCodeFromeBBlock(ebbs[i], ic);
641                     ic = &dummyIcode;
642                 }
643             }
644         }
645     }
646 }
647
648 /*-----------------------------------------------------------------*/
649 /* eBBlockFromiCode - creates extended basic blocks from iCode     */
650 /*                    will return an array of eBBlock pointers     */
651 /*-----------------------------------------------------------------*/
652 eBBlock **eBBlockFromiCode (iCode *ic)
653
654     eBBlock **ebbs = NULL ;       
655     int count = 0;   
656     int saveCount = 0 ;
657     int change = 1;
658     int lchange = 0 ;
659     int kchange = 0;
660     hTab *loops ;
661
662     /* if nothing passed then return nothing */
663     if (!ic)
664         return NULL ;
665
666     count = 0;
667     eBBNum = 0;    
668   
669     /* optimize the chain for labels & gotos 
670        this will eliminate redundant labels and
671        will change jump to jumps by jumps */
672     ic = iCodeLabelOptimize (ic);
673     
674     /* break it down into basic blocks */
675     ebbs = iCodeBreakDown (ic,&count);   
676     saveCount = count ;           
677
678     /* compute the control flow */
679     computeControlFlow (ebbs,count,0);
680
681     /* dumpraw if asked for */
682     if (options.dump_raw)
683         dumpEbbsToFileExt(".dumpraw0",ebbs,count);
684
685     /* replace the local variables with their
686        register equivalents : the liveRange computation
687        along with the register allocation will determine
688        if it finally stays in the registers */
689     replaceRegEqv (ebbs,count);
690
691      /* create loop regions */
692     loops = createLoopRegions (ebbs,count);
693
694    /* dumpraw if asked for */
695     if (options.dump_raw)
696         dumpEbbsToFileExt(".dumpraw1",ebbs,count);
697             
698     /* do common subexpression elimination for each block */     
699     change = cseAllBlocks(ebbs,saveCount);
700
701     /* dumpraw if asked for */
702     if (options.dump_raw)
703         dumpEbbsToFileExt(".dumpcse",ebbs,count);
704     
705     /* compute the data flow */
706     computeDataFlow (ebbs,saveCount); 
707
708     /* dumpraw if asked for */
709     if (options.dump_raw)
710         dumpEbbsToFileExt(".dumpdflow",ebbs,count);
711
712     /* global common subexpression elimination  */
713     if ( optimize.global_cse ) {
714         change += cseAllBlocks(ebbs,saveCount);
715         if (options.dump_gcse)
716             dumpEbbsToFileExt(".dumpgcse",ebbs,saveCount);
717     }
718      /* kill dead code */
719     kchange = killDeadCode (ebbs, saveCount);
720     
721     if (options.dump_kill)
722         dumpEbbsToFileExt(".dumpdeadcode",ebbs,count);
723     
724     /* do loop optimizations */
725     change += (lchange = loopOptimizations (loops,ebbs,count)); 
726     if (options.dump_loop)
727         dumpEbbsToFileExt(".dumploop",ebbs,count);
728  
729     /* recompute the data flow and apply global cse again 
730        if loops optimizations or dead code caused a change:
731        loops will brings out of the loop which then may be
732        available for use in the later blocks: dead code
733        elimination could potentially disconnect some blocks
734        conditional flow may be efected so we need to apply
735        subexpression once more */
736     if ( lchange || kchange ) {
737
738         computeDataFlow (ebbs,saveCount);    
739         change += cseAllBlocks(ebbs,saveCount);
740         if (options.dump_loop)
741             dumpEbbsToFileExt(".dumploopg",ebbs,count);
742
743         /* if loop optimizations caused a change then do
744            dead code elimination once more : this will
745            get rid of the extra assignments to the induction
746            variables created during loop optimizations */       
747         killDeadCode (ebbs, saveCount);
748         
749         if (options.dump_loop)
750             dumpEbbsToFileExt(".dumploopd",ebbs,count);
751
752     }    
753     
754    
755     /* sort it back by block number */
756     qsort (ebbs,saveCount,sizeof(eBBlock *),bbNumCompare);           
757
758     /* if cyclomatic info requested then print it */
759     if (options.cyclomatic)
760         printCyclomatic(ebbs,saveCount);
761
762
763     /* convert operations with support routines
764        written in C to function calls : Iam doing
765        this at this point since I want all the
766        operations to be as they are for optimzations */
767     convertToFcall (ebbs,count);
768
769
770     /* compute the live ranges */
771     computeLiveRanges (ebbs,count);
772
773     if (options.dump_range)
774         dumpEbbsToFileExt(".dumprange",ebbs,count);
775
776     /* Now that we have the live ranges, discard parameter
777      * receives for unused parameters.
778      */
779     discardDeadParamReceives(ebbs,count);
780
781     /* allocate registers & generate code */   
782     port->assignRegisters(ebbs,count);      
783     
784     /* throw away blocks */
785     setToNull ((void **)&graphEdges);
786     ebbs = NULL ;
787
788
789     return NULL;
790 }
791
792
793 /* (add-hook 'c-mode-hook (lambda () (setq c-basic-offset 4))) */