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