* src/SDCCopt.c (killDeadCode): do not throw iCodes away if one
[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           bytesPushed += getSize(operandType(right));
153         }
154
155       addiCodeToeBBlock (ebp, newic, ip);
156       newic->lineno = lineno;
157
158       /* insert push left */
159       if (IS_REGPARM (FUNC_ARGS(func->type)->etype))
160         {
161           newic = newiCode (SEND, left, NULL);
162           newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype);
163         }
164       else
165         {
166           newic = newiCode (IPUSH, left, NULL);
167           newic->parmPush = 1;
168           //bytesPushed+=4;
169           bytesPushed += getSize(operandType(left));
170         }
171       addiCodeToeBBlock (ebp, newic, ip);
172       newic->lineno = lineno;
173     }
174   /* insert the call */
175   newic = newiCode (CALL, operandFromSymbol (func), NULL);
176   IC_RESULT (newic) = IC_RESULT (ic);
177   newic->lineno = lineno;
178   newic->parmBytes+=bytesPushed;
179   ebp->hasFcall = 1;
180   if (currFunc)
181     FUNC_HASFCALL (currFunc->type) = 1;
182     
183   if(TARGET_IS_PIC16) {
184         /* normally these functions aren't marked external, so we can use their
185          * _extern field to marked as already added to symbol table */
186
187         if(!SPEC_EXTR(func->etype)) {
188             memmap *seg = SPEC_OCLS(OP_SYMBOL(IC_LEFT(newic))->etype);
189                 
190                 SPEC_EXTR(func->etype) = 1;
191                 seg = SPEC_OCLS( func->etype );
192                 addSet(&seg->syms, func);
193         }
194   }
195
196   addiCodeToeBBlock (ebp, newic, ip);
197 }
198
199 /*-----------------------------------------------------------------*/
200 /* cnvToFloatCast - converts casts to floats to function calls     */
201 /*-----------------------------------------------------------------*/
202 static void 
203 cnvToFloatCast (iCode * ic, eBBlock * ebp)
204 {
205   iCode *ip, *newic;
206   symbol *func = NULL;
207   sym_link *type = operandType (IC_RIGHT (ic));
208   int linenno = ic->lineno;
209   int bwd, su;
210   int bytesPushed=0;
211
212   ip = ic->next;
213   /* remove it from the iCode */
214   remiCodeFromeBBlock (ebp, ic);
215   /* depending on the type */
216   for (bwd = 0; bwd < 3; bwd++)
217     {
218       for (su = 0; su < 2; su++)
219         {
220           if (compareType (type, __multypes[bwd][su]) == 1)
221             {
222               func = __conv[0][bwd][su];
223               goto found;
224             }
225         }
226     }
227   assert (0);
228 found:
229
230   /* if float support routines NOT compiled as reentrant */
231   if (!options.float_rent)
232     {
233       /* first one */
234         if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) 
235             {
236                 newic = newiCode (SEND, IC_RIGHT (ic), NULL);
237                 newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype);
238             }
239       else
240         {
241           newic = newiCode ('=', NULL, IC_RIGHT (ic));
242           IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type));
243         }
244       addiCodeToeBBlock (ebp, newic, ip);
245       newic->lineno = linenno;
246
247     }
248   else
249     {
250       /* push the left */
251         if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) {
252             newic = newiCode (SEND, IC_RIGHT (ic), NULL);
253             newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype);
254         }
255       else
256         {
257           newic = newiCode (IPUSH, IC_RIGHT (ic), NULL);
258           newic->parmPush = 1;
259           bytesPushed += getSize(operandType(IC_RIGHT(ic)));
260         }
261       addiCodeToeBBlock (ebp, newic, ip);
262       newic->lineno = linenno;
263
264     }
265
266   /* make the call */
267   newic = newiCode (CALL, operandFromSymbol (func), NULL);
268   IC_RESULT (newic) = IC_RESULT (ic);
269   newic->parmBytes+=bytesPushed;
270   ebp->hasFcall = 1;
271   if (currFunc)
272     FUNC_HASFCALL (currFunc->type) = 1;
273
274   if(TARGET_IS_PIC16) {
275         /* normally these functions aren't marked external, so we can use their
276          * _extern field to marked as already added to symbol table */
277
278         if(!SPEC_EXTR(func->etype)) {
279             memmap *seg = SPEC_OCLS(OP_SYMBOL(IC_LEFT(newic))->etype);
280                 
281                 SPEC_EXTR(func->etype) = 1;
282                 seg = SPEC_OCLS( func->etype );
283                 addSet(&seg->syms, func);
284         }
285   }
286
287   addiCodeToeBBlock (ebp, newic, ip);
288   newic->lineno = linenno;
289 }
290
291 /*-----------------------------------------------------------------*/
292 /* cnvFromFloatCast - converts casts From floats to function calls */
293 /*-----------------------------------------------------------------*/
294 static void 
295 cnvFromFloatCast (iCode * ic, eBBlock * ebp)
296 {
297   iCode *ip, *newic;
298   symbol *func = NULL;
299   sym_link *type = operandType (IC_LEFT (ic));
300   int lineno = ic->lineno;
301   int bwd, su;
302   int bytesPushed=0;
303
304   ip = ic->next;
305   /* remove it from the iCode */
306   remiCodeFromeBBlock (ebp, ic);
307
308   /* depending on the type */
309   for (bwd = 0; bwd < 3; bwd++)
310     {
311       for (su = 0; su < 2; su++)
312         {
313           if (compareType (type, __multypes[bwd][su]) == 1)
314             {
315               func = __conv[1][bwd][su];
316               goto found;
317             }
318         }
319     }
320   assert (0);
321 found:
322
323   /* if float support routines NOT compiled as reentrant */
324   if (!options.float_rent)
325     {
326       /* first one */
327         if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) {
328             newic = newiCode (SEND, IC_RIGHT (ic), NULL);
329             newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype);
330         }
331       else
332         {
333           newic = newiCode ('=', NULL, IC_RIGHT (ic));
334           IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type));
335         }
336       addiCodeToeBBlock (ebp, newic, ip);
337       newic->lineno = lineno;
338
339     }
340   else
341     {
342
343       /* push the left */
344         if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) {
345             newic = newiCode (SEND, IC_RIGHT (ic), NULL);
346             newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype);
347         }
348       else
349         {
350           newic = newiCode (IPUSH, IC_RIGHT (ic), NULL);
351           newic->parmPush = 1;
352           bytesPushed += getSize(operandType(IC_RIGHT(ic)));
353         }
354       addiCodeToeBBlock (ebp, newic, ip);
355       newic->lineno = lineno;
356
357     }
358
359   /* make the call */
360   newic = newiCode (CALL, operandFromSymbol (func), NULL);
361   IC_RESULT (newic) = IC_RESULT (ic);
362   newic->parmBytes+=bytesPushed;
363   ebp->hasFcall = 1;
364   if (currFunc)
365     FUNC_HASFCALL (currFunc->type) = 1;
366
367   if(TARGET_IS_PIC16) {
368         /* normally these functions aren't marked external, so we can use their
369          * _extern field to marked as already added to symbol table */
370
371         if(!SPEC_EXTR(func->etype)) {
372             memmap *seg = SPEC_OCLS(OP_SYMBOL(IC_LEFT(newic))->etype);
373                 
374                 SPEC_EXTR(func->etype) = 1;
375                 seg = SPEC_OCLS( func->etype );
376                 addSet(&seg->syms, func);
377         }
378   }
379
380   addiCodeToeBBlock (ebp, newic, ip);
381   newic->lineno = lineno;
382 }
383
384 extern operand *geniCodeRValue (operand *, bool);
385
386 /*-----------------------------------------------------------------*/
387 /* convilong - converts int or long mults or divs to fcalls        */
388 /*-----------------------------------------------------------------*/
389 static void 
390 convilong (iCode * ic, eBBlock * ebp, sym_link * type, int op)
391 {
392   symbol *func = NULL;
393   iCode *ip = ic->next;
394   iCode *newic;
395   int lineno = ic->lineno;
396   int bwd;
397   int su;
398   int bytesPushed=0;
399
400   remiCodeFromeBBlock (ebp, ic);    
401     
402   /* depending on the type */
403   for (bwd = 0; bwd < 3; bwd++)
404     {
405       for (su = 0; su < 2; su++)
406         {
407           if (compareType (type, __multypes[bwd][su]) == 1)
408             {
409               if (op == '*')
410                 func = __muldiv[0][bwd][su];
411               else if (op == '/')
412                 func = __muldiv[1][bwd][su];
413               else if (op == '%')
414                 func = __muldiv[2][bwd][su];
415               else if (op == RRC)
416                 func = __rlrr[1][bwd][su];
417               else if (op == RLC)
418                 func = __rlrr[0][bwd][su];
419               else if (op == RIGHT_OP)
420                 func = __rlrr[1][bwd][su];
421               else if (op == LEFT_OP)
422                 func = __rlrr[0][bwd][su];
423               else
424                 assert (0);
425               goto found;
426             }
427         }
428     }
429   assert (0);
430 found:
431   /* if int & long support routines NOT compiled as reentrant */
432   if (!options.intlong_rent)
433     {
434       /* first one */
435         if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) {
436             newic = newiCode (SEND, IC_LEFT (ic), NULL);
437             newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype);
438         }
439       else
440         {
441           newic = newiCode ('=', NULL, IC_LEFT (ic));
442           IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type));
443         }
444       addiCodeToeBBlock (ebp, newic, ip);
445       newic->lineno = lineno;
446
447       /* second one */
448       if (IS_REGPARM (FUNC_ARGS(func->type)->next->etype)) {
449           newic = newiCode (SEND, IC_RIGHT (ic), NULL);
450           newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->next->etype);
451       }
452       else
453         {
454           newic = newiCode ('=', NULL, IC_RIGHT (ic));
455           IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)->next);
456         }
457       addiCodeToeBBlock (ebp, newic, ip);
458       newic->lineno = lineno;
459
460     }
461   else
462     {
463       /* compiled as reentrant then push */
464       /* push right */
465       if (IS_REGPARM (FUNC_ARGS(func->type)->next->etype))
466         {
467           newic = newiCode (SEND, IC_RIGHT (ic), NULL);
468           newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->next->etype);
469         }
470       else
471         {
472           newic = newiCode (IPUSH, IC_RIGHT (ic), NULL);
473           newic->parmPush = 1;
474
475           bytesPushed += getSize(operandType(IC_RIGHT(ic)));
476         }
477       addiCodeToeBBlock (ebp, newic, ip);
478       newic->lineno = lineno;
479
480       /* insert push left */
481       if (IS_REGPARM (FUNC_ARGS(func->type)->etype))
482         {
483           newic = newiCode (SEND, IC_LEFT (ic), NULL);
484           newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype);
485         }
486       else
487         {
488           newic = newiCode (IPUSH, IC_LEFT (ic), NULL);
489           newic->parmPush = 1;
490
491           bytesPushed += getSize(operandType(IC_LEFT(ic)));
492         }
493       addiCodeToeBBlock (ebp, newic, ip);
494       newic->lineno = lineno;
495
496     }
497
498   /* for the result */
499   newic = newiCode (CALL, operandFromSymbol (func), NULL);
500   IC_RESULT (newic) = IC_RESULT (ic);
501   newic->lineno = lineno;
502   newic->parmBytes+=bytesPushed; // to clear the stack after the call
503   ebp->hasFcall = 1;
504   if (currFunc)
505     FUNC_HASFCALL (currFunc->type) = 1;
506
507   if(TARGET_IS_PIC16) {
508         /* normally these functions aren't marked external, so we can use their
509          * _extern field to marked as already added to symbol table */
510
511         if(!SPEC_EXTR(func->etype)) {
512             memmap *seg = SPEC_OCLS(OP_SYMBOL(IC_LEFT(newic))->etype);
513                 
514                 SPEC_EXTR(func->etype) = 1;
515                 seg = SPEC_OCLS( func->etype );
516                 addSet(&seg->syms, func);
517         }
518   }
519
520   addiCodeToeBBlock (ebp, newic, ip);
521 }
522
523 /*-----------------------------------------------------------------*/
524 /* convertToFcall - converts some operations to fcalls             */
525 /*-----------------------------------------------------------------*/
526 static void 
527 convertToFcall (eBBlock ** ebbs, int count)
528 {
529   int i;
530
531   /* for all blocks do */
532   for (i = 0; i < count; i++)
533     {
534       iCode *ic;
535
536       /* for all instructions in the block do */
537       for (ic = ebbs[i]->sch; ic; ic = ic->next)
538         {
539
540           /* floating point operations are
541              converted to function calls */
542           if ((IS_CONDITIONAL (ic) ||
543                IS_ARITHMETIC_OP (ic)) &&
544               (IS_FLOAT (operandType (IC_RIGHT (ic)))))
545             {
546
547               cnvToFcall (ic, ebbs[i]);
548             }
549
550           /* casting is a little different */
551           if (ic->op == CAST)
552             {
553               if (IS_FLOAT (operandType (IC_RIGHT (ic))))
554                 cnvFromFloatCast (ic, ebbs[i]);
555               else if (IS_FLOAT (operandType (IC_LEFT (ic))))
556                 cnvToFloatCast (ic, ebbs[i]);
557             }
558
559           // Easy special case which avoids function call: modulo by a literal power
560           // of two can be replaced by a bitwise AND.
561           if (ic->op == '%' && isOperandLiteral(IC_RIGHT(ic)) &&
562               IS_UNSIGNED(operandType(IC_LEFT(ic))))
563             {
564               unsigned litVal = abs(operandLitValue(IC_RIGHT(ic)));
565
566               // See if literal value is a power of 2.
567               while (litVal && !(litVal & 1))
568                 {
569                   litVal >>= 1;
570                 }
571               if (litVal)
572                 {
573                   // discard lowest set bit.
574                   litVal >>= 1;
575                 }
576
577               if (!litVal)
578                 {
579                   ic->op = BITWISEAND;
580                   IC_RIGHT(ic) = operandFromLit(operandLitValue(IC_RIGHT(ic)) - 1);
581                   continue;
582                 }
583             }
584
585           /* if long / int mult or divide or mod */
586           if (ic->op == '*' || ic->op == '/' || ic->op == '%')
587             {
588               sym_link *leftType = operandType (IC_LEFT (ic));
589
590               if (IS_INTEGRAL (leftType) && getSize (leftType) > port->support.muldiv)
591                 {
592                   sym_link *rightType = operandType (IC_RIGHT (ic));
593
594                   if (port->hasNativeMulFor != NULL &&
595                       port->hasNativeMulFor (ic, leftType, rightType))
596                     {
597                       /* Leave as native */
598                     }
599                   else
600                     {
601                       convilong (ic, ebbs[i], leftType, ic->op);
602                     }
603                 }
604             }
605           
606           if (ic->op == RRC || ic->op == RLC || ic->op == LEFT_OP || ic->op == RIGHT_OP)
607             {
608               sym_link *type = operandType (IC_LEFT (ic));
609
610               if (IS_INTEGRAL (type) && getSize (type) > port->support.shift && port->support.shift >= 0)
611                 {
612                   convilong (ic, ebbs[i], type, ic->op);
613                 }
614             }
615         }
616     }
617 }
618
619 /*-----------------------------------------------------------------*/
620 /* isLocalWithoutDef - return 1 if sym might be used without a     */
621 /*                     defining iCode                              */
622 /*-----------------------------------------------------------------*/
623 static int
624 isLocalWithoutDef (symbol * sym)
625 {
626   if (!IS_AUTO (sym))
627     return 0;
628   
629   if (IS_VOLATILE (sym->type))
630     return 0;
631   
632   if (sym->_isparm)
633     return 0;
634   
635   if (IS_AGGREGATE (sym->type))
636     return 0;
637   
638   if (sym->addrtaken)
639     return 0;
640   
641   return !sym->defs;
642 }
643
644 /*-----------------------------------------------------------------*/
645 /* replaceRegEqv - replace all local variables with their reqv     */
646 /*-----------------------------------------------------------------*/
647 static void 
648 replaceRegEqv (eBBlock ** ebbs, int count)
649 {
650   int i;
651
652   /* Update the symbols' def bitvector so we know if there is   */
653   /* a defining iCode or not. Only replace a local variable     */
654   /* with its register equivalent if there is a defining iCode; */
655   /* otherwise, the port's register allocater may choke.        */
656   cseAllBlocks (ebbs, count, TRUE);
657
658   for (i = 0; i < count; i++)
659     {
660
661       iCode *ic;
662
663       for (ic = ebbs[i]->sch; ic; ic = ic->next)
664         {
665
666           if (SKIP_IC2 (ic))
667             continue;
668
669           if (ic->op == IFX)
670             {
671               if (IC_COND (ic) &&
672                   IS_TRUE_SYMOP (IC_COND (ic)) &&
673                   isLocalWithoutDef (OP_SYMBOL (IC_COND (ic))))
674                 {
675                   werrorfl (ic->filename, ic->lineno,
676                           W_LOCAL_NOINIT,
677                           OP_SYMBOL (IC_COND (ic))->name);
678                   OP_REQV (IC_COND (ic)) = NULL;
679                   OP_SYMBOL (IC_COND (ic))->allocreq = 1;
680                 }
681               
682               if (IS_TRUE_SYMOP (IC_COND (ic)) &&
683                   OP_REQV (IC_COND (ic)))
684                 IC_COND (ic) = opFromOpWithDU (OP_REQV (IC_COND (ic)),
685                                              OP_SYMBOL (IC_COND (ic))->defs,
686                                             OP_SYMBOL (IC_COND (ic))->uses);
687
688               continue;
689             }
690
691           
692           if (ic->op == JUMPTABLE)
693             {
694               if (IC_JTCOND (ic) &&
695                   IS_TRUE_SYMOP (IC_JTCOND (ic)) &&
696                   isLocalWithoutDef (OP_SYMBOL (IC_JTCOND (ic))))
697                 {
698                   werrorfl (ic->filename, ic->lineno,
699                           W_LOCAL_NOINIT,
700                           OP_SYMBOL (IC_JTCOND (ic))->name);
701                   OP_REQV (IC_JTCOND (ic)) = NULL;
702                   OP_SYMBOL (IC_JTCOND (ic))->allocreq = 1;
703                 }
704               
705               if (IS_TRUE_SYMOP (IC_JTCOND (ic)) &&
706                   OP_REQV (IC_JTCOND (ic)))
707                 IC_JTCOND (ic) = opFromOpWithDU (OP_REQV (IC_JTCOND (ic)),
708                                            OP_SYMBOL (IC_JTCOND (ic))->defs,
709                                           OP_SYMBOL (IC_JTCOND (ic))->uses);
710               continue;
711             }
712
713           if (ic->op == RECEIVE)
714             {
715               if (OP_SYMBOL (IC_RESULT (ic))->addrtaken)
716                 OP_SYMBOL (IC_RESULT (ic))->isspilt = 1;
717             }
718
719           /* general case */
720           if (IC_RESULT (ic) &&
721               IS_TRUE_SYMOP (IC_RESULT (ic)) &&
722               OP_REQV (IC_RESULT (ic)))
723             {
724               if (POINTER_SET (ic))
725                 {
726                   IC_RESULT (ic) = opFromOpWithDU (OP_REQV (IC_RESULT (ic)),
727                                            OP_SYMBOL (IC_RESULT (ic))->defs,
728                                           OP_SYMBOL (IC_RESULT (ic))->uses);
729                   IC_RESULT (ic)->isaddr = 1;
730                 }
731               else
732                 IC_RESULT (ic) = opFromOpWithDU (OP_REQV (IC_RESULT (ic)),
733                                            OP_SYMBOL (IC_RESULT (ic))->defs,
734                                           OP_SYMBOL (IC_RESULT (ic))->uses);
735             }
736
737           if (IC_RIGHT (ic) &&
738               IS_TRUE_SYMOP (IC_RIGHT (ic)) &&
739               isLocalWithoutDef (OP_SYMBOL (IC_RIGHT (ic))))
740             {
741               werrorfl (ic->filename, ic->lineno,
742                         W_LOCAL_NOINIT,
743                         OP_SYMBOL (IC_RIGHT (ic))->name);
744               OP_REQV (IC_RIGHT (ic)) = NULL;
745               OP_SYMBOL (IC_RIGHT (ic))->allocreq = 1;
746             }
747           
748           if (IC_RIGHT (ic) &&
749               IS_TRUE_SYMOP (IC_RIGHT (ic)) &&
750               OP_REQV (IC_RIGHT (ic)))
751             {
752               IC_RIGHT (ic) = opFromOpWithDU (OP_REQV (IC_RIGHT (ic)),
753                                             OP_SYMBOL (IC_RIGHT (ic))->defs,
754                                            OP_SYMBOL (IC_RIGHT (ic))->uses);
755               IC_RIGHT (ic)->isaddr = 0;
756             }
757
758           if (IC_LEFT (ic) &&
759               IS_TRUE_SYMOP (IC_LEFT (ic)) &&
760               isLocalWithoutDef (OP_SYMBOL (IC_LEFT (ic))))
761             {
762               werrorfl (ic->filename, ic->lineno,
763                         W_LOCAL_NOINIT,
764                         OP_SYMBOL (IC_LEFT (ic))->name);
765               OP_REQV (IC_LEFT (ic)) = NULL;
766               OP_SYMBOL (IC_LEFT (ic))->allocreq = 1;
767             }
768             
769           if (IC_LEFT (ic) &&
770               IS_TRUE_SYMOP (IC_LEFT (ic)) &&
771               OP_REQV (IC_LEFT (ic)))
772             {
773               IC_LEFT (ic) = opFromOpWithDU (OP_REQV (IC_LEFT (ic)),
774                                              OP_SYMBOL (IC_LEFT (ic))->defs,
775                                              OP_SYMBOL (IC_LEFT (ic))->uses);
776               IC_LEFT (ic)->isaddr = 0;
777             }
778         }
779     }
780 }
781
782 /*-----------------------------------------------------------------*/
783 /* findReqv - search for a register equivalent                     */
784 /*-----------------------------------------------------------------*/
785 operand *
786 findReqv (symbol * prereqv, eBBlock ** ebbs, int count)
787 {
788   int i;
789   iCode * ic;
790   
791   /* for all blocks do */
792   for (i=0; i<count; i++)
793     {
794       /* for all instructions in the block do */
795       for (ic = ebbs[i]->sch; ic; ic = ic->next)
796         {
797           if (ic->op == IFX)
798             {
799               if (IS_ITEMP (IC_COND (ic))
800                   && OP_SYMBOL (IC_COND (ic))->prereqv == prereqv)
801                 return IC_COND (ic);
802             }
803           else if (ic->op == JUMPTABLE)
804             {
805               if (IS_ITEMP (IC_JTCOND (ic))
806                   && OP_SYMBOL (IC_JTCOND (ic))->prereqv == prereqv)
807                 return IC_JTCOND (ic);
808             }
809           else
810             {
811               if (IS_ITEMP (IC_LEFT (ic))
812                   && OP_SYMBOL (IC_LEFT (ic))->prereqv == prereqv)
813                 return IC_LEFT (ic);
814               if (IS_ITEMP (IC_RIGHT (ic))
815                   && OP_SYMBOL (IC_RIGHT (ic))->prereqv == prereqv)
816                 return IC_RIGHT (ic);
817               if (IS_ITEMP (IC_RESULT (ic))
818                   && OP_SYMBOL (IC_RESULT (ic))->prereqv == prereqv)
819                 return IC_RESULT (ic);
820             }
821         }
822     }
823   
824   return NULL;
825 }
826
827 /*-----------------------------------------------------------------*/
828 /* killDeadCode - eliminates dead assignments                      */
829 /*-----------------------------------------------------------------*/
830 int 
831 killDeadCode (eBBlock ** ebbs, int count)
832 {
833   int change = 1;
834   int gchange = 0;
835   int i = 0;
836
837
838   /* basic algorithm :-                                          */
839   /* first the exclusion rules :-                                */
840   /*  1. if result is a global or volatile then skip             */
841   /*  2. if assignment and result is a temp & isaddr  then skip  */
842   /*     since this means array & pointer access, will be taken  */
843   /*     care of by alias analysis.                              */
844   /*  3. if the result is used in the remainder of the block skip */
845   /*  4. if this definition does not reach the end of the block  */
846   /*     i.e. the result is not present in the outExprs then KILL */
847   /*  5. if it reaches the end of block & is used by some success */
848   /*     or then skip                                            */
849   /*     else            KILL                                    */
850   /* this whole process is carried on iteratively till no change */
851   while (1)
852     {
853
854       change = 0;
855       /* for all blocks do */
856       for (i = 0; i < count; i++)
857         {
858           iCode *ic;
859
860           /* for all instructions in the block do */
861           for (ic = ebbs[i]->sch; ic; ic = ic->next)
862             {
863               int kill, j;
864               kill = 0;
865
866               if (SKIP_IC (ic) ||
867                   ic->op == IFX ||
868                   ic->op == RETURN ||
869                   ic->op == DUMMY_READ_VOLATILE ||
870                   ic->op == CRITICAL ||
871                   ic->op == ENDCRITICAL)
872                 continue;
873
874               /* Since both IFX & JUMPTABLE (in SKIP_IC) have been tested for */
875               /* it is now safe to assume IC_LEFT, IC_RIGHT, & IC_RESULT are  */
876               /* valid. */
877
878               /* if the result is volatile then continue */
879               if (IC_RESULT (ic) && isOperandVolatile (IC_RESULT (ic), FALSE))
880                 continue;
881
882               /* We also cannot remove the iCode, when an operand is volatile.       */
883               /* Even read access can cause side effects on some hardware registers! */
884
885               /* if the left operand is volatile then continue */
886               if (IC_LEFT(ic) && isOperandVolatile (IC_LEFT (ic), TRUE))
887                 continue;
888
889               /* if the right operand is volatile then continue */
890               if (IC_RIGHT(ic) && isOperandVolatile (IC_RIGHT (ic), TRUE))
891                 continue;
892
893
894               /* if the result is a temp & isaddr then skip */
895               if (IC_RESULT (ic) && POINTER_SET (ic))
896                 continue;
897               
898               if (POINTER_GET (ic) && IS_VOLATILE (operandType (IC_LEFT (ic))->next)
899                   && !SPIL_LOC (IC_RESULT (ic)))
900                 continue;
901
902               /* if the result is used in the remainder of the */
903               /* block then skip */
904               if (usedInRemaining (IC_RESULT (ic), ic->next))
905                 continue;
906
907               /* does this definition reach the end of the block 
908                  or the usage is zero then we can kill */
909               if (!bitVectBitValue (ebbs[i]->outDefs, ic->key))
910                 kill = 1;       /* if not we can kill it */
911               else
912                 {
913                   /* if this is a global variable or function parameter */
914                   /* we cannot kill anyway             */
915                   if (isOperandGlobal (IC_RESULT (ic)) ||
916                       (OP_SYMBOL (IC_RESULT (ic))->_isparm &&
917                        !OP_SYMBOL (IC_RESULT (ic))->ismyparm))
918                     continue;
919
920                   /* if we are sure there are no usages */
921                   if (bitVectIsZero (OP_USES (IC_RESULT (ic))))
922                     {
923                       kill = 1;
924                       goto kill;
925                     }
926
927                   /* reset visited flag */
928                   for (j = 0; j < count; ebbs[j++]->visited = 0);
929
930                   /* find out if this definition is alive */
931                   if (applyToSet (ebbs[i]->succList,
932                                   isDefAlive,
933                                   ic))
934                     continue;
935
936                   kill = 1;
937                 }
938
939             kill:
940               /* kill this one if required */
941               if (kill)
942                 {
943                   bool volLeft = IS_SYMOP (IC_LEFT (ic))
944                                  && isOperandVolatile (IC_LEFT (ic), FALSE);
945                   bool volRight = IS_SYMOP (IC_RIGHT (ic)) 
946                                   && isOperandVolatile (IC_RIGHT (ic), FALSE);
947
948                   /* a dead address-of operation should die, even if volatile */
949                   if (ic->op == ADDRESS_OF)
950                     volLeft = FALSE;
951
952                   if (ic->next && ic->seqPoint == ic->next->seqPoint
953                       && (ic->next->op == '+' || ic->next->op == '-'))
954                     {
955                       if (isOperandEqual (IC_LEFT(ic), IC_LEFT(ic->next))
956                           || isOperandEqual (IC_LEFT(ic), IC_RIGHT(ic->next)))
957                         volLeft = FALSE;
958                       if (isOperandEqual (IC_RIGHT(ic), IC_LEFT(ic->next))
959                           || isOperandEqual (IC_RIGHT(ic), IC_RIGHT(ic->next)))
960                         volRight = FALSE;
961                     }
962                   
963                   if (POINTER_GET (ic) && IS_VOLATILE (operandType (IC_LEFT (ic))->next))
964                     {
965                       if (SPIL_LOC (IC_RESULT (ic)))
966                         {
967                           IC_RESULT (ic) = newiTempFromOp (IC_RESULT (ic));
968                           SPIL_LOC (IC_RESULT (ic)) = NULL;
969                         }
970                       continue;
971                     }
972                   
973                   change = 1;
974                   gchange++;
975                   
976                   /* now delete from defUseSet */
977                   deleteItemIf (&ebbs[i]->outExprs, ifDiCodeIsX, ic);
978                   bitVectUnSetBit (ebbs[i]->outDefs, ic->key);
979
980                   /* and defset of the block */
981                   bitVectUnSetBit (ebbs[i]->defSet, ic->key);
982
983                   /* If this is the last of a register equivalent, */
984                   /* look for a successor register equivalent. */
985                   bitVectUnSetBit (OP_DEFS (IC_RESULT (ic)), ic->key);
986                   if (IS_ITEMP (IC_RESULT (ic))
987                       && OP_SYMBOL (IC_RESULT (ic))->isreqv
988                       && bitVectIsZero (OP_DEFS (IC_RESULT (ic))))
989                     {
990                       symbol * resultsym = OP_SYMBOL (IC_RESULT (ic));
991                       symbol * prereqv = resultsym->prereqv;
992                       
993                       if (OP_SYMBOL (prereqv->reqv) == resultsym)
994                         {
995                           operand * newreqv;
996
997                           IC_RESULT (ic) = NULL;
998                           newreqv = findReqv (prereqv, ebbs, count);
999                           if (newreqv)
1000                             {
1001                               prereqv->reqv = newreqv;
1002                             }
1003                         }
1004                     }
1005
1006                   /* delete the result */
1007                   IC_RESULT (ic) = NULL;
1008                   
1009                   if (volLeft || volRight)
1010                     {
1011                       /* something is volatile, so keep the iCode */
1012                       /* and change the operator instead */
1013                       ic->op = DUMMY_READ_VOLATILE;
1014
1015                       /* keep only the volatile operands */      
1016                       if (!volLeft)
1017                         IC_LEFT (ic) = NULL;
1018                       if (!volRight)
1019                         IC_RIGHT (ic) = NULL;
1020                     }
1021                   else
1022                     {
1023                       /* nothing is volatile, eliminate the iCode */
1024                       remiCodeFromeBBlock (ebbs[i], ic);
1025
1026                       /* for the left & right remove the usage */
1027                       if (IS_SYMOP (IC_LEFT (ic)))
1028                         bitVectUnSetBit (OP_USES (IC_LEFT (ic)), ic->key);
1029
1030                       if (IS_SYMOP (IC_RIGHT (ic)))
1031                         bitVectUnSetBit (OP_USES (IC_RIGHT (ic)), ic->key);
1032                     }
1033                 }
1034
1035             }                   /* end of all instructions */
1036
1037           if (!ebbs[i]->sch && !ebbs[i]->noPath)
1038             disconBBlock (ebbs[i], ebbs, count);
1039
1040         }                       /* end of for all blocks */
1041
1042       if (!change)
1043         break;
1044     }                           /* end of while(1) */
1045
1046   return gchange;
1047 }
1048
1049 /*-----------------------------------------------------------------*/
1050 /* printCyclomatic - prints the cyclomatic information             */
1051 /*-----------------------------------------------------------------*/
1052 static void 
1053 printCyclomatic (eBBlock ** ebbs, int count)
1054 {
1055   int nEdges = elementsInSet (graphEdges);
1056   int i, nNodes = 0;
1057
1058   for (i = 0; i < count; i++)
1059     nNodes += (!ebbs[i]->noPath);
1060
1061   /* print the information */
1062   werror (I_CYCLOMATIC, currFunc->name, nEdges, nNodes, nEdges - nNodes + 2);
1063 }
1064
1065 /*-----------------------------------------------------------------*/
1066 /* discardDeadParamReceives - remove any RECEIVE opcodes which     */
1067 /* refer to dead variables.                                        */
1068 /*-----------------------------------------------------------------*/
1069 static void 
1070 discardDeadParamReceives (eBBlock ** ebbs, int count)
1071 {
1072   int i;
1073   iCode *ic;
1074   iCode dummyIcode;
1075
1076   for (i = 0; i < count; i++)
1077     {
1078       for (ic = ebbs[i]->sch; ic; ic = ic->next)
1079         {
1080           if (ic->op == RECEIVE)
1081             {
1082               if (IC_RESULT (ic) && OP_SYMBOL (IC_RESULT (ic))
1083                   && !OP_SYMBOL (IC_RESULT (ic))->used)
1084                 {
1085 #if 0
1086                   fprintf (stderr, "discarding dead receive for %s\n",
1087                            OP_SYMBOL (IC_RESULT (ic))->name);
1088 #endif
1089                   dummyIcode.next = ic->next;
1090                   remiCodeFromeBBlock (ebbs[i], ic);
1091                   ic = &dummyIcode;
1092                 }
1093             }
1094         }
1095     }
1096 }
1097
1098 /*-----------------------------------------------------------------*/
1099 /* optimizeCastCast - remove unneeded intermediate casts.          */
1100 /* Integer promotion may cast (un)signed char to int and then      */
1101 /* recast the int to (un)signed long. If the signedness of the     */
1102 /* char and long are the same, the cast can be safely performed in */
1103 /* a single step.                                                  */
1104 /*-----------------------------------------------------------------*/
1105 static void 
1106 optimizeCastCast (eBBlock ** ebbs, int count)
1107 {
1108   int i;
1109   iCode *ic;
1110   iCode *uic;
1111   sym_link * type1;
1112   sym_link * type2;
1113   sym_link * type3;
1114   symbol * sym;
1115
1116   for (i = 0; i < count; i++)
1117     {
1118       for (ic = ebbs[i]->sch; ic; ic = ic->next)
1119         {
1120           
1121           if (ic->op == CAST && IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
1122             {
1123               type1 = operandType (IC_RIGHT (ic));
1124               type2 = operandType (IC_RESULT (ic));
1125
1126               /* Look only for a cast from an integer type to an */
1127               /* integer type that has no loss of bits */
1128               if (!IS_INTEGRAL (type1) || !IS_INTEGRAL (type2))
1129                 continue;
1130               if (getSize (type2) < getSize (type1))
1131                 continue;
1132               
1133               /* There must be only one use of this first result */
1134               if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) != 1)
1135                 continue;
1136               
1137               /* This use must be a second cast */
1138               uic = hTabItemWithKey (iCodehTab,
1139                         bitVectFirstBit (OP_USES (IC_RESULT (ic))));
1140               if (!uic || uic->op != CAST)
1141                 continue;
1142   
1143               /* It must be a cast to another integer type that */
1144               /* has no loss of bits */
1145               type3 = operandType (IC_RESULT (uic));
1146               if (!IS_INTEGRAL (type3))
1147                  continue;
1148               if (getSize (type3) < getSize (type2))
1149                  continue;
1150               
1151               /* The signedness between the first and last types */
1152               /* must match */
1153               if (SPEC_USIGN (type3) != SPEC_USIGN (type1))
1154                  continue;
1155
1156               /* Change the first cast to a simple assignment and */
1157               /* let the second cast do all the work */
1158               ic->op = '=';
1159               IC_LEFT (ic) = NULL;
1160               sym = OP_SYMBOL (IC_RESULT (ic));
1161               sym->type = copyLinkChain (type1);
1162               sym->etype = getSpec (sym->type);
1163             }
1164         }
1165     }
1166 }
1167
1168 /*-----------------------------------------------------------------*/
1169 /* eBBlockFromiCode - creates extended basic blocks from iCode     */
1170 /*                    will return an array of eBBlock pointers     */
1171 /*-----------------------------------------------------------------*/
1172 eBBlock **
1173 eBBlockFromiCode (iCode * ic)
1174 {
1175   eBBlock **ebbs = NULL;
1176   int count = 0;
1177   int saveCount = 0;
1178   int change = 1;
1179   int lchange = 0;
1180   int kchange = 0;
1181   hTab *loops;
1182
1183   /* if nothing passed then return nothing */
1184   if (!ic)
1185     return NULL;
1186
1187   count = 0;
1188   eBBNum = 0;
1189
1190   /* optimize the chain for labels & gotos 
1191      this will eliminate redundant labels and
1192      will change jump to jumps by jumps */
1193   ic = iCodeLabelOptimize (ic);
1194
1195   /* break it down into basic blocks */
1196   ebbs = iCodeBreakDown (ic, &count);
1197   saveCount = count;
1198
1199   /* hash the iCode keys so that we can quickly index */
1200   /* them in the rest of the optimization steps */
1201   setToNull ((void *) &iCodehTab);
1202   iCodehTab = newHashTable (iCodeKey);
1203   hashiCodeKeys (ebbs, count);
1204   
1205   /* compute the control flow */
1206   computeControlFlow (ebbs, count, 0);
1207
1208   /* dumpraw if asked for */
1209   if (options.dump_raw)
1210     dumpEbbsToFileExt (DUMP_RAW0, ebbs, count);
1211
1212   /* replace the local variables with their
1213      register equivalents : the liveRange computation
1214      along with the register allocation will determine
1215      if it finally stays in the registers */
1216   replaceRegEqv (ebbs, count);
1217
1218   /* create loop regions */
1219   loops = createLoopRegions (ebbs, count);
1220
1221   /* dumpraw if asked for */
1222   if (options.dump_raw)
1223     dumpEbbsToFileExt (DUMP_RAW1, ebbs, count);
1224
1225   optimizeCastCast (ebbs, saveCount);
1226     
1227   /* do common subexpression elimination for each block */
1228   change = cseAllBlocks (ebbs, saveCount, FALSE);
1229
1230   /* dumpraw if asked for */
1231   if (options.dump_raw)
1232     dumpEbbsToFileExt (DUMP_CSE, ebbs, count);
1233
1234   /* compute the data flow */
1235   computeDataFlow (ebbs, saveCount);
1236
1237   /* dumpraw if asked for */
1238   if (options.dump_raw)
1239     dumpEbbsToFileExt (DUMP_DFLOW, ebbs, count);
1240
1241   /* global common subexpression elimination  */
1242   if (optimize.global_cse)
1243     {
1244       change += cseAllBlocks (ebbs, saveCount, FALSE);
1245       if (options.dump_gcse)
1246         dumpEbbsToFileExt (DUMP_GCSE, ebbs, saveCount);
1247     }
1248   else
1249     {
1250       // compute the dataflow only
1251       assert(cseAllBlocks (ebbs, saveCount, TRUE)==0);
1252     }
1253   /* kill dead code */
1254   kchange = killDeadCode (ebbs, saveCount);
1255
1256   if (options.dump_kill)
1257     dumpEbbsToFileExt (DUMP_DEADCODE, ebbs, count);
1258
1259   /* do loop optimizations */
1260   change += (lchange = loopOptimizations (loops, ebbs, count));
1261   if (options.dump_loop)
1262     dumpEbbsToFileExt (DUMP_LOOP, ebbs, count);
1263
1264   /* recompute the data flow and apply global cse again 
1265      if loops optimizations or dead code caused a change:
1266      loops will brings out of the loop which then may be
1267      available for use in the later blocks: dead code
1268      elimination could potentially disconnect some blocks
1269      conditional flow may be efected so we need to apply
1270      subexpression once more */
1271   if (lchange || kchange)
1272     {
1273       computeDataFlow (ebbs, saveCount);
1274       change += cseAllBlocks (ebbs, saveCount, FALSE);
1275       if (options.dump_loop)
1276         dumpEbbsToFileExt (DUMP_LOOPG, ebbs, count);
1277
1278       /* if loop optimizations caused a change then do
1279          dead code elimination once more : this will
1280          get rid of the extra assignments to the induction
1281          variables created during loop optimizations */
1282       killDeadCode (ebbs, saveCount);
1283
1284       if (options.dump_loop)
1285         dumpEbbsToFileExt (DUMP_LOOPD, ebbs, count);
1286
1287     }
1288
1289   /* sort it back by block number */
1290   qsort (ebbs, saveCount, sizeof (eBBlock *), bbNumCompare);
1291
1292   if (!options.lessPedantic) {
1293     // this is a good place to check missing return values
1294     if (currFunc) {
1295       // the user is on his own with naked functions...
1296       if (!IS_VOID(currFunc->etype)
1297        && !FUNC_ISNAKED(currFunc->type)) {
1298         eBBlock *bp;
1299         // make sure all predecessors of the last block end in a return
1300         for (bp=setFirstItem(ebbs[saveCount-1]->predList); 
1301              bp; 
1302              bp=setNextItem(ebbs[saveCount-1]->predList)) {
1303           if (bp->ech->op != RETURN) {
1304             werrorfl (bp->ech->filename, bp->ech->lineno,
1305                       W_VOID_FUNC, currFunc->name);
1306           }
1307         }
1308       }
1309     }
1310   }
1311
1312   /* if cyclomatic info requested then print it */
1313   if (options.cyclomatic)
1314     printCyclomatic (ebbs, saveCount);
1315
1316   /* convert operations with support routines
1317      written in C to function calls : Iam doing
1318      this at this point since I want all the
1319      operations to be as they are for optimzations */
1320   convertToFcall (ebbs, count);
1321
1322   /* compute the live ranges */
1323   computeLiveRanges (ebbs, count);
1324
1325   if (options.dump_range)
1326     dumpEbbsToFileExt (DUMP_RANGE, ebbs, count);
1327
1328   /* Now that we have the live ranges, discard parameter
1329    * receives for unused parameters.
1330    */
1331   discardDeadParamReceives (ebbs, count);
1332
1333   /* allocate registers & generate code */
1334   port->assignRegisters (ebbs, count);
1335
1336   /* throw away blocks */
1337   setToNull ((void *) &graphEdges);
1338   ebbs = NULL;
1339   
1340   return NULL;
1341 }
1342
1343
1344 /* (add-hook 'c-mode-hook (lambda () (setq c-basic-offset 4))) */