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