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