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