optimization: replace modulo by a power of two with a bitwise AND
[fw/sdcc] / src / SDCCopt.c
1 /*-------------------------------------------------------------------------
2   SDCCopt.c - calls all the optimizations routines and does some of the
3               hackier transformations, these include translating iCodes
4               to function calls and replacing local variables with their
5               register equivalents etc. Also contains the driver routine
6               for dead code elimination
7
8              Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
9
10    This program is free software; you can redistribute it and/or modify it
11    under the terms of the GNU General Public License as published by the
12    Free Software Foundation; either version 2, or (at your option) any
13    later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23    
24    In other words, you are welcome to use, share and improve this program.
25    You are forbidden to forbid anyone else to use, share and improve
26    what you give them.   Help stamp out software-hoarding!  
27 -------------------------------------------------------------------------*/
28
29 #include "common.h"
30
31 /*-----------------------------------------------------------------*/
32 /* global variables */
33 int cseDefNum = 0;
34
35 char flowChanged = 0;
36
37
38 /*-----------------------------------------------------------------*/
39 /* printSymName - prints the symbol names                          */
40 /*-----------------------------------------------------------------*/
41 int 
42 printSymName (void *vsym)
43 {
44   symbol *sym = vsym;
45   fprintf (stdout, " %s ", sym->name);
46   return 0;
47 }
48
49 /*-----------------------------------------------------------------*/
50 /* cnvToFcall - does the actual conversion to function call        */
51 /*-----------------------------------------------------------------*/
52 static void 
53 cnvToFcall (iCode * ic, eBBlock * ebp)
54 {
55   iCode *ip;
56   iCode *newic;
57   operand *left;
58   operand *right;
59   symbol *func = NULL;
60   int lineno = ic->lineno;
61   int bytesPushed=0;
62
63   ip = ic->next;                /* insertion point */
64   /* remove it from the iCode */
65   remiCodeFromeBBlock (ebp, ic);
66
67   left = IC_LEFT (ic);
68   right = IC_RIGHT (ic);
69
70   switch (ic->op)
71     {
72     case '+':
73       func = __fsadd;
74       break;
75     case '-':
76       func = __fssub;
77       break;
78     case '/':
79       func = __fsdiv;
80       break;
81     case '*':
82       func = __fsmul;
83       break;
84     case EQ_OP:
85       func = __fseq;
86       break;
87     case NE_OP:
88       func = __fsneq;
89       break;
90     case '<':
91       func = __fslt;
92       break;
93     case '>':
94       func = __fsgt;
95       break;
96     case LE_OP:
97       func = __fslteq;
98       break;
99     case GE_OP:
100       func = __fsgteq;
101       break;
102     }
103
104   /* if float support routines NOT compiled as reentrant */
105   if (!options.float_rent)
106     {
107
108       /* first one */
109       if (IS_REGPARM (FUNC_ARGS(func->type)->etype))
110         {
111           newic = newiCode (SEND, IC_LEFT (ic), NULL);
112           newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype);
113         }
114       else
115         {
116           newic = newiCode ('=', NULL, IC_LEFT (ic));
117           IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type));
118         }
119
120       addiCodeToeBBlock (ebp, newic, ip);
121       newic->lineno = lineno;
122
123       /* second one */
124       if (IS_REGPARM (FUNC_ARGS(func->type)->next->etype))
125         {
126           newic = newiCode (SEND, IC_RIGHT (ic), NULL);
127           newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->next->etype);
128         }
129       else
130         {
131           newic = newiCode ('=', NULL, IC_RIGHT (ic));
132           IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)->next);
133         }
134       addiCodeToeBBlock (ebp, newic, ip);
135       newic->lineno = lineno;
136
137     }
138   else
139     {
140
141       /* push right */
142       if (IS_REGPARM (FUNC_ARGS(func->type)->next->etype))
143         {
144           newic = newiCode (SEND, right, NULL);
145           newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->next->etype);
146         }
147       else
148         {
149           newic = newiCode (IPUSH, right, NULL);
150           newic->parmPush = 1;
151           bytesPushed+=4;
152         }
153
154       addiCodeToeBBlock (ebp, newic, ip);
155       newic->lineno = lineno;
156
157       /* insert push left */
158       if (IS_REGPARM (FUNC_ARGS(func->type)->etype))
159         {
160           newic = newiCode (SEND, left, NULL);
161           newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype);
162         }
163       else
164         {
165           newic = newiCode (IPUSH, left, NULL);
166           newic->parmPush = 1;
167           bytesPushed+=4;
168         }
169       addiCodeToeBBlock (ebp, newic, ip);
170       newic->lineno = lineno;
171     }
172   /* insert the call */
173   newic = newiCode (CALL, operandFromSymbol (func), NULL);
174   IC_RESULT (newic) = IC_RESULT (ic);
175   newic->lineno = lineno;
176   newic->parmBytes+=bytesPushed;
177   addiCodeToeBBlock (ebp, newic, ip);
178 }
179
180 /*-----------------------------------------------------------------*/
181 /* cnvToFloatCast - converts casts to floats to function calls     */
182 /*-----------------------------------------------------------------*/
183 static void 
184 cnvToFloatCast (iCode * ic, eBBlock * ebp)
185 {
186   iCode *ip, *newic;
187   symbol *func = NULL;
188   sym_link *type = operandType (IC_RIGHT (ic));
189   int linenno = ic->lineno;
190   int bwd, su;
191
192   ip = ic->next;
193   /* remove it from the iCode */
194   remiCodeFromeBBlock (ebp, ic);
195   /* depending on the type */
196   for (bwd = 0; bwd < 3; bwd++)
197     {
198       for (su = 0; su < 2; su++)
199         {
200           if (compareType (type, __multypes[bwd][su]) == 1)
201             {
202               func = __conv[0][bwd][su];
203               goto found;
204             }
205         }
206     }
207   assert (0);
208 found:
209
210   /* if float support routines NOT compiled as reentrant */
211   if (!options.float_rent)
212     {
213       /* first one */
214         if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) 
215             {
216                 newic = newiCode (SEND, IC_RIGHT (ic), NULL);
217                 newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype);
218             }
219       else
220         {
221           newic = newiCode ('=', NULL, IC_RIGHT (ic));
222           IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type));
223         }
224       addiCodeToeBBlock (ebp, newic, ip);
225       newic->lineno = linenno;
226
227     }
228   else
229     {
230       /* push the left */
231         if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) {
232             newic = newiCode (SEND, IC_RIGHT (ic), NULL);
233             newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype);
234         }
235       else
236         {
237           newic = newiCode (IPUSH, IC_RIGHT (ic), NULL);
238           newic->parmPush = 1;
239         }
240       addiCodeToeBBlock (ebp, newic, ip);
241       newic->lineno = linenno;
242
243     }
244
245   /* make the call */
246   newic = newiCode (CALL, operandFromSymbol (func), NULL);
247   IC_RESULT (newic) = IC_RESULT (ic);
248   addiCodeToeBBlock (ebp, newic, ip);
249   newic->lineno = linenno;
250
251 }
252
253 /*-----------------------------------------------------------------*/
254 /* cnvFromFloatCast - converts casts From floats to function calls */
255 /*-----------------------------------------------------------------*/
256 static void 
257 cnvFromFloatCast (iCode * ic, eBBlock * ebp)
258 {
259   iCode *ip, *newic;
260   symbol *func = NULL;
261   sym_link *type = operandType (IC_LEFT (ic));
262   int lineno = ic->lineno;
263   int bwd, su;
264
265   ip = ic->next;
266   /* remove it from the iCode */
267   remiCodeFromeBBlock (ebp, ic);
268
269   /* depending on the type */
270   for (bwd = 0; bwd < 3; bwd++)
271     {
272       for (su = 0; su < 2; su++)
273         {
274           if (compareType (type, __multypes[bwd][su]) == 1)
275             {
276               func = __conv[1][bwd][su];
277               goto found;
278             }
279         }
280     }
281   assert (0);
282 found:
283
284   /* if float support routines NOT compiled as reentrant */
285   if (!options.float_rent)
286     {
287       /* first one */
288         if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) {
289             newic = newiCode (SEND, IC_RIGHT (ic), NULL);
290             newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype);
291         }
292       else
293         {
294           newic = newiCode ('=', NULL, IC_RIGHT (ic));
295           IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type));
296         }
297       addiCodeToeBBlock (ebp, newic, ip);
298       newic->lineno = lineno;
299
300     }
301   else
302     {
303
304       /* push the left */
305         if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) {
306             newic = newiCode (SEND, IC_RIGHT (ic), NULL);
307             newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype);
308         }
309       else
310         {
311           newic = newiCode (IPUSH, IC_RIGHT (ic), NULL);
312           newic->parmPush = 1;
313         }
314       addiCodeToeBBlock (ebp, newic, ip);
315       newic->lineno = lineno;
316
317     }
318
319   /* make the call */
320   newic = newiCode (CALL, operandFromSymbol (func), NULL);
321   IC_RESULT (newic) = IC_RESULT (ic);
322   addiCodeToeBBlock (ebp, newic, ip);
323   newic->lineno = lineno;
324
325 }
326
327 extern operand *geniCodeRValue (operand *, bool);
328
329 /*-----------------------------------------------------------------*/
330 /* convilong - converts int or long mults or divs to fcalls        */
331 /*-----------------------------------------------------------------*/
332 static void 
333 convilong (iCode * ic, eBBlock * ebp, sym_link * type, int op)
334 {
335   symbol *func = NULL;
336   iCode *ip = ic->next;
337   iCode *newic;
338   int lineno = ic->lineno;
339   int bwd;
340   int su;
341   int bytesPushed=0;
342
343   // Easy special case which avoids function call: modulo by a literal power 
344   // of two can be replaced by a bitwise AND.
345   if (op == '%' && isOperandLiteral(IC_RIGHT(ic)))
346   {
347       unsigned litVal = (unsigned)(operandLitValue(IC_RIGHT(ic)));
348       
349       // See if literal value is a power of 2.
350       while (litVal && !(litVal & 1))
351       {
352           litVal >>= 1;
353       }
354       if (litVal)
355       {
356           // discard first high bit set.
357           litVal >>= 1;
358       }
359           
360       if (!litVal)
361       {
362           ic->op = BITWISEAND;
363           IC_RIGHT(ic) = operandFromLit(operandLitValue(IC_RIGHT(ic)) - 1);
364           return;
365       }
366   }
367     
368   remiCodeFromeBBlock (ebp, ic);    
369     
370     
371   /* depending on the type */
372   for (bwd = 0; bwd < 3; bwd++)
373     {
374       for (su = 0; su < 2; su++)
375         {
376           if (compareType (type, __multypes[bwd][su]) == 1)
377             {
378               if (op == '*')
379                 func = __muldiv[0][bwd][su];
380               else if (op == '/')
381                 func = __muldiv[1][bwd][su];
382               else if (op == '%')
383                 func = __muldiv[2][bwd][su];
384               else if (op == RRC)
385                 func = __rlrr[1][bwd][su];
386               else if (op == RLC)
387                 func = __rlrr[0][bwd][su];
388               else if (op == RIGHT_OP)
389                 func = __rlrr[1][bwd][su];
390               else if (op == LEFT_OP)
391                 func = __rlrr[0][bwd][su];
392               else
393                 assert (0);
394               goto found;
395             }
396         }
397     }
398   assert (0);
399 found:
400   /* if int & long support routines NOT compiled as reentrant */
401   if (!options.intlong_rent)
402     {
403       /* first one */
404         if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) {
405             newic = newiCode (SEND, IC_LEFT (ic), NULL);
406             newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype);
407         }
408       else
409         {
410           newic = newiCode ('=', NULL, IC_LEFT (ic));
411           IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type));
412         }
413       addiCodeToeBBlock (ebp, newic, ip);
414       newic->lineno = lineno;
415
416       /* second one */
417       if (IS_REGPARM (FUNC_ARGS(func->type)->next->etype)) {
418           newic = newiCode (SEND, IC_RIGHT (ic), NULL);
419           newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->next->etype);
420       }
421       else
422         {
423           newic = newiCode ('=', NULL, IC_RIGHT (ic));
424           IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)->next);
425         }
426       addiCodeToeBBlock (ebp, newic, ip);
427       newic->lineno = lineno;
428
429     }
430   else
431     {
432       /* compiled as reentrant then push */
433       /* push right */
434       if (IS_REGPARM (FUNC_ARGS(func->type)->next->etype))
435         {
436           newic = newiCode (SEND, IC_RIGHT (ic), NULL);
437           newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->next->etype);
438         }
439       else
440         {
441           newic = newiCode (IPUSH, IC_RIGHT (ic), NULL);
442           newic->parmPush = 1;
443
444           bytesPushed += getSize(operandType(IC_RIGHT(ic)));
445         }
446       addiCodeToeBBlock (ebp, newic, ip);
447       newic->lineno = lineno;
448
449       /* insert push left */
450       if (IS_REGPARM (FUNC_ARGS(func->type)->etype))
451         {
452           newic = newiCode (SEND, IC_LEFT (ic), NULL);
453           newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype);
454         }
455       else
456         {
457           newic = newiCode (IPUSH, IC_LEFT (ic), NULL);
458           newic->parmPush = 1;
459
460           bytesPushed += getSize(operandType(IC_LEFT(ic)));
461         }
462       addiCodeToeBBlock (ebp, newic, ip);
463       newic->lineno = lineno;
464
465     }
466
467   /* for the result */
468   newic = newiCode (CALL, operandFromSymbol (func), NULL);
469   IC_RESULT (newic) = IC_RESULT (ic);
470   newic->lineno = lineno;
471   newic->parmBytes+=bytesPushed; // to clear the stack after the call
472   addiCodeToeBBlock (ebp, newic, ip);
473 }
474
475 /*-----------------------------------------------------------------*/
476 /* convertToFcall - converts some operations to fcalls             */
477 /*-----------------------------------------------------------------*/
478 static void 
479 convertToFcall (eBBlock ** ebbs, int count)
480 {
481   int i;
482
483   /* for all blocks do */
484   for (i = 0; i < count; i++)
485     {
486       iCode *ic;
487
488       /* for all instructions in the block do */
489       for (ic = ebbs[i]->sch; ic; ic = ic->next)
490         {
491
492           /* floating point operations are
493              converted to function calls */
494           if ((IS_CONDITIONAL (ic) ||
495                IS_ARITHMETIC_OP (ic)) &&
496               (IS_FLOAT (operandType (IC_RIGHT (ic)))))
497             {
498
499               cnvToFcall (ic, ebbs[i]);
500             }
501
502           /* casting is a little different */
503           if (ic->op == CAST)
504             {
505               if (IS_FLOAT (operandType (IC_RIGHT (ic))))
506                 cnvFromFloatCast (ic, ebbs[i]);
507               else if (IS_FLOAT (operandType (IC_LEFT (ic))))
508                 cnvToFloatCast (ic, ebbs[i]);
509             }
510
511           /* if long / int mult or divide or mod */
512           if (ic->op == '*' || ic->op == '/' || ic->op == '%')
513             {
514               sym_link *leftType = operandType (IC_LEFT (ic));
515
516               if (IS_INTEGRAL (leftType) && getSize (leftType) > port->support.muldiv)
517                 {
518                   sym_link *rightType = operandType (IC_RIGHT (ic));
519
520                   if (port->hasNativeMulFor != NULL &&
521                       port->hasNativeMulFor (ic, leftType, rightType))
522                     {
523                       /* Leave as native */
524                     }
525                   else
526                     {
527                       convilong (ic, ebbs[i], leftType, ic->op);
528                     }
529                 }
530             }
531           
532           if (ic->op == RRC || ic->op == RLC || ic->op == LEFT_OP || ic->op == RIGHT_OP)
533             {
534               sym_link *type = operandType (IC_LEFT (ic));
535
536               if (IS_INTEGRAL (type) && getSize (type) > port->support.shift && port->support.shift >= 0)
537                 {
538                   convilong (ic, ebbs[i], type, ic->op);
539                 }
540             }
541         }
542     }
543 }
544
545 /*-----------------------------------------------------------------*/
546 /* replaceRegEqv - replace all local variables with their reqv     */
547 /*-----------------------------------------------------------------*/
548 static void 
549 replaceRegEqv (eBBlock ** ebbs, int count)
550 {
551   int i;
552
553   for (i = 0; i < count; i++)
554     {
555
556       iCode *ic;
557
558       for (ic = ebbs[i]->sch; ic; ic = ic->next)
559         {
560
561           if (SKIP_IC2 (ic))
562             continue;
563
564           if (ic->op == IFX)
565             {
566
567               if (IS_TRUE_SYMOP (IC_COND (ic)) &&
568                   OP_REQV (IC_COND (ic)))
569                 IC_COND (ic) = opFromOpWithDU (OP_REQV (IC_COND (ic)),
570                                              OP_SYMBOL (IC_COND (ic))->defs,
571                                             OP_SYMBOL (IC_COND (ic))->uses);
572
573               continue;
574             }
575
576           if (ic->op == JUMPTABLE)
577             {
578               if (IS_TRUE_SYMOP (IC_JTCOND (ic)) &&
579                   OP_REQV (IC_JTCOND (ic)))
580                 IC_JTCOND (ic) = opFromOpWithDU (OP_REQV (IC_JTCOND (ic)),
581                                            OP_SYMBOL (IC_JTCOND (ic))->defs,
582                                           OP_SYMBOL (IC_JTCOND (ic))->uses);
583               continue;
584             }
585
586           if (ic->op == RECEIVE)
587             {
588               if (OP_SYMBOL (IC_RESULT (ic))->addrtaken)
589                 OP_SYMBOL (IC_RESULT (ic))->isspilt = 1;
590             }
591
592           /* general case */
593           if (IC_RESULT (ic) &&
594               IS_TRUE_SYMOP (IC_RESULT (ic)) &&
595               OP_REQV (IC_RESULT (ic)))
596             {
597               if (POINTER_SET (ic))
598                 {
599                   IC_RESULT (ic) = opFromOpWithDU (OP_REQV (IC_RESULT (ic)),
600                                            OP_SYMBOL (IC_RESULT (ic))->defs,
601                                           OP_SYMBOL (IC_RESULT (ic))->uses);
602                   IC_RESULT (ic)->isaddr = 1;
603                 }
604               else
605                 IC_RESULT (ic) = opFromOpWithDU (OP_REQV (IC_RESULT (ic)),
606                                            OP_SYMBOL (IC_RESULT (ic))->defs,
607                                           OP_SYMBOL (IC_RESULT (ic))->uses);
608             }
609
610           if (IC_RIGHT (ic) &&
611               IS_TRUE_SYMOP (IC_RIGHT (ic)) &&
612               OP_REQV (IC_RIGHT (ic)))
613             {
614               IC_RIGHT (ic) = opFromOpWithDU (OP_REQV (IC_RIGHT (ic)),
615                                             OP_SYMBOL (IC_RIGHT (ic))->defs,
616                                            OP_SYMBOL (IC_RIGHT (ic))->uses);
617               IC_RIGHT (ic)->isaddr = 0;
618             }
619
620           if (IC_LEFT (ic) &&
621               IS_TRUE_SYMOP (IC_LEFT (ic)) &&
622               OP_REQV (IC_LEFT (ic)))
623             {
624               IC_LEFT (ic) = opFromOpWithDU (OP_REQV (IC_LEFT (ic)),
625                                              OP_SYMBOL (IC_LEFT (ic))->defs,
626                                              OP_SYMBOL (IC_LEFT (ic))->uses);
627               IC_LEFT (ic)->isaddr = 0;
628             }
629         }
630     }
631 }
632
633 /*-----------------------------------------------------------------*/
634 /* killDeadCode - eliminates dead assignments                      */
635 /*-----------------------------------------------------------------*/
636 int 
637 killDeadCode (eBBlock ** ebbs, int count)
638 {
639   int change = 1;
640   int gchange = 0;
641   int i = 0;
642
643
644   /* basic algorithm :-                                          */
645   /* first the exclusion rules :-                                */
646   /*  1. if result is a global or volatile then skip             */
647   /*  2. if assignment and result is a temp & isaddr  then skip  */
648   /*     since this means array & pointer access, will be taken  */
649   /*     care of by alias analysis.                              */
650   /*  3. if the result is used in the remainder of the block skip */
651   /*  4. if this definition does not reach the end of the block  */
652   /*     i.e. the result is not present in the outExprs then KILL */
653   /*  5. if it reaches the end of block & is used by some success */
654   /*     or then skip                                            */
655   /*     else            KILL                                    */
656   /* this whole process is carried on iteratively till no change */
657   while (1)
658     {
659
660       change = 0;
661       /* for all blocks do */
662       for (i = 0; i < count; i++)
663         {
664           iCode *ic;
665
666           /* for all instructions in the block do */
667           for (ic = ebbs[i]->sch; ic; ic = ic->next)
668             {
669               int kill, j;
670               kill = 0;
671
672               if (SKIP_IC (ic) ||
673                   ic->op == IFX ||
674                   ic->op == RETURN)
675                 continue;
676
677               /* if the result is volatile then continue */
678               if (IC_RESULT (ic) && isOperandVolatile (IC_RESULT (ic), FALSE))
679                 continue;
680
681               /* if the result is a temp & isaddr then skip */
682               if (IC_RESULT (ic) && POINTER_SET (ic))
683                 continue;
684
685               /* if the result is used in the remainder of the */
686               /* block then skip */
687               if (usedInRemaining (IC_RESULT (ic), ic->next))
688                 continue;
689
690               /* does this definition reach the end of the block 
691                  or the usage is zero then we can kill */
692               if (!bitVectBitValue (ebbs[i]->outDefs, ic->key))
693                 kill = 1;       /* if not we can kill it */
694               else
695                 {
696                   /* if this is a global variable or function parameter */
697                   /* we cannot kill anyway             */
698                   if (isOperandGlobal (IC_RESULT (ic)) ||
699                       (OP_SYMBOL (IC_RESULT (ic))->_isparm &&
700                        !OP_SYMBOL (IC_RESULT (ic))->ismyparm))
701                     continue;
702
703                   /* if we are sure there are no usages */
704                   if (bitVectIsZero (OP_USES (IC_RESULT (ic))))
705                     {
706                       kill = 1;
707                       goto kill;
708                     }
709
710                   /* reset visited flag */
711                   for (j = 0; j < count; ebbs[j++]->visited = 0);
712
713                   /* find out if this definition is alive */
714                   if (applyToSet (ebbs[i]->succList,
715                                   isDefAlive,
716                                   ic))
717                     continue;
718
719                   kill = 1;
720                 }
721
722             kill:
723               /* kill this one if required */
724               if (kill)
725                 {
726                   change = 1;
727                   gchange++;
728                   /* eliminate this */
729                   remiCodeFromeBBlock (ebbs[i], ic);
730
731                   /* now delete from defUseSet */
732                   deleteItemIf (&ebbs[i]->outExprs, ifDiCodeIsX, ic);
733                   bitVectUnSetBit (ebbs[i]->outDefs, ic->key);
734
735                   /* and defset of the block */
736                   bitVectUnSetBit (ebbs[i]->defSet, ic->key);
737
738                   /* for the left & right remove the usage */
739                   if (IS_SYMOP (IC_LEFT (ic)))
740                     bitVectUnSetBit (OP_USES (IC_LEFT (ic)), ic->key);
741
742                   if (IS_SYMOP (IC_RIGHT (ic)))
743                     bitVectUnSetBit (OP_USES (IC_RIGHT (ic)), ic->key);
744                 }
745
746             }                   /* end of all instructions */
747
748           if (!ebbs[i]->sch && !ebbs[i]->noPath)
749             disconBBlock (ebbs[i], ebbs, count);
750
751         }                       /* end of for all blocks */
752
753       if (!change)
754         break;
755     }                           /* end of while(1) */
756
757   return gchange;
758 }
759
760 /*-----------------------------------------------------------------*/
761 /* printCyclomatic - prints the cyclomatic information             */
762 /*-----------------------------------------------------------------*/
763 static void 
764 printCyclomatic (eBBlock ** ebbs, int count)
765 {
766   int nEdges = elementsInSet (graphEdges);
767   int i, nNodes = 0;
768
769   for (i = 0; i < count; i++)
770     nNodes += (!ebbs[i]->noPath);
771
772   /* print the information */
773   werror (I_CYCLOMATIC, currFunc->name, nEdges, nNodes, nEdges - nNodes + 2);
774 }
775
776 /*-----------------------------------------------------------------*/
777 /* discardDeadParamReceives - remove any RECEIVE opcodes which     */
778 /* refer to dead variables.                                        */
779 /*-----------------------------------------------------------------*/
780 static void 
781 discardDeadParamReceives (eBBlock ** ebbs, int count)
782 {
783   int i;
784   iCode *ic;
785   iCode dummyIcode;
786
787   for (i = 0; i < count; i++)
788     {
789       for (ic = ebbs[i]->sch; ic; ic = ic->next)
790         {
791           if (ic->op == RECEIVE)
792             {
793               if (IC_RESULT (ic) && OP_SYMBOL (IC_RESULT (ic))
794                   && !OP_SYMBOL (IC_RESULT (ic))->used)
795                 {
796 #if 0
797                   fprintf (stderr, "discarding dead receive for %s\n",
798                            OP_SYMBOL (IC_RESULT (ic))->name);
799 #endif
800                   dummyIcode.next = ic->next;
801                   remiCodeFromeBBlock (ebbs[i], ic);
802                   ic = &dummyIcode;
803                 }
804             }
805         }
806     }
807 }
808
809 /*-----------------------------------------------------------------*/
810 /* eBBlockFromiCode - creates extended basic blocks from iCode     */
811 /*                    will return an array of eBBlock pointers     */
812 /*-----------------------------------------------------------------*/
813 eBBlock **
814 eBBlockFromiCode (iCode * ic)
815 {
816   eBBlock **ebbs = NULL;
817   int count = 0;
818   int saveCount = 0;
819   int change = 1;
820   int lchange = 0;
821   int kchange = 0;
822   hTab *loops;
823
824   /* if nothing passed then return nothing */
825   if (!ic)
826     return NULL;
827
828   count = 0;
829   eBBNum = 0;
830
831   /* optimize the chain for labels & gotos 
832      this will eliminate redundant labels and
833      will change jump to jumps by jumps */
834   ic = iCodeLabelOptimize (ic);
835
836   /* break it down into basic blocks */
837   ebbs = iCodeBreakDown (ic, &count);
838   saveCount = count;
839
840   /* compute the control flow */
841   computeControlFlow (ebbs, count, 0);
842
843   /* dumpraw if asked for */
844   if (options.dump_raw)
845     dumpEbbsToFileExt (DUMP_RAW0, ebbs, count);
846
847   /* replace the local variables with their
848      register equivalents : the liveRange computation
849      along with the register allocation will determine
850      if it finally stays in the registers */
851   replaceRegEqv (ebbs, count);
852
853   /* create loop regions */
854   loops = createLoopRegions (ebbs, count);
855
856   /* dumpraw if asked for */
857   if (options.dump_raw)
858     dumpEbbsToFileExt (DUMP_RAW1, ebbs, count);
859
860   /* do common subexpression elimination for each block */
861   change = cseAllBlocks (ebbs, saveCount, FALSE);
862
863   /* dumpraw if asked for */
864   if (options.dump_raw)
865     dumpEbbsToFileExt (DUMP_CSE, ebbs, count);
866
867   /* compute the data flow */
868   computeDataFlow (ebbs, saveCount);
869
870   /* dumpraw if asked for */
871   if (options.dump_raw)
872     dumpEbbsToFileExt (DUMP_DFLOW, ebbs, count);
873
874   /* global common subexpression elimination  */
875   if (optimize.global_cse)
876     {
877       change += cseAllBlocks (ebbs, saveCount, FALSE);
878       if (options.dump_gcse)
879         dumpEbbsToFileExt (DUMP_GCSE, ebbs, saveCount);
880     }
881   else
882     {
883       // compute the dataflow only
884       assert(cseAllBlocks (ebbs, saveCount, TRUE)==0);
885     }
886   /* kill dead code */
887   kchange = killDeadCode (ebbs, saveCount);
888
889   if (options.dump_kill)
890     dumpEbbsToFileExt (DUMP_DEADCODE, ebbs, count);
891
892   /* do loop optimizations */
893   change += (lchange = loopOptimizations (loops, ebbs, count));
894   if (options.dump_loop)
895     dumpEbbsToFileExt (DUMP_LOOP, ebbs, count);
896
897   /* recompute the data flow and apply global cse again 
898      if loops optimizations or dead code caused a change:
899      loops will brings out of the loop which then may be
900      available for use in the later blocks: dead code
901      elimination could potentially disconnect some blocks
902      conditional flow may be efected so we need to apply
903      subexpression once more */
904   if (lchange || kchange)
905     {
906       computeDataFlow (ebbs, saveCount);
907       change += cseAllBlocks (ebbs, saveCount, FALSE);
908       if (options.dump_loop)
909         dumpEbbsToFileExt (DUMP_LOOPG, ebbs, count);
910
911       /* if loop optimizations caused a change then do
912          dead code elimination once more : this will
913          get rid of the extra assignments to the induction
914          variables created during loop optimizations */
915       killDeadCode (ebbs, saveCount);
916
917       if (options.dump_loop)
918         dumpEbbsToFileExt (DUMP_LOOPD, ebbs, count);
919
920     }
921
922   /* sort it back by block number */
923   qsort (ebbs, saveCount, sizeof (eBBlock *), bbNumCompare);
924
925   if (!options.lessPedantic) {
926     // this is a good place to check missing return values
927     if (currFunc) {
928       if (!IS_VOID(currFunc->etype)) {
929         eBBlock *bp;
930         // make sure all predecessors of the last block end in a return
931         for (bp=setFirstItem(ebbs[saveCount-1]->predList); 
932              bp; 
933              bp=setNextItem(ebbs[saveCount-1]->predList)) {
934           if (bp->ech->op != RETURN) {
935             werror (W_VOID_FUNC, currFunc->name);
936           }
937         }
938       }
939     }
940   }
941
942   /* if cyclomatic info requested then print it */
943   if (options.cyclomatic)
944     printCyclomatic (ebbs, saveCount);
945
946   /* convert operations with support routines
947      written in C to function calls : Iam doing
948      this at this point since I want all the
949      operations to be as they are for optimzations */
950   convertToFcall (ebbs, count);
951
952   /* compute the live ranges */
953   computeLiveRanges (ebbs, count);
954
955   if (options.dump_range)
956     dumpEbbsToFileExt (DUMP_RANGE, ebbs, count);
957
958   /* Now that we have the live ranges, discard parameter
959    * receives for unused parameters.
960    */
961   discardDeadParamReceives (ebbs, count);
962
963   /* allocate registers & generate code */
964   port->assignRegisters (ebbs, count);
965
966   /* throw away blocks */
967   setToNull ((void **) &graphEdges);
968   ebbs = NULL;
969   
970   return NULL;
971 }
972
973
974 /* (add-hook 'c-mode-hook (lambda () (setq c-basic-offset 4))) */