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