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