enabled somemore pointer post inc/dec optimizations
[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     /* this routine will change
977        a = b + 10;
978        c = a + 10;
979        to
980        c = b + 20; */
981
982     /* deal with only + & - */
983     if (ic->op != '+' &&
984         ic->op != '-' )
985         return 0;
986
987     /* this check is a hueristic to prevent live ranges
988        from becoming too long */
989     if (IS_PTR(operandType(IC_RESULT(ic))))
990         return 0;
991
992     /* check if operation with a literal */
993     if (!IS_OP_LITERAL(IC_RIGHT(ic)))
994         return 0;
995
996     /* check if we can find a definition for the
997        right hand side */
998     if (!(applyToSet(cseSet,diCodeForSym,IC_LEFT(ic),&dic)))
999         return 0;
1000
1001     /* check that this is also a +/-  */
1002     if (dic->op != '+' && dic->op != '-')
1003         return 0;
1004
1005     /* with a literal */
1006     if (!IS_OP_LITERAL(IC_RIGHT(dic)))
1007         return 0;
1008
1009     /* it is if the operations are the same*/
1010     /* the literal parts need to be added  */
1011     IC_LEFT(ic) = operandFromOperand(IC_LEFT(dic));    
1012     if (ic->op == dic->op )
1013         IC_RIGHT(ic) = operandFromLit(operandLitValue(IC_RIGHT(ic))+
1014                                       operandLitValue(IC_RIGHT(dic)));
1015     else
1016         IC_RIGHT(ic) = operandFromLit(operandLitValue(IC_RIGHT(ic)) -
1017                                       operandLitValue(IC_RIGHT(dic)));
1018
1019     if (IS_ITEMP(IC_RESULT(ic))) {
1020         SPIL_LOC(IC_RESULT(ic)) = NULL;
1021         IC_RESULT(ic)->noSpilLoc = 1;
1022     }
1023         
1024     
1025     return 1;
1026 }
1027
1028 /*-----------------------------------------------------------------*/
1029 /* deleteGetPointers - called when a pointer is passed as parm     */
1030 /* will delete from cseSet all get pointers computed from this     */
1031 /* pointer. A simple ifOperandsHave is not good enough here        */
1032 /*-----------------------------------------------------------------*/
1033 static void deleteGetPointers (set **cseSet, set **pss, operand *op,eBBlock *ebb)
1034 {
1035     set *compItems = NULL;
1036     cseDef *cdp ;
1037     operand *cop;
1038     
1039     /* easy return */
1040     if (!*cseSet && !*pss)
1041         return ;
1042     
1043     /* first find all items computed from this operand .
1044        This done fairly simply go thru the list and find
1045        those that are computed by arthimetic with this
1046        op */
1047     for (cdp = setFirstItem(*cseSet); cdp ; cdp = setNextItem(*cseSet)) {
1048         if (IS_ARITHMETIC_OP(cdp->diCode)) {
1049             if (isOperandEqual(IC_LEFT(cdp->diCode),op) ||
1050                 isOperandEqual(IC_RIGHT(cdp->diCode),op)) {
1051                                 /* save it in our list of items */
1052                 addSet(&compItems,IC_RESULT(cdp->diCode));
1053             }
1054             /* also check for those computed from our computed 
1055                list . This will take care of situations like
1056                iTemp1 = iTemp0 + 8;
1057                iTemp2 = iTemp1 + 8; */
1058             if (isinSetWith(compItems,IC_LEFT(cdp->diCode),isOperandEqual) ||
1059                 isinSetWith(compItems,IC_RIGHT(cdp->diCode),isOperandEqual)) {
1060                     addSet(&compItems,IC_RESULT(cdp->diCode));
1061             }
1062         }
1063     }
1064     
1065     /* now delete all pointer gets with this op */
1066     deleteItemIf(cseSet,ifPointerGet,op);
1067     deleteItemIf(pss,ifPointerSet,op);
1068
1069     /* set the bit vector used by dataFlow computation later */
1070     ebb->ptrsSet = bitVectSetBit(ebb->ptrsSet,op->key);
1071     /* now for the computed items */
1072     for (cop = setFirstItem(compItems); cop ; cop = setNextItem(compItems)) {
1073         ebb->ptrsSet = bitVectSetBit(ebb->ptrsSet,cop->key);    
1074         deleteItemIf(cseSet,ifPointerGet,cop);
1075         deleteItemIf(pss,ifPointerSet,cop);
1076     }
1077 }
1078
1079 /*-----------------------------------------------------------------*/
1080 /* delGetPointerSucc - delete get pointer from inExprs of succ with*/
1081 /*                     dfnum > supplied                            */
1082 /*-----------------------------------------------------------------*/
1083 DEFSETFUNC(delGetPointerSucc)
1084 {
1085     eBBlock *ebp = item;
1086     V_ARG(operand *,op);
1087     V_ARG(int,dfnum);
1088
1089     if (ebp->visited)
1090         return 0;
1091     
1092     ebp->visited = 1;
1093     if (ebp->dfnum > dfnum) {
1094         deleteItemIf(&ebp->inExprs,ifPointerGet,op);
1095     }
1096
1097     return applyToSet(ebp->succList,delGetPointerSucc,op,dfnum);
1098 }    
1099
1100 /*-----------------------------------------------------------------*/
1101 /* cseBBlock - common subexpression elimination for basic blocks   */
1102 /*             this is the hackiest kludgiest routine in the whole */
1103 /*             system. also the most important, since almost all   */
1104 /*             data flow related information is computed by it     */
1105 /*-----------------------------------------------------------------*/
1106 int cseBBlock ( eBBlock *ebb, int computeOnly, 
1107                 eBBlock **ebbs, int count)
1108 {
1109     set *cseSet ;
1110     iCode *ic ;           
1111     int change = 0 ;
1112     int i;   
1113     set *ptrSetSet = NULL;
1114
1115     /* if this block is not reachable */
1116     if (ebb->noPath)
1117         return change;
1118
1119    /* set of common subexpressions */   
1120     cseSet = setFromSet (ebb->inExprs) ;      
1121       
1122     /* these will be computed by this routine */
1123     setToNull ((void **)&ebb->outDefs);    
1124     setToNull ((void **)&ebb->defSet);
1125     setToNull ((void **)&ebb->usesDefs);
1126     setToNull ((void **)&ebb->ptrsSet);
1127     setToNull ((void **)&ebb->addrOf);
1128     setToNull ((void **)&ebb->ldefs);
1129
1130     ebb->outDefs = bitVectCopy (ebb->inDefs);
1131     bitVectDefault = iCodeKey;
1132     ebb->defSet = newBitVect(iCodeKey);
1133     ebb->usesDefs=newBitVect(iCodeKey);
1134
1135     /* for all the instructions in this block do */
1136     for (ic = ebb->sch ; ic ; ic = ic->next ) {
1137         
1138         iCode *pdic; 
1139         operand *pdop ;
1140         iCode *defic;
1141         
1142         if (SKIP_IC2(ic))
1143             continue ;
1144
1145         /* if this is an assignment from true symbol
1146            to a temp then do pointer post inc/dec optimzation */
1147         if (ic->op == '=' && !POINTER_SET(ic) &&
1148             IS_PTR(operandType(IC_RESULT(ic)))) {
1149             ptrPostIncDecOpt(ic);
1150         }
1151
1152         /* clear the def & use chains for the operands involved */
1153         /* in this operation . since it can change due to opts  */
1154         unsetDefsAndUses (ic);
1155         
1156         if ( ic->op == PCALL || ic->op == CALL || ic->op == RECEIVE) {
1157             /* add to defSet of the symbol */
1158             OP_DEFS(IC_RESULT(ic)) = 
1159                 bitVectSetBit (OP_DEFS(IC_RESULT(ic)),ic->key);
1160             /* add to the definition set of this block */
1161             ebb->defSet = bitVectSetBit (ebb->defSet,ic->key);      
1162             ebb->ldefs  = bitVectSetBit (ebb->ldefs,ic->key);
1163             ebb->outDefs= bitVectCplAnd (ebb->outDefs,OP_DEFS(IC_RESULT(ic)));
1164             setUsesDefs(IC_RESULT(ic),ebb->defSet,ebb->outDefs,&ebb->usesDefs);
1165             /* delete global variables from the cseSet
1166                since they can be modified by the function call */
1167             deleteItemIf(&cseSet,ifDefGlobal);
1168         }
1169
1170         /* for pcall & ipush we need to add to the useSet */
1171         if ((ic->op == PCALL || 
1172              ic->op == IPUSH || 
1173              ic->op == IPOP  || 
1174              ic->op == SEND) && 
1175             IS_SYMOP(IC_LEFT(ic))) {
1176             
1177             /* check if they can be replaced */
1178             if ( !computeOnly ) {
1179                 pdop = NULL ;
1180                 applyToSetFTrue(cseSet,findCheaperOp,IC_LEFT(ic),&pdop);
1181                 if (pdop)
1182                     IC_LEFT(ic) = pdop ;
1183             }
1184             /* the lookup could have changed it*/
1185             if (IS_SYMOP(IC_LEFT(ic))) {
1186                 OP_USES(IC_LEFT(ic)) = 
1187                     bitVectSetBit(OP_USES(IC_LEFT(ic)),ic->key);
1188                 setUsesDefs(IC_LEFT(ic),ebb->defSet,
1189                             ebb->outDefs,&ebb->usesDefs);
1190             }
1191
1192             
1193             /* if we a sending a pointer as a parameter
1194                then kill all cse since the pointed to item
1195                might be changed in the function being called */
1196             if ((ic->op == IPUSH || ic->op == SEND) &&
1197                 IS_PTR(operandType(IC_LEFT(ic)))) {
1198                 deleteGetPointers(&cseSet,&ptrSetSet,IC_LEFT(ic),ebb);
1199                 ebb->ptrsSet = bitVectSetBit(ebb->ptrsSet,IC_LEFT(ic)->key);
1200                 for (i = 0 ; i < count ;ebbs[i++]->visited = 0);
1201                 applyToSet(ebb->succList,delGetPointerSucc,
1202                            IC_LEFT(ic),ebb->dfnum);
1203             }
1204             continue;
1205         }
1206
1207         /* if jumptable then mark the usage */
1208         if (ic->op == JUMPTABLE ) {
1209             OP_USES(IC_JTCOND(ic)) = 
1210                 bitVectSetBit(OP_USES(IC_JTCOND(ic)),ic->key);
1211             setUsesDefs(IC_JTCOND(ic),ebb->defSet,
1212                         ebb->outDefs,&ebb->usesDefs);
1213             continue;
1214         }
1215
1216         if (SKIP_IC(ic))
1217             continue ;
1218         
1219         /* do some algebraic optimizations if possible */
1220         algebraicOpts (ic);
1221         while (constFold(ic,cseSet));
1222
1223         /* small klugde */
1224         if (POINTER_GET(ic) && !IS_PTR(operandType(IC_LEFT(ic)))) {
1225             setOperandType(IC_LEFT(ic),
1226                            aggrToPtr(operandType(IC_LEFT(ic)),FALSE));
1227         }
1228         if (POINTER_SET(ic) && !IS_PTR(operandType(IC_RESULT(ic)))) {
1229             setOperandType(IC_RESULT(ic),
1230                            aggrToPtr(operandType(IC_RESULT(ic)),FALSE));
1231         }
1232
1233         /* if this is a condition statment then */
1234         /* check if the condition can be replaced */
1235         if (ic->op == IFX ) {
1236             ifxOptimize (ic, cseSet, computeOnly, 
1237                          ebb, &change, 
1238                          ebbs, count);
1239             continue ;
1240         }
1241             
1242         /* if the assignment & result is a temp */
1243         /* see if we can replace it             */
1244         if (ic->op == '=') {
1245             
1246             /* update the spill location for this */
1247             updateSpillLocation (ic);
1248
1249             if (POINTER_SET(ic)) {
1250                 pdop = NULL ;
1251                 applyToSetFTrue (cseSet,findCheaperOp,IC_RESULT(ic),&pdop);
1252                 if (pdop && IS_ITEMP(pdop) && !computeOnly)                 
1253                     IC_RESULT(ic) = pdop;                               
1254             }
1255         }           
1256         
1257         /* do the operand lookup i.e. for both the */
1258         /* right & left operand : check the cseSet */
1259         /* to see if they have been replaced if yes*/
1260         /* then replace them with those from cseSet*/
1261         /* left operand */
1262         /* and left is a symbol  */
1263         if (IS_SYMOP(IC_LEFT(ic)) && 
1264             !computeOnly && ic->op != ADDRESS_OF ) {  
1265             
1266             pdop = NULL;                
1267             applyToSetFTrue (cseSet,findCheaperOp,IC_LEFT(ic),&pdop) ;
1268             if (pdop)  { 
1269                 if (POINTER_GET(ic)) {
1270                     if (IS_ITEMP(pdop) || IS_OP_LITERAL(pdop)) {
1271                         IC_LEFT(ic) = pdop;
1272                         change = 1;
1273                     }
1274                     /* check if there is a pointer set
1275                        for the same pointer visible if yes
1276                        then change this into an assignment */
1277                     pdop = NULL;
1278                     if (applyToSetFTrue(cseSet,findPointerSet,IC_LEFT(ic),&pdop,IC_RESULT(ic)) &&
1279                         !bitVectBitValue(ebb->ptrsSet,pdop->key)){
1280                         ic->op = '=';
1281                         IC_LEFT(ic) = NULL;
1282                         IC_RIGHT(ic) = pdop;
1283                         SET_ISADDR(IC_RESULT(ic),0);
1284                     }
1285                         
1286                 }
1287                 else {
1288                     IC_LEFT(ic)  = pdop ;
1289                     change = 1;
1290                 }
1291             }       
1292         }
1293         
1294         /*right operand */
1295         if (IS_SYMOP(IC_RIGHT(ic)) && !computeOnly) {
1296             
1297             pdop = NULL ;
1298             applyToSetFTrue (cseSet,findCheaperOp,IC_RIGHT(ic),&pdop);
1299             if (pdop) {
1300                 
1301                 IC_RIGHT(ic) = pdop;
1302                 change = 1;
1303             }
1304         }
1305         
1306         /* if left or right changed then do algebraic */
1307         if (change) {
1308             algebraicOpts(ic);
1309             while(constFold(ic,cseSet));
1310         }
1311
1312         /* if after all this it becomes a assignment to self 
1313            then delete it and continue */
1314         if (ASSIGNMENT_TO_SELF(ic)) {      
1315             remiCodeFromeBBlock(ebb,ic);
1316             continue;
1317         }           
1318         
1319         /* now we will check to see if the entire */
1320         /* operation has been performed before    */
1321         /* and is available                       */     
1322         /* don't do assignments they will be killed */
1323         /* by dead code elimination if required  do */
1324         /* it only if result is a temporary         */
1325         pdic = NULL ;   
1326         if (!( POINTER_GET(ic)                      &&
1327                (IS_BITFIELD(OP_SYMBOL(IC_RESULT(ic))->etype) ||
1328                isOperandVolatile(IC_LEFT(ic),TRUE)           ||
1329                bitVectBitValue(ebb->ndompset,IC_LEFT(ic)->key))) &&
1330             ! ASSIGNMENT(ic)                        && 
1331               IS_ITEMP(IC_RESULT(ic))               &&
1332             ! computeOnly) {
1333             applyToSet (cseSet,findPrevIc,ic,&pdic);
1334         } 
1335        
1336         /* if found then eliminate this and add to*/
1337         /* to cseSet an element containing result */
1338         /* of this with previous opcode           */      
1339         if (pdic) {
1340
1341             if (IS_ITEMP(IC_RESULT(ic))) {
1342
1343                 /* replace in the remaining of this block */
1344                 replaceAllSymBySym(ic->next,IC_RESULT(ic),IC_RESULT(pdic),&ebb->ndompset);
1345                 /* remove this iCode from inexpressions of all
1346                    its successors, it cannot be in the in expressions
1347                    of any of the predecessors */        
1348                 for (i = 0 ; i < count ;ebbs[i++]->visited = 0);
1349                 applyToSet(ebb->succList,removeFromInExprs,ic,IC_RESULT(ic),
1350                            IC_RESULT(pdic),ebb);
1351
1352                 /* if this was moved from another block */
1353                 /* then replace in those blocks too     */
1354                 if ( ic->movedFrom ) {
1355                     eBBlock *owner ;
1356                     for (owner = setFirstItem(ic->movedFrom); owner ;
1357                          owner = setNextItem(ic->movedFrom))
1358                         replaceAllSymBySym(owner->sch,IC_RESULT(ic),IC_RESULT(pdic),&owner->ndompset);
1359                 }
1360                 pdic->movedFrom = unionSets(pdic->movedFrom,ic->movedFrom,THROW_NONE);
1361             } 
1362             else
1363                 addSetHead (&cseSet,newCseDef(IC_RESULT(ic),pdic));                     
1364             
1365             if (!computeOnly) 
1366                 /* eliminate this */
1367                 remiCodeFromeBBlock (ebb,ic);               
1368                     
1369             defic = pdic ;          
1370             change++ ;
1371
1372             if (IS_ITEMP(IC_RESULT(ic)))
1373                 continue ;
1374
1375         } else {
1376
1377             /* just add this as a previous expression except in */
1378             /* case of a pointer access in which case this is a */
1379             /* usage not a definition                           */
1380             if (! (POINTER_SET(ic)) && IC_RESULT(ic)){
1381                 deleteItemIf (&cseSet, ifDefSymIsX,IC_RESULT(ic));
1382                 addSetHead(&cseSet,newCseDef(IC_RESULT(ic),ic));
1383             }
1384             defic = ic;
1385
1386         }
1387         
1388         /* if assignment to a parameter which is not
1389            mine and type is a pointer then delete
1390            pointerGets to take care of aliasing */
1391         if (ASSIGNMENT(ic)                        && 
1392             OTHERS_PARM(OP_SYMBOL(IC_RESULT(ic))) &&
1393             IS_PTR(operandType(IC_RESULT(ic)))) {
1394             deleteGetPointers(&cseSet,&ptrSetSet,IC_RIGHT(ic),ebb);
1395             for (i = 0 ; i < count ;ebbs[i++]->visited = 0);
1396             applyToSet(ebb->succList,delGetPointerSucc,IC_RIGHT(ic),ebb->dfnum);
1397             ebb->ptrsSet = bitVectSetBit(ebb->ptrsSet,IC_RIGHT(ic)->key);
1398         }
1399
1400         /* if this is a pointerget then see if we can replace
1401            this with a previously assigned pointer value */
1402         if (POINTER_GET(ic) && 
1403             !(IS_BITFIELD(OP_SYMBOL(IC_RESULT(ic))->etype) ||
1404                isOperandVolatile(IC_LEFT(ic),TRUE))) {
1405             pdop = NULL;
1406             applyToSet(ptrSetSet,findPointerSet,IC_LEFT(ic),&pdop,IC_RESULT(ic));
1407             /* if we find it then locally replace all
1408                references to the result with what we assigned */
1409             if (pdop) {
1410                 replaceAllSymBySym(ic->next,IC_RESULT(ic),pdop,&ebb->ndompset);
1411             }
1412         }
1413
1414         /* delete from the cseSet anything that has */
1415         /* operands matching the result of this     */
1416         /* except in case of pointer access         */
1417         if (!(POINTER_SET(ic)) && IC_RESULT(ic)) {
1418             deleteItemIf (&cseSet,ifOperandsHave,IC_RESULT(ic));            
1419             /* delete any previous definitions */ 
1420             ebb->defSet = bitVectCplAnd (ebb->defSet,OP_DEFS(IC_RESULT(ic)));     
1421             
1422         }
1423         
1424         /* add the left & right to the defUse set */
1425         if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic))) {
1426             OP_USES(IC_LEFT(ic)) = 
1427                 bitVectSetBit (OP_USES(IC_LEFT(ic)),ic->key);
1428             setUsesDefs(IC_LEFT(ic),ebb->defSet,ebb->outDefs,&ebb->usesDefs);
1429
1430         }
1431
1432         if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic))) {
1433             OP_USES(IC_RIGHT(ic)) = 
1434                 bitVectSetBit (OP_USES(IC_RIGHT(ic)),ic->key);  
1435             setUsesDefs(IC_RIGHT(ic),ebb->defSet,ebb->outDefs,&ebb->usesDefs);
1436
1437         }
1438
1439         /* for the result it is special case, put the result */
1440         /* in the defuseSet if it a pointer or array access  */
1441         if ( POINTER_SET(defic) ) {
1442             OP_USES(IC_RESULT(ic)) = 
1443                 bitVectSetBit (OP_USES(IC_RESULT(ic)),ic->key);
1444             setUsesDefs(IC_RESULT(ic),ebb->defSet,ebb->outDefs,&ebb->usesDefs);
1445             deleteItemIf(&cseSet,ifPointerGet,IC_RESULT(ic));
1446             ebb->ptrsSet = bitVectSetBit(ebb->ptrsSet,IC_RESULT(ic)->key);
1447             /* delete from inexpressions of all successors which
1448                have dfNum > than this block */
1449             for (i = 0 ; i < count ;ebbs[i++]->visited = 0);
1450             applyToSet(ebb->succList,delGetPointerSucc,IC_RESULT(ic),ebb->dfnum);
1451             
1452             /* delete from cseSet all other pointer sets
1453                for this operand */
1454             deleteItemIf(&ptrSetSet,ifPointerSet,IC_RESULT(ic));
1455             /* add to the local pointerset set */
1456             addSetHead(&ptrSetSet,newCseDef(IC_RESULT(ic),ic));
1457         }
1458         else /* add the result to defintion set */
1459             if (IC_RESULT(ic)) {
1460                 OP_DEFS(IC_RESULT(ic)) = 
1461                     bitVectSetBit (OP_DEFS(IC_RESULT(ic)),ic->key);
1462                 ebb->defSet = bitVectSetBit (ebb->defSet,ic->key);              
1463                 ebb->outDefs= bitVectCplAnd (ebb->outDefs,OP_DEFS(IC_RESULT(ic))); 
1464                 ebb->ldefs  = bitVectSetBit (ebb->ldefs,ic->key);
1465             }
1466                
1467
1468         /* if this is an addressof instruction then */
1469         /* put the symbol in the address of list &  */
1470         /* delete it from the cseSet                */
1471         if (defic->op == ADDRESS_OF) {
1472             addSetHead (&ebb->addrOf, IC_LEFT(ic));
1473             deleteItemIf(&cseSet,ifDefSymIsX,IC_LEFT(ic));
1474         }
1475     }
1476
1477     setToNull ((void **)&ebb->outExprs);
1478     ebb->outExprs = cseSet;        
1479     ebb->outDefs = bitVectUnion (ebb->outDefs,ebb->defSet);
1480     ebb->ptrsSet = bitVectUnion (ebb->ptrsSet,ebb->inPtrsSet);
1481     return change ;
1482 }
1483
1484 /*-----------------------------------------------------------------*/
1485 /* cseAllBlocks - will sequentially go thru & do cse for all blocks*/
1486 /*-----------------------------------------------------------------*/
1487 int cseAllBlocks (eBBlock **ebbs,int count)
1488 {
1489     int i;
1490     int change = 0 ;
1491
1492     /* if optimization turned off */
1493
1494     for (i = 0 ; i < count ;i++ ) 
1495         change += cseBBlock (ebbs[i],FALSE,ebbs,count);
1496
1497     return change;
1498 }
1499