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