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