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