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