Fix peephole rule condition functions properly; add special case so test for bug...
[fw/sdcc] / src / SDCCcse.c
1 //#define LIVERANGEHUNT
2 #ifdef LIVERANGEHUNT
3   #define LRH(x) x
4 #else
5   #define LRH(x)
6 #endif
7 /*-------------------------------------------------------------------------
8   SDCCcse.c - source file for Common Subexpressions and other utility
9
10              Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
11
12    This program is free software; you can redistribute it and/or modify it
13    under the terms of the GNU General Public License as published by the
14    Free Software Foundation; either version 2, or (at your option) any
15    later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software
24    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25
26    In other words, you are welcome to use, share and improve this program.
27    You are forbidden to forbid anyone else to use, share and improve
28    what you give them.   Help stamp out software-hoarding!
29 -------------------------------------------------------------------------*/
30
31 #include "common.h"
32 #include "newalloc.h"
33
34 /*-----------------------------------------------------------------*/
35 /* newCseDef - new cseDef                                          */
36 /*-----------------------------------------------------------------*/
37 cseDef *
38 newCseDef (operand * sym, iCode * ic)
39 {
40   cseDef *cdp;
41
42   assert (sym);
43   cdp = Safe_alloc (sizeof (cseDef));
44
45   cdp->sym = sym;
46   cdp->diCode = ic;
47   cdp->key = sym->key;
48
49   return cdp;
50 }
51
52
53
54 /*-----------------------------------------------------------------*/
55 /* int isCseDefEqual - two definitions are equal                   */
56 /*-----------------------------------------------------------------*/
57 int 
58 isCseDefEqual (void *vsrc, void *vdest)
59 {
60   cseDef *src = vsrc;
61   cseDef *dest = vdest;
62
63   if (src == dest)
64     return 1;
65
66   return (src->key == dest->key &&
67           src->diCode == dest->diCode);
68
69 }
70
71 /*-----------------------------------------------------------------*/
72 /* pcseDef - in the cseDef                                         */
73 /*-----------------------------------------------------------------*/
74 int 
75 pcseDef (void *item, va_list ap)
76 {
77   cseDef *cdp = item;
78   iCodeTable *icTab;
79
80   (void) ap;
81
82   if (!cdp->sym)
83     fprintf (stdout, "**null op**");
84   printOperand (cdp->sym, stdout);
85   icTab = getTableEntry (cdp->diCode->op);
86   icTab->iCodePrint (stdout, cdp->diCode, icTab->printName);
87   return 1;
88 }
89
90 void ReplaceOpWithCheaperOp(operand **op, operand *cop) {
91 #ifdef RANGEHUNT
92   printf ("ReplaceOpWithCheaperOp (%s:%d with %s:%d): ", 
93           OP_SYMBOL((*op))->name, OP_SYMBOL((*op))->isreqv,
94           OP_SYMBOL(cop)->name, OP_SYMBOL(cop)->isreqv);
95   // if op is a register equivalent
96   if (IS_ITEMP(cop) && OP_SYMBOL((*op))->isreqv) {
97     operand **rop = &OP_SYMBOL((*op))->usl.spillLoc->reqv;
98     if (isOperandEqual(*rop, *op)) {
99       printf ("true");
100       *rop=cop;
101       OP_SYMBOL((*op))->isreqv=0;
102       OP_SYMBOL(cop)->isreqv=1;
103     } else {
104       printf ("false");
105     }
106   }
107   printf ("\n");
108 #endif
109   *op=cop;
110 }
111
112 /*-----------------------------------------------------------------*/
113 /* replaceAllSymBySym - replaces all operands by operand in an     */
114 /*                      instruction chain                          */
115 /*-----------------------------------------------------------------*/
116 void 
117 replaceAllSymBySym (iCode * ic, operand * from, operand * to, bitVect ** ndpset)
118 {
119   iCode *lic;
120
121   LRH(printf ("replaceAllSymBySym: from %s to %s\n", OP_SYMBOL(from)->name, OP_SYMBOL(to)->name));
122   for (lic = ic; lic; lic = lic->next)
123     {
124       int siaddr;
125
126       /* do the special cases first */
127       if (lic->op == IFX)
128         {
129           if (IS_SYMOP (to) &&
130               IC_COND (lic)->key == from->key)
131             {
132
133               bitVectUnSetBit (OP_USES (from), lic->key);
134               OP_USES(to)=bitVectSetBit (OP_USES (to), lic->key);
135               siaddr = IC_COND (lic)->isaddr;
136               IC_COND (lic) = operandFromOperand (to);
137               IC_COND (lic)->isaddr = siaddr;
138
139             }
140           continue;
141         }
142
143       if (lic->op == JUMPTABLE)
144         {
145           if (IS_SYMOP (to) &&
146               IC_JTCOND (lic)->key == from->key)
147             {
148
149               bitVectUnSetBit (OP_USES (from), lic->key);
150               OP_USES(to)=bitVectSetBit (OP_USES (to), lic->key);
151               siaddr = IC_COND (lic)->isaddr;
152               IC_JTCOND (lic) = operandFromOperand (to);
153               IC_JTCOND (lic)->isaddr = siaddr;
154
155             }
156           continue;
157         }
158
159       if (IC_RESULT (lic) && IC_RESULT (lic)->key == from->key)
160         {
161           /* maintain du chains */
162           if (POINTER_SET (lic))
163             {
164               bitVectUnSetBit (OP_USES (from), lic->key);
165               OP_USES(to)=bitVectSetBit (OP_USES (to), lic->key);
166
167               /* also check if the "from" was in the non-dominating
168                  pointer sets and replace it with "to" in the bitVector */
169               if (bitVectBitValue (*ndpset, from->key))
170                 {
171                   bitVectUnSetBit (*ndpset, from->key);
172                   bitVectSetBit (*ndpset, to->key);
173                 }
174
175             }
176           else
177             {
178               bitVectUnSetBit (OP_DEFS (from), lic->key);
179               OP_DEFS(to)=bitVectSetBit (OP_DEFS (to), lic->key);
180             }
181           siaddr = IC_RESULT (lic)->isaddr;
182           IC_RESULT (lic) = operandFromOperand (to);
183           IC_RESULT (lic)->isaddr = siaddr;
184         }
185
186       if (IS_SYMOP (to) &&
187           IC_RIGHT (lic) && IC_RIGHT (lic)->key == from->key)
188         {
189           bitVectUnSetBit (OP_USES (from), lic->key);
190           OP_USES(to)=bitVectSetBit (OP_USES (to), lic->key);
191           siaddr = IC_RIGHT (lic)->isaddr;
192           IC_RIGHT (lic) = operandFromOperand (to);
193           IC_RIGHT (lic)->isaddr = siaddr;
194         }
195
196       if (IS_SYMOP (to) &&
197           IC_LEFT (lic) && IC_LEFT (lic)->key == from->key)
198         {
199           bitVectUnSetBit (OP_USES (from), lic->key);
200           OP_USES(to)=bitVectSetBit (OP_USES (to), lic->key);
201           siaddr = IC_LEFT (lic)->isaddr;
202           IC_LEFT (lic) = operandFromOperand (to);
203           IC_LEFT (lic)->isaddr = siaddr;
204         }
205     }
206 }
207
208 /*-----------------------------------------------------------------*/
209 /* iCodeKeyIs - if the icode keys match then return 1              */
210 /*-----------------------------------------------------------------*/
211 DEFSETFUNC (iCodeKeyIs)
212 {
213   cseDef *cdp = item;
214   V_ARG (int, key);
215
216   if (cdp->diCode->key == key)
217     return 1;
218   else
219     return 0;
220 }
221
222 /*-----------------------------------------------------------------*/
223 /* removeFromInExprs - removes an icode from inexpressions         */
224 /*-----------------------------------------------------------------*/
225 DEFSETFUNC (removeFromInExprs)
226 {
227   eBBlock *ebp = item;
228   V_ARG (iCode *, ic);
229   V_ARG (operand *, from);
230   V_ARG (operand *, to);
231   V_ARG (eBBlock *, cbp);
232
233   if (ebp->visited)
234     return 0;
235
236   ebp->visited = 1;
237   deleteItemIf (&ebp->inExprs, iCodeKeyIs, ic->key);
238   if (ebp != cbp && !bitVectBitValue (cbp->domVect, ebp->bbnum))
239     replaceAllSymBySym (ebp->sch, from, to, &ebp->ndompset);
240
241   applyToSet (ebp->succList, removeFromInExprs, ic, from, to, cbp);
242   return 0;
243 }
244
245 /*-----------------------------------------------------------------*/
246 /* isGlobalInNearSpace - return TRUE if valriable is a globalin data */
247 /*-----------------------------------------------------------------*/
248 static bool 
249 isGlobalInNearSpace (operand * op)
250 {
251   sym_link *type = getSpec (operandType (op));
252   /* this is 8051 specific: optimization
253      suggested by Jean-Louis VERN, with 8051s we have no
254      advantage of putting variables in near space into
255      registers */
256   if (isOperandGlobal (op) && !IN_FARSPACE (SPEC_OCLS (type)) &&
257       IN_DIRSPACE (SPEC_OCLS (type)))
258     return TRUE;
259   else
260     return FALSE;
261 }
262
263 /*-----------------------------------------------------------------*/
264 /* findCheaperOp - cseBBlock support routine, will check to see if */
265 /*              we have a operand previously defined               */
266 /*-----------------------------------------------------------------*/
267 DEFSETFUNC (findCheaperOp)
268 {
269   cseDef *cdp = item;
270   V_ARG (operand *, cop);
271   V_ARG (operand **, opp);
272   V_ARG (int, checkSign);
273
274   /* if we have already found it */
275   if (*opp)
276     return 1;
277
278   /* not found it yet check if this is the one */
279   /* and this is not the defining one          */
280   if (cop->key == cdp->key)
281     {
282
283       /* do a special check this will help in */
284       /* constant propagation & dead code elim */
285       /* for assignments only                 */
286       if (cdp->diCode->op == '=') {
287         /* if the result is volatile then return result */
288         if (IS_OP_VOLATILE (IC_RESULT (cdp->diCode)))
289           *opp = IC_RESULT (cdp->diCode);
290         else 
291           /* if this is a straight assignment and
292              left is a temp then prefer the temporary to the
293              true symbol */
294           if (!POINTER_SET (cdp->diCode) &&
295               IS_ITEMP (IC_RESULT (cdp->diCode)) &&
296               IS_TRUE_SYMOP (IC_RIGHT (cdp->diCode)))
297             *opp = IC_RESULT (cdp->diCode);
298           else {
299             /* if straight assignement && and both
300                are temps then prefer the one that
301                will not need extra space to spil, also
302                take into consideration if right side
303                an induction variable
304             */
305             if (!POINTER_SET (cdp->diCode) &&
306                 IS_ITEMP (IC_RESULT (cdp->diCode)) &&
307                 IS_ITEMP (IC_RIGHT (cdp->diCode)) &&
308                 !OP_SYMBOL (IC_RIGHT (cdp->diCode))->isind &&
309                 !OP_SYMBOL(IC_RIGHT (cdp->diCode))->isreqv &&
310                 ((!SPIL_LOC (IC_RIGHT (cdp->diCode)) &&
311                   SPIL_LOC (IC_RESULT (cdp->diCode))) ||
312                  (SPIL_LOC (IC_RESULT (cdp->diCode)) &&
313                   SPIL_LOC (IC_RESULT (cdp->diCode)) ==
314                   SPIL_LOC (IC_RIGHT (cdp->diCode)))))
315               *opp = IC_RESULT (cdp->diCode);
316             else
317               *opp = IC_RIGHT (cdp->diCode);
318           }
319       }
320       else
321         *opp = IC_RESULT (cdp->diCode);
322     }
323
324   /* if this is an assign to a temp. then check
325      if the right side is this then return this */
326   if (IS_TRUE_SYMOP (cop) &&
327       cdp->diCode->op == '=' &&
328       !POINTER_SET (cdp->diCode) &&
329       cop->key == IC_RIGHT (cdp->diCode)->key &&
330       !isGlobalInNearSpace (IC_RIGHT (cdp->diCode)) &&
331       IS_ITEMP (IC_RESULT (cdp->diCode)))
332     *opp = IC_RESULT (cdp->diCode);
333
334   if ((*opp) && 
335       (isOperandLiteral(*opp) || !checkSign || 
336        (checkSign &&
337         IS_SPEC(operandType (cop)) && IS_SPEC(operandType (*opp)) &&
338         (SPEC_USIGN(operandType (cop))==SPEC_USIGN(operandType (*opp)) &&
339          (SPEC_LONG(operandType (cop))==SPEC_LONG(operandType (*opp)))))))
340       {
341
342       if ((isGlobalInNearSpace (cop) &&
343            !isOperandLiteral (*opp)) ||
344           isOperandVolatile (*opp, FALSE)
345         )
346         {
347           *opp = NULL;
348           return 0;
349         }
350
351       if (cop->key == (*opp)->key)
352         {
353           *opp = NULL;
354           return 0;
355         }
356
357       if ((*opp)->isaddr != cop->isaddr && IS_ITEMP (cop))
358         {
359           *opp = operandFromOperand (*opp);
360           (*opp)->isaddr = cop->isaddr;
361         }
362           
363       if (IS_SPEC(operandType (cop)) && IS_SPEC(operandType (*opp)) &&
364           SPEC_NOUN(operandType(cop)) != SPEC_NOUN(operandType(*opp)))
365         {
366             // special case: we can make an unsigned char literal 
367             // into an int literal with no cost.
368             if (isOperandLiteral(*opp)
369              && SPEC_NOUN(operandType(*opp)) == V_CHAR
370              && SPEC_NOUN(operandType(cop)) == V_INT)
371             {
372                 *opp = operandFromOperand (*opp);
373                 SPEC_NOUN(operandType(*opp)) = V_INT;
374             }
375             else
376             {
377                 // No clue...
378                 *opp = NULL;
379                 return 0;
380             }
381             
382         }
383           
384       LRH(printf ("findCheaperOp: %s < %s\n",\
385               IS_SYMOP((*opp)) ? OP_SYMBOL((*opp))->name : "!SYM",\
386               OP_SYMBOL(cop)->name));
387       return 1;
388
389     }
390   *opp=NULL;
391   return 0;
392 }
393
394 /*-----------------------------------------------------------------*/
395 /* findPointerSet - finds the right side of a pointer set op       */
396 /*-----------------------------------------------------------------*/
397 DEFSETFUNC (findPointerSet)
398 {
399   cseDef *cdp = item;
400   V_ARG (operand *, op);
401   V_ARG (operand **, opp);
402   V_ARG (operand *, rop);
403
404   if (POINTER_SET (cdp->diCode) &&
405       IC_RESULT (cdp->diCode)->key == op->key &&
406       !isOperandVolatile (IC_RESULT (cdp->diCode), TRUE) &&
407       !isOperandVolatile (IC_RIGHT (cdp->diCode), TRUE) &&
408       getSize (operandType (IC_RIGHT (cdp->diCode))) ==
409       getSize (operandType (rop)))
410     {
411       *opp = IC_RIGHT (cdp->diCode);
412       return 1;
413     }
414
415   return 0;
416 }
417
418 /*-----------------------------------------------------------------*/
419 /* findPrevIc - cseBBlock support function will return the iCode   */
420 /*              which matches the current one                      */
421 /*-----------------------------------------------------------------*/
422 DEFSETFUNC (findPrevIc)
423 {
424   cseDef *cdp = item;
425   V_ARG (iCode *, ic);
426   V_ARG (iCode **, icp);
427
428   /* if already found */
429   if (*icp)
430     return 1;
431
432   /* if the iCodes are the same */
433   if (isiCodeEqual (ic, cdp->diCode) &&
434       isOperandEqual (cdp->sym, IC_RESULT (cdp->diCode)))
435     {
436       LRH(printf ("findPrevIc same: %d %d\n", ic->key, cdp->diCode->key));
437         *icp = cdp->diCode;
438       return 1;
439     }
440
441   /* if iCodes are not the same */
442   /* see the operands maybe interchanged */
443   if (ic->op == cdp->diCode->op &&
444       (ic->op == '+' || ic->op == '*') &&
445       isOperandEqual (IC_LEFT (ic), IC_RIGHT (cdp->diCode)) &&
446       isOperandEqual (IC_RIGHT (ic), IC_LEFT (cdp->diCode)))
447     {
448       LRH(printf ("findPrevIc inter: %d %d\n", ic->key, cdp->diCode->key));
449       *icp = cdp->diCode;
450       return 1;
451     }
452
453   return 0;
454 }
455
456 /*-------------------------------------------------------------------*/
457 /* ifAssignedFromGlobal - if definition is an assignment from global */
458 /*-------------------------------------------------------------------*/
459 DEFSETFUNC (ifAssignedFromGlobal)
460 {
461   cseDef *cdp = item;
462   iCode *dic=cdp->diCode;
463
464   if (dic->op=='=' && isOperandGlobal(IC_RIGHT(dic))) {
465     return 1;
466   }
467   return 0;
468 }
469
470 /*-----------------------------------------------------------------*/
471 /* ifDefGlobal - if definition is global                           */
472 /*-----------------------------------------------------------------*/
473 DEFSETFUNC (ifDefGlobal)
474 {
475   cseDef *cdp = item;
476
477   return (isOperandGlobal (cdp->sym));
478 }
479
480 /*-----------------------------------------------------------------*/
481 /* ifAnyGetPointer - if get pointer icode                          */
482 /*-----------------------------------------------------------------*/
483 DEFSETFUNC (ifAnyGetPointer)
484 {
485   cseDef *cdp = item;
486
487   if (cdp->diCode && POINTER_GET (cdp->diCode))
488     return 1;
489   return 0;
490 }
491
492 /*-----------------------------------------------------------------*/
493 /* ifOperandsHave - if any of the operand are the same as this     */
494 /*-----------------------------------------------------------------*/
495 DEFSETFUNC (ifOperandsHave)
496 {
497   cseDef *cdp = item;
498   V_ARG (operand *, op);
499
500
501   if (IC_LEFT (cdp->diCode) &&
502       IS_SYMOP (IC_LEFT (cdp->diCode)) &&
503       IC_LEFT (cdp->diCode)->key == op->key)
504     return 1;
505
506   if (IC_RIGHT (cdp->diCode) &&
507       IS_SYMOP (IC_RIGHT (cdp->diCode)) &&
508       IC_RIGHT (cdp->diCode)->key == op->key)
509     return 1;
510
511   /* or if any of the operands are volatile */
512   if (IC_LEFT (cdp->diCode) &&
513       IS_OP_VOLATILE (IC_LEFT (cdp->diCode)))
514     return 1;
515
516   if (IC_RIGHT (cdp->diCode) &&
517       IS_OP_VOLATILE (IC_RIGHT (cdp->diCode)))
518     return 1;
519
520
521   if (IC_RESULT (cdp->diCode) &&
522       IS_OP_VOLATILE (IC_RESULT (cdp->diCode)))
523     return 1;
524
525   return 0;
526 }
527
528 /*-----------------------------------------------------------------*/
529 /* ifDefSymIs - if a definition is found in the set                */
530 /*-----------------------------------------------------------------*/
531 int 
532 ifDefSymIs (set * cseSet, operand * sym)
533 {
534   cseDef *loop;
535   set *sl;
536
537   if (!sym || !IS_SYMOP (sym))
538     return 0;
539   for (sl = cseSet; sl; sl = sl->next)
540     {
541       loop = sl->item;
542       if (loop->sym->key == sym->key)
543         return 1;
544     }
545   return 0;
546 }
547
548
549 /*-----------------------------------------------------------------*/
550 /* ifDefSymIsX - will return 1 if the symbols match                */
551 /*-----------------------------------------------------------------*/
552 DEFSETFUNC (ifDefSymIsX)
553 {
554   cseDef *cdp = item;
555   V_ARG (operand *, op);
556
557   if (op && cdp->sym)
558     return cdp->sym->key == op->key;
559   else
560     return (isOperandEqual (cdp->sym, op));
561
562 }
563
564
565 /*-----------------------------------------------------------------*/
566 /* ifDiCodeIs - returns truw if diCode is same                     */
567 /*-----------------------------------------------------------------*/
568 int 
569 ifDiCodeIs (set * cseSet, iCode * ic)
570 {
571   cseDef *loop;
572   set *sl;
573
574   if (!ic)
575     return 0;
576
577   for (sl = cseSet; sl; sl = sl->next)
578     {
579       loop = sl->item;
580       if (loop->diCode == ic)
581         return 1;
582     }
583   return 0;
584
585 }
586
587 /*-----------------------------------------------------------------*/
588 /* ifPointerGet - returns true if the icode is pointer get sym     */
589 /*-----------------------------------------------------------------*/
590 DEFSETFUNC (ifPointerGet)
591 {
592   cseDef *cdp = item;
593   V_ARG (operand *, op);
594   iCode *dic = cdp->diCode;
595   operand *left = IC_LEFT (cdp->diCode);
596
597   if (POINTER_GET (dic) && left->key == op->key)
598     return 1;
599
600   return 0;
601 }
602
603 /*-----------------------------------------------------------------*/
604 /* ifPointerSet - returns true if the icode is pointer set sym     */
605 /*-----------------------------------------------------------------*/
606 DEFSETFUNC (ifPointerSet)
607 {
608   cseDef *cdp = item;
609   V_ARG (operand *, op);
610
611   if (POINTER_SET (cdp->diCode) &&
612       IC_RESULT (cdp->diCode)->key == op->key)
613     return 1;
614
615   return 0;
616 }
617
618 /*-----------------------------------------------------------------*/
619 /* ifDiCodeIsX - will return 1 if the symbols match                 */
620 /*-----------------------------------------------------------------*/
621 DEFSETFUNC (ifDiCodeIsX)
622 {
623   cseDef *cdp = item;
624   V_ARG (iCode *, ic);
625
626   return cdp->diCode == ic;
627
628 }
629
630 /*-----------------------------------------------------------------*/
631 /* findBackwardDef - scan backwards to find deinition of operand   */
632 /*-----------------------------------------------------------------*/
633 iCode *findBackwardDef(operand *op,iCode *ic)
634 {
635     iCode *lic;
636
637     for (lic = ic; lic ; lic = lic->prev) {
638         if (IC_RESULT(lic) && isOperandEqual(op,IC_RESULT(lic))) 
639             return lic;
640     }
641     return NULL;
642 }
643
644 /*-----------------------------------------------------------------*/
645 /* algebraicOpts - does some algebraic optimizations               */
646 /*-----------------------------------------------------------------*/
647 void 
648 algebraicOpts (iCode * ic)
649 {
650   /* we don't deal with the following iCodes
651      here */
652   if (ic->op == IFX ||
653       ic->op == IPUSH ||
654       ic->op == IPOP ||
655       ic->op == CALL ||
656       ic->op == PCALL ||
657       ic->op == RETURN ||
658       POINTER_GET (ic))
659     return;
660
661   /* if both operands present & ! IFX */
662   /* then if they are both literal we */
663   /* perform the operation right now  */
664   if (IC_RESULT (ic) &&
665       IC_RIGHT (ic) &&
666       IC_LEFT (ic) &&
667       IS_OP_LITERAL (IC_LEFT (ic)) &&
668       IS_OP_LITERAL (IC_RIGHT (ic)))
669     {
670
671       IC_RIGHT (ic) = operandOperation (IC_LEFT (ic),
672                                         IC_RIGHT (ic),
673                                         ic->op,
674                                         operandType (IC_RESULT (ic)));
675       ic->op = '=';
676       IC_LEFT (ic) = NULL;
677       SET_RESULT_RIGHT (ic);
678       return;
679
680     }
681   /* if not ifx & only one operand present */
682   if (IC_RESULT (ic) &&
683       IC_LEFT (ic) &&
684       IS_OP_LITERAL (IC_LEFT (ic)) &&
685       !IC_RIGHT (ic))
686     {
687
688       IC_RIGHT (ic) = operandOperation (IC_LEFT (ic),
689                                         IC_RIGHT (ic),
690                                         ic->op,
691                                         operandType (IC_RESULT (ic)));
692       ic->op = '=';
693       IC_LEFT (ic) = NULL;
694       SET_RESULT_RIGHT (ic);
695       return;
696     }
697
698
699   /* a special case : or in short a kludgy solution will think
700      about a better solution over a glass of wine someday */
701   if (ic->op == GET_VALUE_AT_ADDRESS)
702     {
703
704       if (IS_ITEMP (IC_RESULT (ic)) &&
705           IS_TRUE_SYMOP (IC_LEFT (ic)))
706         {
707
708           ic->op = '=';
709           IC_RIGHT (ic) = operandFromOperand (IC_LEFT (ic));
710           IC_RIGHT (ic)->isaddr = 0;
711           IC_LEFT (ic) = NULL;
712           IC_RESULT (ic) = operandFromOperand (IC_RESULT (ic));
713           IC_RESULT (ic)->isaddr = 0;
714           setOperandType (IC_RESULT (ic), operandType (IC_RIGHT (ic)));
715           return;
716         }
717
718       if (IS_ITEMP (IC_LEFT (ic)) &&
719           IS_ITEMP (IC_RESULT (ic)) &&
720 /*      !OP_SYMBOL(IC_RESULT(ic))->isreqv && */
721 /*      !OP_SYMBOL(IC_LEFT(ic))->isreqv && */
722           !IC_LEFT (ic)->isaddr)
723         {
724           ic->op = '=';
725           IC_RIGHT (ic) = operandFromOperand (IC_LEFT (ic));
726           IC_RIGHT (ic)->isaddr = 0;
727           IC_RESULT (ic) = operandFromOperand (IC_RESULT (ic));
728           IC_RESULT (ic)->isaddr = 0;
729           IC_LEFT (ic) = NULL;
730           return;
731         }
732
733     }
734
735
736   /* depending on the operation */
737   switch (ic->op)
738     {
739     case '+':
740       /* if adding the same thing change to left shift by 1 */
741       if (IC_LEFT (ic)->key == IC_RIGHT (ic)->key &&
742           !IS_FLOAT (operandType (IC_RESULT (ic))))
743         {
744           ic->op = LEFT_OP;
745           IC_RIGHT (ic) = operandFromLit (1);
746           return;
747         }
748       /* if addition then check if one of them is a zero */
749       /* if yes turn it  into assignmnt */
750       if (IS_OP_LITERAL (IC_LEFT (ic)) &&
751           operandLitValue (IC_LEFT (ic)) == 0.0)
752         {
753
754           ic->op = '=';
755           IC_LEFT (ic) = NULL;
756           SET_ISADDR (IC_RESULT (ic), 0);
757           SET_ISADDR (IC_RIGHT (ic), 0);
758           return;
759         }
760       if (IS_OP_LITERAL (IC_RIGHT (ic)) &&
761           operandLitValue (IC_RIGHT (ic)) == 0.0)
762         {
763
764           ic->op = '=';
765           IC_RIGHT (ic) = IC_LEFT (ic);
766           IC_LEFT (ic) = 0;
767           SET_ISADDR (IC_RIGHT (ic), 0);
768           SET_ISADDR (IC_RESULT (ic), 0);
769           return;
770         }
771       break;
772     case '-':
773       /* if subtracting the the same thing then zero     */
774       if (IC_LEFT (ic)->key == IC_RIGHT (ic)->key)
775         {
776           ic->op = '=';
777           IC_RIGHT (ic) = operandFromLit (0);
778           IC_LEFT (ic) = NULL;
779           IC_RESULT (ic) = operandFromOperand (IC_RESULT (ic));
780           IC_RESULT (ic)->isaddr = 0;
781           return;
782         }
783
784       /* if subtraction then check if one of the operand */
785       /* is zero then depending on which operand change  */
786       /* to assignment or unary minus                    */
787       if (IS_OP_LITERAL (IC_RIGHT (ic)) &&
788           operandLitValue (IC_RIGHT (ic)) == 0.0)
789         {
790           /* right size zero change to assignment */
791           ic->op = '=';
792           IC_RIGHT (ic) = IC_LEFT (ic);
793           IC_LEFT (ic) = NULL;
794           SET_ISADDR (IC_RIGHT (ic), 0);
795           SET_ISADDR (IC_RESULT (ic), 0);
796           return;
797         }
798       if (IS_OP_LITERAL (IC_LEFT (ic)) &&
799           operandLitValue (IC_LEFT (ic)) == 0.0)
800         {
801           /* left zero turn into an unary minus */
802           ic->op = UNARYMINUS;
803           IC_LEFT (ic) = IC_RIGHT (ic);
804           IC_RIGHT (ic) = NULL;
805           return;
806         }
807       break;
808       /* if multiplication then check if either of */
809       /* them is zero then the result is zero      */
810       /* if either of them is one then result is   */
811       /* the other one                             */
812     case '*':
813       if (IS_OP_LITERAL (IC_LEFT (ic)))
814         {
815
816           if (operandLitValue (IC_LEFT (ic)) == 0.0)
817             {
818               ic->op = '=';
819               IC_RIGHT (ic) = IC_LEFT (ic);
820               IC_LEFT (ic) = NULL;
821               SET_RESULT_RIGHT (ic);
822               return;
823             }
824           if (operandLitValue (IC_LEFT (ic)) == 1.0)
825             {
826               ic->op = '=';
827               IC_LEFT (ic) = NULL;
828               SET_RESULT_RIGHT (ic);
829               return;
830             }
831         }
832
833       if (IS_OP_LITERAL (IC_RIGHT (ic)))
834         {
835
836           if (operandLitValue (IC_RIGHT (ic)) == 0.0)
837             {
838               ic->op = '=';
839               IC_LEFT (ic) = NULL;
840               SET_RESULT_RIGHT (ic);
841               return;
842             }
843
844           if (operandLitValue (IC_RIGHT (ic)) == 1.0)
845             {
846               ic->op = '=';
847               IC_RIGHT (ic) = IC_LEFT (ic);
848               IC_LEFT (ic) = NULL;
849               SET_RESULT_RIGHT (ic);
850               return;
851             }
852         }
853       break;
854     case '/':
855       /* if division by self then 1 */
856       if (IC_LEFT (ic)->key == IC_RIGHT (ic)->key)
857         {
858           ic->op = '=';
859           IC_RIGHT (ic) = operandFromLit (1);
860           IC_LEFT (ic) = NULL;
861           IC_RESULT (ic) = operandFromOperand (IC_RESULT (ic));
862           IC_RESULT (ic)->isaddr = 0;
863           break;
864         }
865       /* if this is a division then check if right */
866       /* is one then change it to an assignment    */
867       if (IS_OP_LITERAL (IC_RIGHT (ic)) &&
868           operandLitValue (IC_RIGHT (ic)) == 1.0)
869         {
870
871           ic->op = '=';
872           IC_RIGHT (ic) = IC_LEFT (ic);
873           IC_LEFT (ic) = NULL;
874           SET_RESULT_RIGHT (ic);
875           return;
876         }
877       break;
878       /* if both are the same for an comparison operators */
879     case EQ_OP:
880     case LE_OP:
881     case GE_OP:
882       if (isOperandEqual (IC_LEFT (ic), IC_RIGHT (ic)))
883         {
884           ic->op = '=';
885           IC_RIGHT (ic) = operandFromLit (1);
886           IC_LEFT (ic) = NULL;
887           SET_RESULT_RIGHT (ic);
888         }
889       break;
890     case NE_OP:
891     case '>':
892     case '<':
893       if (isOperandEqual (IC_LEFT (ic), IC_RIGHT (ic)))
894         {
895           ic->op = '=';
896           IC_RIGHT (ic) = operandFromLit (0);
897           IC_LEFT (ic) = NULL;
898           SET_RESULT_RIGHT (ic);
899         }
900       break;
901     case CAST:
902             {
903                     sym_link *otype = operandType(IC_RIGHT(ic));
904                     sym_link *ctype = operandType(IC_LEFT(ic));
905                     /* if this is a cast of a literal value */
906                     if (IS_OP_LITERAL (IC_RIGHT (ic)) &&
907                         !(IS_GENPTR(ctype) && (IS_PTR(otype) && !IS_GENPTR(otype)))) {
908                             ic->op = '=';
909                             IC_RIGHT (ic) =
910                                     operandFromValue (valCastLiteral (operandType (IC_LEFT (ic)),
911                                                                       operandLitValue (IC_RIGHT (ic))));
912                             IC_LEFT (ic) = NULL;
913                             SET_ISADDR (IC_RESULT (ic), 0);
914                     }
915                     /* if casting to the same */
916                     if (compareType (operandType (IC_RESULT (ic)),
917                                      operandType (IC_RIGHT (ic))) == 1) {
918                             ic->op = '=';
919                             IC_LEFT (ic) = NULL;
920                             SET_ISADDR (IC_RESULT (ic), 0);
921                     }
922             }
923             break;
924     case '!':
925       if (IS_OP_LITERAL (IC_LEFT (ic)))
926         {
927           ic->op = '=';
928           IC_RIGHT (ic) =
929             (operandLitValue (IC_LEFT (ic)) == 0 ?
930              operandFromLit (1) : operandFromLit (0));
931           IC_LEFT (ic) = NULL;
932           SET_ISADDR (IC_RESULT (ic), 0);
933         }
934     }
935
936   return;
937 }
938 #define OTHERS_PARM(s) (s->_isparm && !s->ismyparm)
939 /*-----------------------------------------------------------------*/
940 /* updateSpillLocation - keeps track of register spill location    */
941 /*-----------------------------------------------------------------*/
942 void 
943 updateSpillLocation (iCode * ic, int induction)
944 {
945         sym_link *setype;
946
947         if (POINTER_SET (ic))
948                 return;
949
950         if (ic->nosupdate)
951                 return;
952
953         /* for the form true_symbol := iTempNN */
954         if (ASSIGN_ITEMP_TO_SYM (ic) && 
955             !SPIL_LOC (IC_RIGHT (ic))) {
956
957                 setype = getSpec (operandType (IC_RESULT (ic)));
958
959                 if (!OP_SYMBOL(IC_RIGHT (ic))->noSpilLoc &&
960                     !IS_VOLATILE (setype) &&
961                     !IN_FARSPACE (SPEC_OCLS (setype)) &&
962                     !OTHERS_PARM (OP_SYMBOL (IC_RESULT (ic))))
963                 {
964                     wassert(IS_SYMOP(IC_RESULT (ic)));
965                     wassert(IS_SYMOP(IC_RIGHT (ic)));
966                         SPIL_LOC (IC_RIGHT (ic)) =
967                                 IC_RESULT (ic)->operand.symOperand;
968                 }
969             
970         }
971
972 #if 0 /* this needs furthur investigation can save a lot of code */
973         if (ASSIGN_SYM_TO_ITEMP(ic) &&
974             !SPIL_LOC(IC_RESULT(ic))) {
975             if (!OTHERS_PARM (OP_SYMBOL (IC_RIGHT (ic))))
976                 SPIL_LOC (IC_RESULT (ic)) =
977                     IC_RIGHT (ic)->operand.symOperand;
978         }
979 #endif
980         if (ASSIGN_ITEMP_TO_ITEMP (ic)) {
981           
982                 if (!SPIL_LOC (IC_RIGHT (ic)) &&
983                     !bitVectBitsInCommon (OP_DEFS (IC_RIGHT (ic)), OP_USES (IC_RESULT (ic))) &&
984                     OP_SYMBOL (IC_RESULT (ic))->isreqv) {
985
986                         setype = getSpec (operandType (IC_RESULT (ic)));
987               
988                         if (!OP_SYMBOL(IC_RIGHT (ic))->noSpilLoc &&
989                             !IS_VOLATILE (setype) &&
990                             !IN_FARSPACE (SPEC_OCLS (setype)) &&
991                             !OTHERS_PARM (OP_SYMBOL (IC_RESULT (ic))))
992
993                                 SPIL_LOC (IC_RIGHT (ic)) =
994                                         SPIL_LOC (IC_RESULT (ic));
995                 }
996                 /* special case for inductions */
997                 if (induction && 
998                     OP_SYMBOL(IC_RIGHT(ic))->isreqv && 
999                     !OP_SYMBOL(IC_RESULT (ic))->noSpilLoc &&
1000                     !SPIL_LOC(IC_RESULT(ic))) {
1001                         SPIL_LOC (IC_RESULT (ic)) = SPIL_LOC (IC_RIGHT (ic));
1002                 }
1003         }
1004 }
1005 /*-----------------------------------------------------------------*/
1006 /* setUsesDef - sets the uses def bitvector for a given operand    */
1007 /*-----------------------------------------------------------------*/
1008 void 
1009 setUsesDefs (operand * op, bitVect * bdefs,
1010              bitVect * idefs, bitVect ** oud)
1011 {
1012   /* compute the definitions alive at this point */
1013   bitVect *adefs = bitVectUnion (bdefs, idefs);
1014
1015   /* of these definitions find the ones that are */
1016   /* for this operand */
1017   adefs = bitVectIntersect (adefs, OP_DEFS (op));
1018
1019   /* these are the definitions that this operand can use */
1020   op->usesDefs = adefs;
1021
1022   /* the out defs is an union */
1023   *oud = bitVectUnion (*oud, adefs);
1024 }
1025
1026 /*-----------------------------------------------------------------*/
1027 /* unsetDefsAndUses - clear this operation for the operands        */
1028 /*-----------------------------------------------------------------*/
1029 void 
1030 unsetDefsAndUses (iCode * ic)
1031 {
1032   if (ic->op == JUMPTABLE)
1033     return;
1034
1035   /* take away this definition from the def chain of the */
1036   /* result & take away from use set of the operands */
1037   if (ic->op != IFX)
1038     {
1039       /* turn off def set */
1040       if (IS_SYMOP (IC_RESULT (ic)))
1041         {
1042           if (!POINTER_SET (ic))
1043             bitVectUnSetBit (OP_DEFS (IC_RESULT (ic)), ic->key);
1044           else
1045             bitVectUnSetBit (OP_USES (IC_RESULT (ic)), ic->key);
1046         }
1047       /* turn off the useSet for the operands */
1048       if (IS_SYMOP (IC_LEFT (ic)))
1049         bitVectUnSetBit (OP_USES (IC_LEFT (ic)), ic->key);
1050
1051       if (IS_SYMOP (IC_RIGHT (ic)))
1052         bitVectUnSetBit (OP_USES (IC_RIGHT (ic)), ic->key);
1053     }
1054   else
1055     /* must be ifx turn off the use */ if (IS_SYMOP (IC_COND (ic)))
1056     bitVectUnSetBit (OP_USES (IC_COND (ic)), ic->key);
1057 }
1058
1059 /*-----------------------------------------------------------------*/
1060 /* ifxOptimize - changes ifx conditions if it can                  */
1061 /*-----------------------------------------------------------------*/
1062 void 
1063 ifxOptimize (iCode * ic, set * cseSet,
1064              int computeOnly,
1065              eBBlock * ebb, int *change,
1066              eBBlock ** ebbs, int count)
1067 {
1068   operand *pdop;
1069   symbol *label;
1070
1071   /* if the condition can be replaced */
1072   if (!computeOnly)
1073     {
1074       pdop = NULL;
1075       applyToSetFTrue (cseSet, findCheaperOp, IC_COND (ic), &pdop, 0);
1076       if (pdop)
1077         {
1078           ReplaceOpWithCheaperOp(&IC_COND (ic), pdop);
1079           (*change)++;
1080         }
1081     }
1082
1083   /* if the conditional is a literal then */
1084   if (IS_OP_LITERAL (IC_COND (ic)))
1085     {
1086
1087       if ((operandLitValue (IC_COND (ic)) != 0.0) && IC_TRUE (ic))
1088         {
1089
1090           /* change to a goto */
1091           ic->op = GOTO;
1092           IC_LABEL (ic) = IC_TRUE (ic);
1093           (*change)++;
1094
1095         }
1096       else
1097         {
1098
1099           if (!operandLitValue (IC_COND (ic)) && IC_FALSE (ic))
1100             {
1101               ic->op = GOTO;
1102               IC_LABEL (ic) = IC_FALSE (ic);
1103               (*change)++;
1104
1105             }
1106           else
1107             {
1108               /* then kill this if condition */
1109               remiCodeFromeBBlock (ebb, ic);
1110             }
1111         }
1112
1113       /* now we need to recompute the control flow */
1114       /* since the control flow has changed        */
1115       /* this is very expensive but it does not happen */
1116       /* too often, if it does happen then the user pays */
1117       /* the price */
1118       computeControlFlow (ebbs, count, 1);
1119       if (!options.lessPedantic) {
1120         werror (W_CONTROL_FLOW, ic->filename, ic->lineno);
1121       }
1122       return;
1123     }
1124
1125   /* if there is only one successor and that successor
1126      is the same one we are conditionally going to then
1127      we can remove this conditional statement */
1128   label = (IC_TRUE (ic) ? IC_TRUE (ic) : IC_FALSE (ic));
1129   if (elementsInSet (ebb->succList) == 1 &&
1130       isinSet (ebb->succList, eBBWithEntryLabel (ebbs, label, count)))
1131     {
1132
1133       remiCodeFromeBBlock (ebb, ic);
1134       computeControlFlow (ebbs, count, 1);
1135       if (!options.lessPedantic) {
1136         werror (W_CONTROL_FLOW, ic->filename, ic->lineno);
1137       }
1138       return;
1139     }
1140
1141
1142   /* if it remains an IFX the update the use Set */
1143   OP_USES(IC_COND (ic))=bitVectSetBit (OP_USES (IC_COND (ic)), ic->key);
1144   setUsesDefs (IC_COND (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs);
1145   return;
1146 }
1147
1148 /*-----------------------------------------------------------------*/
1149 /* diCodeForSym - finds the definiting instruction for a symbol    */
1150 /*-----------------------------------------------------------------*/
1151 DEFSETFUNC (diCodeForSym)
1152 {
1153   cseDef *cdp = item;
1154   V_ARG (operand *, sym);
1155   V_ARG (iCode **, dic);
1156
1157   /* if already found */
1158   if (*dic)
1159     return 0;
1160
1161   /* if not if this is the defining iCode */
1162   if (sym->key == cdp->key)
1163     {
1164       *dic = cdp->diCode;
1165       return 1;
1166     }
1167
1168   return 0;
1169 }
1170
1171 /*-----------------------------------------------------------------*/
1172 /* constFold - does some constant folding                          */
1173 /*-----------------------------------------------------------------*/
1174 int 
1175 constFold (iCode * ic, set * cseSet)
1176 {
1177   iCode *dic = NULL;
1178   iCode *ldic = NULL;
1179   /* this routine will change
1180      a = b + 10;
1181      c = a + 10;
1182      to
1183      c = b + 20; */
1184
1185   /* deal with only + & - */
1186   if (ic->op != '+' &&
1187       ic->op != '-')
1188     return 0;
1189
1190   /* this check is a hueristic to prevent live ranges
1191      from becoming too long */
1192   if (IS_PTR (operandType (IC_RESULT (ic))))
1193       return 0;
1194
1195   /* check if operation with a literal */
1196   if (!IS_OP_LITERAL (IC_RIGHT (ic)))
1197     return 0;
1198
1199   /* check if we can find a definition for the
1200      right hand side */
1201   if (!(applyToSet (cseSet, diCodeForSym, IC_LEFT (ic), &dic)))
1202     return 0;
1203
1204   /* check that this is also a +/-  */
1205   if (dic->op != '+' && dic->op != '-')
1206     return 0;
1207
1208   /* with a literal */
1209   if (!IS_OP_LITERAL (IC_RIGHT (dic)))
1210     return 0;
1211
1212   /* find the definition of the left operand
1213      of dic.then check if this defined with a
1214      get_pointer return 0 if the pointer size is
1215      less than 2 (MCS51 specific) */
1216   if (!(applyToSet (cseSet, diCodeForSym, IC_LEFT (dic), &ldic)))
1217     return 0;
1218
1219   if (POINTER_GET (ldic) && getSize (operandType (IC_LEFT (ldic))) <= 1)
1220     return 0;
1221
1222   /* it is if the operations are the same */
1223   /* the literal parts need to be added  */
1224   IC_LEFT (ic) = operandFromOperand (IC_LEFT (dic));
1225   if (ic->op == dic->op)
1226     IC_RIGHT (ic) = operandFromLit (operandLitValue (IC_RIGHT (ic)) +
1227                                     operandLitValue (IC_RIGHT (dic)));
1228   else
1229     IC_RIGHT (ic) = operandFromLit (operandLitValue (IC_RIGHT (ic)) -
1230                                     operandLitValue (IC_RIGHT (dic)));
1231
1232   if (IS_ITEMP (IC_RESULT (ic)))
1233     {
1234       SPIL_LOC (IC_RESULT (ic)) = NULL;
1235       OP_SYMBOL(IC_RESULT (ic))->noSpilLoc = 1;
1236     }
1237
1238
1239   return 1;
1240 }
1241
1242 /*-----------------------------------------------------------------*/
1243 /* deleteGetPointers - called when a pointer is passed as parm     */
1244 /* will delete from cseSet all get pointers computed from this     */
1245 /* pointer. A simple ifOperandsHave is not good enough here        */
1246 /*-----------------------------------------------------------------*/
1247 static void 
1248 deleteGetPointers (set ** cseSet, set ** pss, operand * op, eBBlock * ebb)
1249 {
1250   set *compItems = NULL;
1251   cseDef *cdp;
1252   operand *cop;
1253
1254   /* easy return */
1255   if (!*cseSet && !*pss)
1256     return;
1257
1258   /* first find all items computed from this operand .
1259      This done fairly simply go thru the list and find
1260      those that are computed by arthimetic with this
1261      op */
1262   for (cdp = setFirstItem (*cseSet); cdp; cdp = setNextItem (*cseSet))
1263     {
1264       if (IS_ARITHMETIC_OP (cdp->diCode))
1265         {
1266           if (isOperandEqual (IC_LEFT (cdp->diCode), op) ||
1267               isOperandEqual (IC_RIGHT (cdp->diCode), op))
1268             {
1269               /* save it in our list of items */
1270               addSet (&compItems, IC_RESULT (cdp->diCode));
1271             }
1272           /* also check for those computed from our computed
1273              list . This will take care of situations like
1274              iTemp1 = iTemp0 + 8;
1275              iTemp2 = iTemp1 + 8; */
1276           if (isinSetWith (compItems, (void*)IC_LEFT (cdp->diCode), 
1277                            (insetwithFunc)isOperandEqual) ||
1278               isinSetWith (compItems, (void*)IC_RIGHT (cdp->diCode), 
1279                            (insetwithFunc)isOperandEqual))
1280             {
1281               addSet (&compItems, IC_RESULT (cdp->diCode));
1282             }
1283         }
1284     }
1285
1286   /* now delete all pointer gets with this op */
1287   deleteItemIf (cseSet, ifPointerGet, op);
1288   deleteItemIf (pss, ifPointerSet, op);
1289
1290   /* set the bit vector used by dataFlow computation later */
1291   ebb->ptrsSet = bitVectSetBit (ebb->ptrsSet, op->key);
1292   /* now for the computed items */
1293   for (cop = setFirstItem (compItems); cop; cop = setNextItem (compItems))
1294     {
1295       ebb->ptrsSet = bitVectSetBit (ebb->ptrsSet, cop->key);
1296       deleteItemIf (cseSet, ifPointerGet, cop);
1297       deleteItemIf (pss, ifPointerSet, cop);
1298     }
1299 }
1300
1301 /*-----------------------------------------------------------------*/
1302 /* delGetPointerSucc - delete get pointer from inExprs of succ with */
1303 /*                     dfnum > supplied                            */
1304 /*-----------------------------------------------------------------*/
1305 DEFSETFUNC (delGetPointerSucc)
1306 {
1307   eBBlock *ebp = item;
1308   V_ARG (operand *, op);
1309   V_ARG (int, dfnum);
1310
1311   if (ebp->visited)
1312     return 0;
1313
1314   ebp->visited = 1;
1315   if (ebp->dfnum > dfnum)
1316     {
1317       deleteItemIf (&ebp->inExprs, ifPointerGet, op);
1318     }
1319
1320   return applyToSet (ebp->succList, delGetPointerSucc, op, dfnum);
1321 }
1322
1323 /*-----------------------------------------------------------------*/
1324 /* fixUpTypes - KLUGE HACK fixup a lowering problem                */
1325 /*-----------------------------------------------------------------*/
1326 static void 
1327 fixUpTypes (iCode * ic)
1328 {
1329   sym_link *t1 = operandType (IC_LEFT (ic)), *t2;
1330
1331   /* if (TARGET_IS_DS390) */
1332   if (options.model == MODEL_FLAT24)
1333     {
1334       /* hack-o-matic! */
1335       return;
1336     }
1337
1338   /* for pointer_gets if the types of result & left r the
1339      same then change it type of result to next */
1340   if (IS_PTR (t1) &&
1341       compareType (t2 = operandType (IC_RESULT (ic)), t1) == 1)
1342     {
1343       setOperandType (IC_RESULT (ic), t2->next);
1344     }
1345 }
1346
1347 /*-----------------------------------------------------------------*/
1348 /* isSignedOp - will return 1 if sign is important to operation    */
1349 /*-----------------------------------------------------------------*/
1350 static int isSignedOp (iCode *ic)
1351 {
1352     switch (ic->op) {
1353     case '!':
1354     case '~':
1355     case UNARYMINUS:
1356     case IPUSH:
1357     case IPOP:
1358     case CALL:
1359     case PCALL:
1360     case RETURN:
1361     case '+':
1362     case '-':
1363     case EQ_OP:
1364     case AND_OP:
1365     case OR_OP:
1366     case '^':
1367     case '|':
1368     case BITWISEAND:
1369     case INLINEASM:
1370     case LEFT_OP:
1371     case GET_VALUE_AT_ADDRESS:
1372     case '=':
1373     case IFX:
1374     case RECEIVE:
1375     case SEND:
1376         return 0;
1377     case '*':
1378     case '/':
1379     case '%':
1380     case '>':
1381     case '<':
1382     case LE_OP:
1383     case GE_OP:
1384     case NE_OP:
1385     case RRC:
1386     case RLC:
1387     case GETHBIT:
1388     case RIGHT_OP:
1389     case CAST:
1390     case ARRAYINIT:
1391         return 1;
1392     default:
1393         return 0;
1394     }
1395  }
1396
1397 /*-----------------------------------------------------------------*/
1398 /* cseBBlock - common subexpression elimination for basic blocks   */
1399 /*             this is the hackiest kludgiest routine in the whole */
1400 /*             system. also the most important, since almost all   */
1401 /*             data flow related information is computed by it     */
1402 /*-----------------------------------------------------------------*/
1403 int 
1404 cseBBlock (eBBlock * ebb, int computeOnly,
1405            eBBlock ** ebbs, int count)
1406 {
1407   set *cseSet;
1408   iCode *ic;
1409   int change = 0;
1410   int i;
1411   set *ptrSetSet = NULL;
1412
1413   /* if this block is not reachable */
1414   if (ebb->noPath)
1415     return change;
1416
1417   /* set of common subexpressions */
1418   cseSet = setFromSet (ebb->inExprs);
1419
1420   /* these will be computed by this routine */
1421   setToNull ((void **) &ebb->outDefs);
1422   setToNull ((void **) &ebb->defSet);
1423   setToNull ((void **) &ebb->usesDefs);
1424   setToNull ((void **) &ebb->ptrsSet);
1425   setToNull ((void **) &ebb->addrOf);
1426   setToNull ((void **) &ebb->ldefs);
1427
1428   ebb->outDefs = bitVectCopy (ebb->inDefs);
1429   bitVectDefault = iCodeKey;
1430   ebb->defSet = newBitVect (iCodeKey);
1431   ebb->usesDefs = newBitVect (iCodeKey);
1432
1433   /* for all the instructions in this block do */
1434   for (ic = ebb->sch; ic; ic = ic->next)
1435     {
1436       iCode *pdic;
1437       operand *pdop;
1438       iCode *defic;
1439       int checkSign ;
1440
1441       ic->eBBlockNum = ebb->bbnum;
1442
1443       if (SKIP_IC2 (ic))
1444         continue;
1445
1446       /* if this is an assignment from true symbol
1447          to a temp then do pointer post inc/dec optimzation */
1448       if (ic->op == '=' && !POINTER_SET (ic) &&
1449           IS_PTR (operandType (IC_RESULT (ic))))
1450         {
1451           ptrPostIncDecOpt (ic);
1452         }
1453
1454       /* clear the def & use chains for the operands involved */
1455       /* in this operation . since it can change due to opts  */
1456       unsetDefsAndUses (ic);
1457
1458       if (ic->op == PCALL || ic->op == CALL || ic->op == RECEIVE)
1459         {
1460           /* add to defSet of the symbol */
1461           OP_DEFS(IC_RESULT (ic))=
1462             bitVectSetBit (OP_DEFS (IC_RESULT (ic)), ic->key);
1463           /* add to the definition set of this block */
1464           ebb->defSet = bitVectSetBit (ebb->defSet, ic->key);
1465           ebb->ldefs = bitVectSetBit (ebb->ldefs, ic->key);
1466           ebb->outDefs = bitVectCplAnd (ebb->outDefs, OP_DEFS (IC_RESULT (ic)));
1467           setUsesDefs (IC_RESULT (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs);
1468           /* delete global variables from the cseSet
1469              since they can be modified by the function call */
1470           deleteItemIf (&cseSet, ifDefGlobal);
1471
1472           /* and also itemps assigned from globals */
1473           deleteItemIf (&cseSet, ifAssignedFromGlobal);
1474
1475           /* delete all getpointer iCodes from cseSet, this should
1476              be done only for global arrays & pointers but at this
1477              point we don't know if globals, so to be safe do all */
1478           deleteItemIf (&cseSet, ifAnyGetPointer);
1479         }
1480
1481       /* for pcall & ipush we need to add to the useSet */
1482       if ((ic->op == PCALL ||
1483            ic->op == IPUSH ||
1484            ic->op == IPOP ||
1485            ic->op == SEND) &&
1486           IS_SYMOP (IC_LEFT (ic)))
1487         {
1488
1489           /* check if they can be replaced */
1490           if (!computeOnly)
1491             {
1492               pdop = NULL;
1493               applyToSetFTrue (cseSet, findCheaperOp, IC_LEFT (ic), &pdop, 0);
1494               if (pdop)
1495                 ReplaceOpWithCheaperOp(&IC_LEFT(ic), pdop);
1496             }
1497           /* the lookup could have changed it */
1498           if (IS_SYMOP (IC_LEFT (ic)))
1499             {
1500               OP_USES(IC_LEFT (ic))=
1501                 bitVectSetBit (OP_USES (IC_LEFT (ic)), ic->key);
1502               setUsesDefs (IC_LEFT (ic), ebb->defSet,
1503                            ebb->outDefs, &ebb->usesDefs);
1504             }
1505
1506
1507           /* if we a sending a pointer as a parameter
1508              then kill all cse since the pointed to item
1509              might be changed in the function being called */
1510           if ((ic->op == IPUSH || ic->op == SEND) &&
1511               IS_PTR (operandType (IC_LEFT (ic))))
1512             {
1513               deleteGetPointers (&cseSet, &ptrSetSet, IC_LEFT (ic), ebb);
1514               ebb->ptrsSet = bitVectSetBit (ebb->ptrsSet, IC_LEFT (ic)->key);
1515               for (i = 0; i < count; ebbs[i++]->visited = 0);
1516               applyToSet (ebb->succList, delGetPointerSucc,
1517                           IC_LEFT (ic), ebb->dfnum);
1518             }
1519           continue;
1520         }
1521
1522       /* if jumptable then mark the usage */
1523       if (ic->op == JUMPTABLE)
1524         {
1525           OP_USES(IC_JTCOND (ic))=
1526             bitVectSetBit (OP_USES (IC_JTCOND (ic)), ic->key);
1527           setUsesDefs (IC_JTCOND (ic), ebb->defSet,
1528                        ebb->outDefs, &ebb->usesDefs);
1529           continue;
1530         }
1531
1532       if (SKIP_IC (ic))
1533         continue;
1534
1535       /* do some algebraic optimizations if possible */
1536       algebraicOpts (ic);
1537       while (constFold (ic, cseSet));
1538
1539       /* small klugde */
1540       if (POINTER_GET (ic) && !IS_PTR (operandType (IC_LEFT (ic))))
1541         {
1542           setOperandType (IC_LEFT (ic),
1543                           aggrToPtr (operandType (IC_LEFT (ic)), FALSE));
1544           fixUpTypes (ic);
1545
1546         }
1547       if (POINTER_SET (ic) && !IS_PTR (operandType (IC_RESULT (ic))))
1548         {
1549           setOperandType (IC_RESULT (ic),
1550                           aggrToPtr (operandType (IC_RESULT (ic)), FALSE));
1551         }
1552
1553       /* if this is a condition statment then */
1554       /* check if the condition can be replaced */
1555       if (ic->op == IFX)
1556         {
1557           ifxOptimize (ic, cseSet, computeOnly,
1558                        ebb, &change,
1559                        ebbs, count);
1560           continue;
1561         }
1562
1563       /* if the assignment & result is a temp */
1564       /* see if we can replace it             */
1565       if (ic->op == '=')
1566         {
1567
1568           /* update the spill location for this */
1569           updateSpillLocation (ic,0);
1570
1571           if (POINTER_SET (ic) &&
1572               !(IS_BITFIELD (OP_SYMBOL (IC_RESULT (ic))->etype)))
1573             {
1574               pdop = NULL;
1575               applyToSetFTrue (cseSet, findCheaperOp, IC_RESULT (ic), &pdop, 0);
1576               if (pdop && IS_ITEMP (pdop) && !computeOnly)
1577                 ReplaceOpWithCheaperOp (&IC_RESULT(ic), pdop);
1578             }
1579         }
1580
1581       checkSign = isSignedOp(ic);
1582
1583       /* do the operand lookup i.e. for both the */
1584       /* right & left operand : check the cseSet */
1585       /* to see if they have been replaced if yes */
1586       /* then replace them with those from cseSet */
1587       /* left operand */
1588       /* and left is a symbol  */
1589       if (IS_SYMOP (IC_LEFT (ic)) &&
1590           !computeOnly && ic->op != ADDRESS_OF)
1591         {
1592
1593           pdop = NULL;
1594           applyToSetFTrue (cseSet, findCheaperOp, IC_LEFT (ic), &pdop, checkSign);
1595           if (pdop)
1596             {
1597               if (POINTER_GET (ic))
1598                 {
1599                   if (IS_ITEMP (pdop) || IS_OP_LITERAL (pdop))
1600                     {
1601                         /* some non dominating block does POINTER_SET with
1602                            this variable .. unsafe to remove any POINTER_GETs */
1603                         if (bitVectBitValue(ebb->ndompset,IC_LEFT(ic)->key))
1604                             ebb->ptrsSet = bitVectSetBit(ebb->ptrsSet,pdop->key);
1605                         ReplaceOpWithCheaperOp(&IC_LEFT(ic), pdop);
1606                       change = 1;
1607                     }
1608                   /* check if there is a pointer set
1609                      for the same pointer visible if yes
1610                      then change this into an assignment */
1611                   pdop = NULL;
1612                   if (applyToSetFTrue (cseSet, findPointerSet, IC_LEFT (ic), &pdop, IC_RESULT (ic)) &&
1613                       !bitVectBitValue (ebb->ptrsSet, pdop->key))
1614                     {
1615                       ic->op = '=';
1616                       IC_LEFT (ic) = NULL;
1617                       ReplaceOpWithCheaperOp(&IC_RIGHT(ic), pdop);
1618                       SET_ISADDR (IC_RESULT (ic), 0);
1619                     }
1620
1621                 }
1622               else
1623                 {
1624                   ReplaceOpWithCheaperOp(&IC_LEFT(ic), pdop);
1625                   change = 1;
1626                 }
1627             }
1628         }
1629
1630       /*right operand */
1631       if (IS_SYMOP (IC_RIGHT (ic)) && !computeOnly)
1632         {
1633
1634           pdop = NULL;
1635           applyToSetFTrue (cseSet, findCheaperOp, IC_RIGHT (ic), &pdop, checkSign);
1636           if (pdop) {
1637             ReplaceOpWithCheaperOp(&IC_RIGHT(ic), pdop);
1638             change = 1;
1639           }
1640         }
1641         
1642       /* if left or right changed then do algebraic */
1643       if (change)
1644         {
1645           algebraicOpts (ic);
1646           while (constFold (ic, cseSet));
1647         }
1648
1649       /* if after all this it becomes a assignment to self
1650          then delete it and continue */
1651       if (ASSIGNMENT_TO_SELF (ic))
1652         {
1653           remiCodeFromeBBlock (ebb, ic);
1654           continue;
1655         }
1656
1657       /* now we will check to see if the entire */
1658       /* operation has been performed before    */
1659       /* and is available                       */
1660       /* don't do assignments they will be killed */
1661       /* by dead code elimination if required  do */
1662       /* it only if result is a temporary         */
1663       pdic = NULL;
1664       if (!(POINTER_GET (ic) &&
1665             (IS_BITFIELD (OP_SYMBOL (IC_RESULT (ic))->etype) ||
1666              isOperandVolatile (IC_LEFT (ic), TRUE) ||
1667              bitVectBitValue (ebb->ndompset, IC_LEFT (ic)->key))) &&
1668           !ASSIGNMENT (ic) &&
1669           IS_ITEMP (IC_RESULT (ic)) &&
1670           !computeOnly)
1671         {
1672             applyToSet (cseSet, findPrevIc, ic, &pdic);
1673           if (pdic && compareType (operandType (IC_RESULT (pdic)),
1674                                  operandType (IC_RESULT (ic))) != 1)
1675             pdic = NULL;
1676           if (pdic && port->cseOk && (*port->cseOk)(ic,pdic) == 0) 
1677               pdic = NULL;
1678         }
1679
1680       /* Alternate code */
1681       if (pdic && IS_ITEMP(IC_RESULT(ic))) {
1682         if (POINTER_GET(ic) && bitVectBitValue(ebb->ptrsSet,IC_LEFT(ic)->key)) {
1683           /* Mmm, found an equivalent pointer get at a lower level. 
1684              This could be a loop however with the same pointer set 
1685              later on */
1686         } else {
1687           /* if previous definition found change this to an assignment */
1688           ic->op = '=';
1689           IC_LEFT(ic) = NULL;
1690           IC_RIGHT(ic) = operandFromOperand(IC_RESULT(pdic));
1691           SET_ISADDR(IC_RESULT(ic),0);
1692           SET_ISADDR(IC_RIGHT (ic),0);    
1693         }
1694       }
1695
1696       if (!(POINTER_SET (ic)) && IC_RESULT (ic)) {
1697           deleteItemIf (&cseSet, ifDefSymIsX, IC_RESULT (ic));
1698           addSetHead (&cseSet, newCseDef (IC_RESULT (ic), ic));
1699       }
1700       defic = ic;
1701
1702       /* if assignment to a parameter which is not
1703          mine and type is a pointer then delete
1704          pointerGets to take care of aliasing */
1705       if (ASSIGNMENT (ic) &&
1706           OTHERS_PARM (OP_SYMBOL (IC_RESULT (ic))) &&
1707           IS_PTR (operandType (IC_RESULT (ic))))
1708         {
1709           deleteGetPointers (&cseSet, &ptrSetSet, IC_RIGHT (ic), ebb);
1710           for (i = 0; i < count; ebbs[i++]->visited = 0);
1711           applyToSet (ebb->succList, delGetPointerSucc, IC_RIGHT (ic), ebb->dfnum);
1712           ebb->ptrsSet = bitVectSetBit (ebb->ptrsSet, IC_RIGHT (ic)->key);
1713         }
1714
1715       /* if this is a pointerget then see if we can replace
1716          this with a previously assigned pointer value */
1717       if (POINTER_GET (ic) &&
1718           !(IS_BITFIELD (OP_SYMBOL (IC_RESULT (ic))->etype) ||
1719             isOperandVolatile (IC_LEFT (ic), TRUE)))
1720         {
1721           pdop = NULL;
1722           applyToSet (ptrSetSet, findPointerSet, IC_LEFT (ic), &pdop, IC_RESULT (ic));
1723           /* if we find it then locally replace all
1724              references to the result with what we assigned */
1725           if (pdop)
1726             {
1727               replaceAllSymBySym (ic->next, IC_RESULT (ic), pdop, &ebb->ndompset);
1728             }
1729         }
1730
1731       /* delete from the cseSet anything that has */
1732       /* operands matching the result of this     */
1733       /* except in case of pointer access         */
1734       if (!(POINTER_SET (ic)) && IC_RESULT (ic))
1735         {
1736           deleteItemIf (&cseSet, ifOperandsHave, IC_RESULT (ic));
1737           /* delete any previous definitions */
1738           ebb->defSet = bitVectCplAnd (ebb->defSet, OP_DEFS (IC_RESULT (ic)));
1739
1740         }
1741
1742       /* add the left & right to the defUse set */
1743       if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)))
1744         {
1745           OP_USES(IC_LEFT (ic))=
1746             bitVectSetBit (OP_USES (IC_LEFT (ic)), ic->key);
1747           setUsesDefs (IC_LEFT (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs);
1748
1749         }
1750
1751       if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)))
1752         {
1753           OP_USES(IC_RIGHT (ic))=
1754             bitVectSetBit (OP_USES (IC_RIGHT (ic)), ic->key);
1755           setUsesDefs (IC_RIGHT (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs);
1756
1757         }
1758
1759       /* for the result it is special case, put the result */
1760       /* in the defuseSet if it a pointer or array access  */
1761       if (POINTER_SET (defic))
1762         {
1763           OP_USES(IC_RESULT (ic))=
1764             bitVectSetBit (OP_USES (IC_RESULT (ic)), ic->key);
1765           setUsesDefs (IC_RESULT (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs);
1766           deleteItemIf (&cseSet, ifPointerGet, IC_RESULT (ic));
1767           ebb->ptrsSet = bitVectSetBit (ebb->ptrsSet, IC_RESULT (ic)->key);
1768           /* delete from inexpressions of all successors which
1769              have dfNum > than this block */
1770           for (i = 0; i < count; ebbs[i++]->visited = 0);
1771           applyToSet (ebb->succList, delGetPointerSucc, IC_RESULT (ic), ebb->dfnum);
1772
1773           /* delete from cseSet all other pointer sets
1774              for this operand */
1775           deleteItemIf (&ptrSetSet, ifPointerSet, IC_RESULT (ic));
1776           /* add to the local pointerset set */
1777           addSetHead (&ptrSetSet, newCseDef (IC_RESULT (ic), ic));
1778         }
1779       else
1780         /* add the result to defintion set */ if (IC_RESULT (ic))
1781         {
1782           OP_DEFS(IC_RESULT (ic))=
1783             bitVectSetBit (OP_DEFS (IC_RESULT (ic)), ic->key);
1784           ebb->defSet = bitVectSetBit (ebb->defSet, ic->key);
1785           ebb->outDefs = bitVectCplAnd (ebb->outDefs, OP_DEFS (IC_RESULT (ic)));
1786           ebb->ldefs = bitVectSetBit (ebb->ldefs, ic->key);
1787         }
1788
1789
1790       /* if this is an addressof instruction then */
1791       /* put the symbol in the address of list &  */
1792       /* delete it from the cseSet                */
1793       if (defic->op == ADDRESS_OF)
1794         {
1795           addSetHead (&ebb->addrOf, IC_LEFT (ic));
1796           deleteItemIf (&cseSet, ifDefSymIsX, IC_LEFT (ic));
1797         }
1798     }
1799
1800   setToNull ((void **) &ebb->outExprs);
1801   ebb->outExprs = cseSet;
1802   ebb->outDefs = bitVectUnion (ebb->outDefs, ebb->defSet);
1803   ebb->ptrsSet = bitVectUnion (ebb->ptrsSet, ebb->inPtrsSet);
1804   return change;
1805 }
1806
1807 /*-----------------------------------------------------------------*/
1808 /* cseAllBlocks - will sequentially go thru & do cse for all blocks */
1809 /*-----------------------------------------------------------------*/
1810 int 
1811 cseAllBlocks (eBBlock ** ebbs, int count)
1812 {
1813   int i;
1814   int change = 0;
1815
1816   /* if optimization turned off */
1817
1818   for (i = 0; i < count; i++)
1819     change += cseBBlock (ebbs[i], FALSE, ebbs, count);
1820
1821   return change;
1822 }