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