* src/avr/ralloc.c (serialRegAssign),
[fw/sdcc] / src / xa51 / ralloc.c
1 /* This port is in development, UNSTABLE, DEVELOPERS ONLY! */
2
3 /* idea:
4    R0-^-R2(R0L-R2H) used for scratch (byte, word, pointer)
5    R3L-^-R6H used for bytes
6    R6-v-R4 used for ptr
7    R15/R6-v-R4 used for words
8    
9    R7 used for stack
10 */
11
12 /*------------------------------------------------------------------------
13   
14   SDCCralloc.c - source file for register allocation. (xa51) specific
15   
16   Written By -  
17   
18   This program is free software; you can redistribute it and/or modify it
19   under the terms of the GNU General Public License as published by the
20   Free Software Foundation; either version 2, or (at your option) any
21   later version.
22   
23   This program is distributed in the hope that it will be useful,
24   but WITHOUT ANY WARRANTY; without even the implied warranty of
25   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26   GNU General Public License for more details.
27   
28   You should have received a copy of the GNU General Public License
29   along with this program; if not, write to the Free Software
30   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31   
32   In other words, you are welcome to use, share and improve this program.
33   You are forbidden to forbid anyone else to use, share and improve
34   what you give them.   Help stamp out software-hoarding!  
35   -------------------------------------------------------------------------*/
36
37 #include "common.h"
38 #include "ralloc.h"
39 #include "gen.h"
40
41 extern void genXA51Code (iCode *);
42
43 #define D0(x) 
44 #define D1(x) x
45 #define D2(x) x
46
47 /* Global data */
48 static struct
49 {
50   bitVect *spiltSet;
51   set *stackSpil;
52   bitVect *regAssigned;
53   bitVect *totRegAssigned;    /* final set of LRs that got into registers */
54   short blockSpil;
55   int slocNum;
56   bitVect *funcrUsed;           /* registers used in a function */
57   int stackExtend;
58 }
59 _G;
60
61 /* xa51 registers */
62 regs regsXA51[]={
63   // index size type name regMask isFree symbol
64   {R0L_ID, 1, REG_SCR, "r0l", 0x0001, 1, NULL}, // r0l used for scratch
65   {R0H_ID, 1, REG_SCR, "r0h", 0x0002, 1, NULL}, // r0h used for scratch
66   {R1L_ID, 1, REG_SCR, "r1l", 0x0004, 1, NULL}, // r1l used for scratch
67   {R1H_ID, 1, REG_SCR, "r1h", 0x0008, 1, NULL}, // r1h used for scratch
68   {R2L_ID, 1, REG_PTR, "r2l", 0x0010, 1, NULL},
69   {R2H_ID, 1, REG_PTR, "r2h", 0x0020, 1, NULL},
70   {R3L_ID, 1, REG_PTR, "r3l", 0x0040, 1, NULL},
71   {R3H_ID, 1, REG_PTR, "r3h", 0x0080, 1, NULL},
72   {R4L_ID, 1, REG_PTR, "r4l", 0x0100, 1, NULL},
73   {R4H_ID, 1, REG_PTR, "r4h", 0x0200, 1, NULL},
74   {R5L_ID, 1, REG_PTR, "r5l", 0x0400, 1, NULL},
75   {R5H_ID, 1, REG_PTR, "r5h", 0x0800, 1, NULL},
76   {R6L_ID, 1, REG_PTR, "r6l", 0x1000, 1, NULL},
77   {R6H_ID, 1, REG_PTR, "r6h", 0x2000, 1, NULL},
78   {R7L_ID, 1, REG_STK, "r7l", 0x4000, 1, NULL}, // r7=SP
79   {R7H_ID, 1, REG_STK, "r7h", 0x8000, 1, NULL}, // r7=SP
80
81   {R0_ID, 2, REG_SCR, "r0",  0x0003, 1, NULL}, // r0 used for scratch
82   {R1_ID, 2, REG_SCR, "r1",  0x000c, 1, NULL}, // r1 used for scratch
83   {R2_ID, 2, REG_PTR, "r2",  0x0030, 1, NULL}, 
84   {R3_ID, 2, REG_PTR, "r3",  0x00c0, 1, NULL},
85   {R4_ID, 2, REG_PTR, "r4",  0x0300, 1, NULL}, 
86   {R5_ID, 2, REG_PTR, "r5",  0x0c00, 1, NULL}, 
87   {R6_ID, 2, REG_PTR, "r6",  0x3000, 1, NULL}, 
88   {R7_ID, 2, REG_STK, "r7",  0xc000, 1, NULL}, // r7=SP
89 #if 0 // some derivates have even more! (only bit/word access no ptr use)
90   {R8_ID, 2, REG_GPR, "r8",  0x010000, 1, NULL},
91   {R9_ID, 2, REG_GPR, "r9",  0x020000, 1, NULL},
92   {R10_ID, 2, REG_GPR, "r10", 0x040000, 1, NULL},
93   {R11_ID, 2, REG_GPR, "r11", 0x080000, 1, NULL},
94   {R12_ID, 2, REG_GPR, "r12", 0x100000, 1, NULL},
95   {R13_ID, 2, REG_GPR, "r13", 0x200000, 1, NULL},
96   {R14_ID, 2, REG_GPR, "r14", 0x400000, 1, NULL},
97   {R15_ID, 2, REG_GPR, "r15", 0x800000, 1, NULL},
98 #endif
99   {R0R1_ID, 4, REG_GPR, "(r0,r1)", 0x000f, 1, NULL},
100   {R2R3_ID, 4, REG_GPR, "(r2,r3)", 0x00f0, 1, NULL},
101   {R4R5_ID, 4, REG_GPR, "(r4,r5)", 0x0f00, 1, NULL},
102   {R6R7_ID, 4, REG_GPR, "(r6,r7)", 0xf000, 1, NULL},
103 };
104
105 int xa51_nRegs=sizeof(regsXA51)/sizeof(regs);
106
107 // the currently in use registers
108 unsigned long xa51RegsInUse=0;
109
110 // this should be set with a command line switch
111 bool xa51HasGprRegs=0;
112
113 /*-----------------------------------------------------------------*/
114 /* xa51_regWithMask - returns pointer to register with mask        */
115 /*-----------------------------------------------------------------*/
116 regs *xa51_regWithMask (unsigned long mask) {
117   int i;
118   for (i=0; i<xa51_nRegs; i++) {
119     if (regsXA51[i].regMask==mask) {
120       return &regsXA51[i];
121     }
122   }
123   return NULL;
124 }
125
126 /*-----------------------------------------------------------------*/
127 /* checkRegsMask - check the consistancy of the regMask redundancy */
128 /*-----------------------------------------------------------------*/
129
130 void checkRegMask(char *f) { // for debugging purposes only
131   int i;
132   unsigned long regMask=0;
133   
134   // rebuild the regmask
135   for (i=0; i<xa51_nRegs; i++) {
136     if (!regsXA51[i].isFree) {
137       regMask |= regsXA51[i].regMask;
138     }
139   }
140   
141   // check it
142   if (regMask != xa51RegsInUse) {
143     fprintf (stderr, "error(%s): regMask inconsistent 0x%08lx != 0x%08lx\n",
144              f, regMask, xa51RegsInUse);
145     regMask=regMask^xa51RegsInUse;
146     fprintf (stderr, "%s used by %s\n", 
147              xa51_regWithMask(regMask)->name, 
148              xa51_regWithMask(regMask)->sym->name);
149     
150     exit(1);
151     return;
152   }
153 }
154
155 char *regTypeToStr(short type) {
156   switch (type) 
157     {
158     case REG_PTR: return "ptr"; break; // pointer
159     case REG_GPR: return "gpr"; break; // general purpose
160     case REG_CND: return "cnd"; break; // condition (bit)
161     case REG_STK: return "stk"; break; // stack
162     case REG_SCR: return "scr"; break; // scratch
163     default: return "???";
164     }
165 }
166
167 /*-----------------------------------------------------------------*/
168 /* freeReg - frees a previous allocated register                   */
169 /*-----------------------------------------------------------------*/
170 static void freeReg (regs * reg, bool silent) {
171   
172   checkRegMask(__FUNCTION__);
173   
174   if (!reg) {
175     werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
176             "freeReg - freeing NULL register");
177     return;
178   }
179   
180   if (!silent) {
181     D0(fprintf (stderr, "freeReg: (%08lx) %s (%s) ", xa51RegsInUse, 
182                 reg->name, reg->sym->name));
183   }
184   
185   if (reg->isFree || ((xa51RegsInUse&reg->regMask)!=reg->regMask)) {
186     werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
187             "freeReg - freeing unused register(s)");
188     exit (1);
189   }
190   xa51RegsInUse &= ~reg->regMask;
191   reg->isFree = 1;
192   reg->sym = NULL;
193   if (!silent) D0(fprintf (stderr, "(%08lx)\n", xa51RegsInUse));
194   
195   checkRegMask(__FUNCTION__);
196 }
197
198 /*-----------------------------------------------------------------*/
199 /* allocReg - allocates register of given size (byte, word, dword) */
200 /*            and type (ptr, gpr, cnd)                             */
201 /*-----------------------------------------------------------------*/
202 static bool allocReg (short size, short type, symbol *sym, 
203                       short offset, bool silent) {
204   int i;
205   
206   checkRegMask(__FUNCTION__);
207   
208   if (!silent) {
209     D0(fprintf (stderr, "allocReg (%08lx) for %s size:%d, type:%s ", 
210                 xa51RegsInUse,
211                 sym->name,
212                 size, regTypeToStr(type)));
213   }
214   
215   switch (size) 
216     {
217       // TODO: gaps could be filled for dwords too
218     case 1:
219       // let's see if we can fill a gap
220       for (i=0; i<xa51_nRegs; i++) {
221         if (regsXA51[i].size==2 && regsXA51[i].type==type) {
222           unsigned long mask=regsXA51[i].regMask & ~xa51RegsInUse;
223           if (mask && mask!=regsXA51[i].regMask) {
224             regs *reg=xa51_regWithMask(mask);
225             // found a gap
226             sym->regs[offset]=reg;
227             xa51RegsInUse |= mask;
228             reg->isFree=0; // redundant
229             reg->sym = sym;
230             if (!silent) {
231               D0(fprintf (stderr, "(using gap) %s\n", reg->name));
232             }
233             checkRegMask(__FUNCTION__);
234             return TRUE;
235           }
236         }
237       }
238       // no we can't, fall through
239     case 2:
240       for (i=0; i<xa51_nRegs; i++) {
241         if (regsXA51[i].size==size &&
242             regsXA51[i].type==type &&
243             (regsXA51[i].regMask & xa51RegsInUse)==0) {
244           xa51RegsInUse |= regsXA51[i].regMask;
245           regsXA51[i].isFree = 0; // redundant
246           regsXA51[i].sym = sym;
247           if (!silent) {
248             D0(fprintf (stderr, "%s\n", regsXA51[i].name));
249           }
250           sym->regs[offset]=&regsXA51[i];
251           checkRegMask(__FUNCTION__);
252           return TRUE;
253         }
254       }
255       if (!silent) {
256         D0(fprintf (stderr, "failed (%08lx)\n", xa51RegsInUse));
257       }
258       checkRegMask(__FUNCTION__);
259       return FALSE;
260       break;
261     case 3:
262       // this must be a generic pointer
263       if (!silent) {
264         D0(fprintf (stderr, "trying 1+2\n"));
265       }
266       // get the generic part (gpr regs can't be byte)
267       if (allocReg (1, REG_PTR, sym, offset+1, silent)) {
268         // get the pointer part
269         if (allocReg (2, REG_PTR, sym, offset, silent)) {
270           checkRegMask(__FUNCTION__);
271           return TRUE;
272         }
273         freeReg(sym->regs[offset+1], silent);
274         sym->regs[offset+1]=NULL;
275       }
276       checkRegMask(__FUNCTION__);
277       return FALSE;
278       break;
279     case 4: // this is a dword
280       if (!silent) {
281         D0(fprintf (stderr, "trying 2+2\n"));
282       }
283       if ((xa51HasGprRegs && allocReg (2, REG_GPR, sym, offset, silent)) ||
284           allocReg (2, REG_PTR, sym, offset, silent)) {
285         if ((xa51HasGprRegs && allocReg (2, REG_GPR, sym, offset+1, silent)) ||
286             allocReg (2, REG_PTR, sym, offset+1, silent)) {
287           checkRegMask(__FUNCTION__);
288           return TRUE;
289         }
290       }
291       if (sym->regs[offset]) {
292         freeReg(sym->regs[offset], FALSE);
293         sym->regs[offset]=NULL;
294       }
295       checkRegMask(__FUNCTION__);
296       return FALSE;
297       break;
298     }
299   fprintf (stderr, "\nallocReg: cannot allocate reg of size %d\n", size);
300   exit (1);
301   return FALSE;
302 }
303
304 /*-------------------------------------------------------------------*/
305 /* freeAllRegs - frees all registers                                 */
306 /*-------------------------------------------------------------------*/
307 // just to be sure, this should not be needed
308 static void freeAllRegs (void) {
309   char regsFreed[132];
310   int i;
311   int nfr = 0;
312   
313   checkRegMask(__FUNCTION__);
314   
315   regsFreed[0]=0;
316   for (i=0; i<xa51_nRegs; i++) {
317     if (!regsXA51[i].isFree) {
318       strcat (regsFreed, regsXA51[i].name);
319       strcat (regsFreed, " ");
320       regsXA51[i].isFree=1;
321       regsXA51[i].sym=NULL;
322       nfr++;
323     }
324   }
325   xa51RegsInUse=0;
326   if (nfr) {
327     fprintf (stderr, "freeAllRegisters: %d regs freed (%s)\n", nfr, regsFreed);
328     exit (1);
329   }
330 }
331
332 /*-----------------------------------------------------------------*/
333 /* computeSpillable - given a point find the spillable live ranges */
334 /*-----------------------------------------------------------------*/
335 static bitVect *computeSpillable (iCode * ic) {
336   bitVect *spillable;
337   
338   /* spillable live ranges are those that are live at this 
339      point . the following categories need to be subtracted
340      from this set. 
341      a) - those that are already spilt
342      b) - if being used by this one
343      c) - defined by this one */
344   
345   spillable = bitVectCopy (ic->rlive);
346   spillable =
347     bitVectCplAnd (spillable, _G.spiltSet);     /* those already spilt */
348   spillable =
349     bitVectCplAnd (spillable, ic->uses);        /* used in this one */
350   bitVectUnSetBit (spillable, ic->defKey);      /* defined by this one */
351   spillable = bitVectIntersect (spillable, _G.regAssigned);
352   return spillable;
353   
354 }
355
356 /*-----------------------------------------------------------------*/
357 /* noSpilLoc - return true if a variable has no spil location      */
358 /*-----------------------------------------------------------------*/
359 static int
360 noSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
361 {
362   return (sym->usl.spillLoc ? 0 : 1);
363 }
364
365 /*-----------------------------------------------------------------*/
366 /* hasSpilLoc - will return 1 if the symbol has spil location      */
367 /*-----------------------------------------------------------------*/
368 static int
369 hasSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
370 {
371   return (sym->usl.spillLoc ? 1 : 0);
372 }
373
374 /*-----------------------------------------------------------------*/
375 /* hasSpilLocnoUptr - will return 1 if the symbol has spil location */
376 /*                    but is not used as a pointer                 */
377 /*-----------------------------------------------------------------*/
378 static int
379 hasSpilLocnoUptr (symbol * sym, eBBlock * ebp, iCode * ic)
380 {
381   return ((sym->usl.spillLoc && !sym->uptr) ? 1 : 0);
382 }
383
384 /*-----------------------------------------------------------------*/
385 /* rematable - will return 1 if the remat flag is set              */
386 /*-----------------------------------------------------------------*/
387 static int
388 rematable (symbol * sym, eBBlock * ebp, iCode * ic)
389 {
390   return sym->remat;
391 }
392
393 /*-----------------------------------------------------------------*/
394 /* notUsedInRemaining - not used or defined in remain of the block */
395 /*-----------------------------------------------------------------*/
396 static int
397 notUsedInRemaining (symbol * sym, eBBlock * ebp, iCode * ic)
398 {
399   return ((usedInRemaining (operandFromSymbol (sym), ic) ? 0 : 1) &&
400           allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq));
401 }
402
403 /*-----------------------------------------------------------------*/
404 /* allLRs - return true for all                                    */
405 /*-----------------------------------------------------------------*/
406 static int
407 allLRs (symbol * sym, eBBlock * ebp, iCode * ic)
408 {
409   return 1;
410 }
411
412 /*-----------------------------------------------------------------*/
413 /* liveRangesWith - applies function to a given set of live range  */
414 /*-----------------------------------------------------------------*/
415 static set *
416 liveRangesWith (bitVect * lrs, int (func) (symbol *, eBBlock *, iCode *),
417                 eBBlock * ebp, iCode * ic)
418 {
419   set *rset = NULL;
420   int i;
421   
422   if (!lrs || !lrs->size)
423     return NULL;
424   
425   for (i = 1; i < lrs->size; i++)
426     {
427       symbol *sym;
428       if (!bitVectBitValue (lrs, i))
429         continue;
430       
431       /* if we don't find it in the live range 
432          hash table we are in serious trouble */
433       if (!(sym = hTabItemWithKey (liveRanges, i)))
434         {
435           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
436                   "liveRangesWith could not find liveRange");
437           exit (1);
438         }
439       
440       if (func (sym, ebp, ic) && bitVectBitValue (_G.regAssigned, sym->key))
441         addSetHead (&rset, sym);
442     }
443   
444   return rset;
445 }
446
447
448 /*-----------------------------------------------------------------*/
449 /* leastUsedLR - given a set determines which is the least used    */
450 /*-----------------------------------------------------------------*/
451 static symbol *
452 leastUsedLR (set * sset)
453 {
454   symbol *sym = NULL, *lsym = NULL;
455   
456   sym = lsym = setFirstItem (sset);
457   
458   if (!lsym)
459     return NULL;
460   
461   for (; lsym; lsym = setNextItem (sset))
462     {
463       
464       /* if usage is the same then prefer
465          the spill the smaller of the two */
466       if (lsym->used == sym->used)
467         if (getSize (lsym->type) < getSize (sym->type))
468           sym = lsym;
469       
470       /* if less usage */
471       if (lsym->used < sym->used)
472         sym = lsym;
473       
474     }
475   
476   setToNull ((void *) &sset);
477   sym->blockSpil = 0;
478   return sym;
479 }
480
481 /*-----------------------------------------------------------------*/
482 /* noOverLap - will iterate through the list looking for over lap  */
483 /*-----------------------------------------------------------------*/
484 static int
485 noOverLap (set * itmpStack, symbol * fsym)
486 {
487   symbol *sym;
488   
489   
490   for (sym = setFirstItem (itmpStack); sym;
491        sym = setNextItem (itmpStack))
492     {
493       if (bitVectBitValue(sym->clashes,fsym->key)) return 0;
494     }
495   
496   return 1;
497 }
498
499 /*-----------------------------------------------------------------*/
500 /* isFree - will return 1 if the a free spil location is found     */
501 /*-----------------------------------------------------------------*/
502 static DEFSETFUNC (isFree) {
503   symbol *sym = item;
504   V_ARG (symbol **, sloc);
505   V_ARG (symbol *, fsym);
506   
507   /* if already found */
508   if (*sloc)
509     return 0;
510   
511   /* if it is free && and the itmp assigned to
512      this does not have any overlapping live ranges
513      with the one currently being assigned and
514      the size can be accomodated  */
515   if (sym->isFree &&
516       noOverLap (sym->usl.itmpStack, fsym) &&
517       /* TODO: this is a waste but causes to many problems 
518          getSize (sym->type) >= getSize (fsym->type)) {
519       */
520       getSize (sym->type) == getSize (fsym->type)) {
521     *sloc = sym;
522     return 1;
523   }
524   
525   return 0;
526 }
527
528 /*-----------------------------------------------------------------*/
529 /* createStackSpil - create a location on the stack to spil        */
530 /*-----------------------------------------------------------------*/
531 static symbol *
532 createStackSpil (symbol * sym)
533 {
534   symbol *sloc = NULL;
535   char slocBuffer[30];
536   
537   D1(fprintf (stderr, "  createStackSpil for %s\n", sym->name));
538   
539   /* first go try and find a free one that is already 
540      existing on the stack */
541   if (applyToSet (_G.stackSpil, isFree, &sloc, sym))
542     {
543       /* found a free one : just update & return */
544       sym->usl.spillLoc = sloc;
545       sym->stackSpil = 1;
546       sloc->isFree = 0;
547       addSetHead (&sloc->usl.itmpStack, sym);
548       D1(fprintf (stderr, "    using existing %s\n", sloc->name));
549       return sym;
550     }
551   
552   sprintf (slocBuffer, "sloc%d", _G.slocNum++);
553   sloc = newiTemp (slocBuffer);
554   
555   /* set the type to the spilling symbol */
556   sloc->type = copyLinkChain (sym->type);
557   sloc->etype = getSpec (sloc->type);
558   SPEC_SCLS (sloc->etype) = S_STACK;
559   SPEC_EXTR (sloc->etype) = 0;
560   SPEC_STAT (sloc->etype) = 0;
561   SPEC_VOLATILE(sloc->etype) = 0;
562   SPEC_ABSA(sloc->etype) = 0;
563   
564   allocLocal (sloc);
565   
566   sloc->isref = 1;              /* to prevent compiler warning */
567   
568   currFunc->stack += getSize (sloc->type);
569   _G.stackExtend += getSize (sloc->type);
570   
571   /* add it to the _G.stackSpil set */
572   addSetHead (&_G.stackSpil, sloc);
573   sym->usl.spillLoc = sloc;
574   sym->stackSpil = 1;
575   
576   /* add it to the set of itempStack set 
577      of the spill location */
578   addSetHead (&sloc->usl.itmpStack, sym);
579   return sym;
580 }
581
582 /*-----------------------------------------------------------------*/
583 /* spillThis - spils a specific operand                            */
584 /*-----------------------------------------------------------------*/
585 static void
586 spillThis (symbol * sym)
587 {
588   int i;
589   
590   D1(fprintf (stderr, "  spillThis: %s\n", sym->name));
591   
592   /* if this is rematerializable or has a spillLocation
593      we are okay, else we need to create a spillLocation
594      for it */
595   if (!(sym->remat || sym->usl.spillLoc))
596     createStackSpil (sym);
597   
598   
599   /* mark it has spilt & put it in the spilt set */
600   sym->isspilt = sym->spillA = 1;
601   _G.spiltSet = bitVectSetBit (_G.spiltSet, sym->key);
602   
603   bitVectUnSetBit (_G.regAssigned, sym->key);
604   bitVectUnSetBit (_G.totRegAssigned, sym->key);
605   
606   for (i = 0; i < sym->nRegs; i++)
607     
608     if (sym->regs[i])
609       {
610         freeReg (sym->regs[i], FALSE);
611       }
612   
613   if (sym->usl.spillLoc && !sym->remat)
614     sym->usl.spillLoc->allocreq++;
615   return;
616 }
617
618 /*-----------------------------------------------------------------*/
619 /* selectSpil - select a iTemp to spil : rather a simple procedure */
620 /*-----------------------------------------------------------------*/
621 static symbol *
622 selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
623 {
624   bitVect *lrcs = NULL;
625   set *selectS;
626   symbol *sym;
627   
628   /* get the spillable live ranges */
629   lrcs = computeSpillable (ic);
630   
631   /* get all live ranges that are rematerizable */
632   if ((selectS = liveRangesWith (lrcs, rematable, ebp, ic)))
633     {
634       /* return the least used of these */
635       return leastUsedLR (selectS);
636     }
637   
638   /* if the symbol is local to the block then */
639   if (forSym->liveTo < ebp->lSeq)
640     {
641       
642       /* check if there are any live ranges allocated
643          to registers that are not used in this block */
644       if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInBlock, ebp, ic)))
645         {
646           sym = leastUsedLR (selectS);
647           /* if this is not rematerializable */
648           if (!sym->remat)
649             {
650               _G.blockSpil++;
651               sym->blockSpil = 1;
652             }
653           return sym;
654         }
655       
656       /* check if there are any live ranges that not
657          used in the remainder of the block */
658       if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInRemaining, ebp, ic)))
659         {
660           sym = leastUsedLR (selectS);
661           if (sym != forSym)
662             {
663               if (!sym->remat)
664                 {
665                   sym->remainSpil = 1;
666                   _G.blockSpil++;
667                 }
668               return sym;
669             }
670         }
671     }
672   
673   /* find live ranges with spillocation && not used as pointers */
674   if ((selectS = liveRangesWith (lrcs, hasSpilLocnoUptr, ebp, ic)))
675     {
676       
677       sym = leastUsedLR (selectS);
678       /* mark this as allocation required */
679       sym->usl.spillLoc->allocreq++;
680       return sym;
681     }
682   
683   /* find live ranges with spillocation */
684   if ((selectS = liveRangesWith (lrcs, hasSpilLoc, ebp, ic)))
685     {
686       
687       sym = leastUsedLR (selectS);
688       sym->usl.spillLoc->allocreq++;
689       return sym;
690     }
691   
692   /* couldn't find then we need to create a spil
693      location on the stack , for which one? the least
694      used ofcourse */
695   if ((selectS = liveRangesWith (lrcs, noSpilLoc, ebp, ic)))
696     {
697       
698       /* return a created spil location */
699       sym = createStackSpil (leastUsedLR (selectS));
700       sym->usl.spillLoc->allocreq++;
701       return sym;
702     }
703   
704   /* this is an extreme situation we will spill
705      this one : happens very rarely but it does happen */
706   spillThis (forSym);
707   return forSym;
708 }
709
710 /*-----------------------------------------------------------------*/
711 /* spillSomething - spil some variable & mark registers as free    */
712 /*-----------------------------------------------------------------*/
713 static bool
714 spillSomething (iCode * ic, eBBlock * ebp, symbol * forSym)
715 {
716   symbol *ssym;
717   int i;
718   
719   /* get something we can spil */
720   ssym = selectSpil (ic, ebp, forSym);
721   
722   D1(fprintf (stderr, "  spillSomething: spilling %s\n", ssym->name));
723   
724   /* mark it as spilt */
725   ssym->isspilt = ssym->spillA = 1;
726   _G.spiltSet = bitVectSetBit (_G.spiltSet, ssym->key);
727   
728   /* mark it as not register assigned &
729      take it away from the set */
730   //bitVectUnSetBit (_G.regAssigned, ssym->key);
731   //bitVectUnSetBit (_G.totRegAssigned, ssym->key);
732   
733   /* mark the registers as free */
734   for (i = 0; i < ssym->nRegs; i++) {
735     if (ssym->regs[i]) {
736       freeReg (ssym->regs[i], FALSE);
737       // dont NULL ssym->regs[i], it might be used later
738     }
739   }
740   
741   /* if this was a block level spil then insert push & pop 
742      at the start & end of block respectively */
743   if (ssym->blockSpil)
744     {
745       iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL);
746       /* add push to the start of the block */
747       addiCodeToeBBlock (ebp, nic, (ebp->sch->op == LABEL ?
748                                     ebp->sch->next : ebp->sch));
749       nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
750       /* add pop to the end of the block */
751       addiCodeToeBBlock (ebp, nic, NULL);
752     }
753   
754   /* if spilt because not used in the remainder of the
755      block then add a push before this instruction and
756      a pop at the end of the block */
757   if (ssym->remainSpil)
758     {
759       
760       iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL);
761       /* add push just before this instruction */
762       addiCodeToeBBlock (ebp, nic, ic);
763       
764       nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
765       /* add pop to the end of the block */
766       addiCodeToeBBlock (ebp, nic, NULL);
767     }
768   
769   if (ssym == forSym)
770     return FALSE;
771   else
772     return TRUE;
773 }
774
775 /*-----------------------------------------------------------------*/
776 /* getRegPtr - will try for PTR if not a GPR type if not spil      */
777 /*-----------------------------------------------------------------*/
778 static bool getRegPtr (iCode * ic, eBBlock * ebp, symbol * sym, short offset) {
779   
780   D0(fprintf (stderr, "getRegPtr: %s ", sym->name));
781   D0(printTypeChain(sym->type, stderr));
782   D0(fprintf (stderr, "\n"));
783   
784   while (1) {
785     /* this looks like an infinite loop but 
786        in really selectSpil will abort  */
787     
788     /* try for a ptr type */
789     if (allocReg (getSize(sym->type), REG_PTR, sym, offset, FALSE))
790       return TRUE;
791     
792     /* try for gpr type */
793     if (xa51HasGprRegs && allocReg (getSize(sym->type), 
794                                     REG_GPR, sym, offset, FALSE))
795       return TRUE;
796     
797     /* we have to spil */
798     if (!spillSomething (ic, ebp, sym))
799       return FALSE;
800     
801   }
802 }
803
804 /*-----------------------------------------------------------------*/
805 /* getRegGpr - will try for GPR if not spil                        */
806 /*-----------------------------------------------------------------*/
807 static bool getRegGpr (iCode * ic, eBBlock * ebp, symbol * sym, short offset) {
808   
809   D0(fprintf (stderr, "getRegGpr: %s ", sym->name));
810   D0(printTypeChain(sym->type, stderr));
811   D0(fprintf (stderr, "\n"));
812   
813   while(1) {
814     /* this looks like an infinite loop but 
815        in really selectSpil will abort  */
816     
817     /* try for gpr type */
818     if (xa51HasGprRegs && allocReg (getSize(sym->type), 
819                                     REG_GPR, sym, offset, FALSE))
820       return TRUE;
821     
822     if (allocReg (getSize(sym->type), REG_PTR, sym, offset, FALSE))
823       return TRUE;
824     
825     /* we have to spil */
826     if (!spillSomething (ic, ebp, sym))
827       return FALSE;
828   }
829 }
830
831 /*-----------------------------------------------------------------*/
832 /* deassignLRs - check the live to and if they have registers & are */
833 /*               not spilt then free up the registers              */
834 /*-----------------------------------------------------------------*/
835 static void
836 deassignLRs (iCode * ic, eBBlock * ebp)
837 {
838   symbol *sym;
839   int k;
840   
841   for (sym = hTabFirstItem (liveRanges, &k); sym;
842        sym = hTabNextItem (liveRanges, &k))
843     {
844       /* if it does not end here */
845       if (sym->liveTo > ic->seq)
846         continue;
847       
848       /* if it was spilt on stack then we can 
849          mark the stack spil location as free */
850       if (sym->isspilt)
851         {
852           if (sym->stackSpil)
853             {
854               sym->usl.spillLoc->isFree = 1;
855               sym->stackSpil = 0;
856             }
857           continue;
858         }
859       
860       if (!bitVectBitValue (_G.regAssigned, sym->key))
861         continue;
862       
863       if (sym->nRegs) {
864         int i;
865         
866         bitVectUnSetBit (_G.regAssigned, sym->key);
867         
868         /* free the regs */
869         for (i=0; i < sym->nRegs; i++) {
870           freeReg (sym->regs[i], FALSE);
871         }
872       }
873     }
874 }
875
876 /*-----------------------------------------------------------------*/
877 /* willCauseSpill - determines if allocating will cause a spill    */
878 /*-----------------------------------------------------------------*/
879 static bool willCauseSpill (symbol *sym) {
880   int i;
881   // do it the rude way
882   if (allocReg (getSize(sym->type), sym->regType, sym, 0, TRUE) ||
883       allocReg (getSize(sym->type), sym->regType==REG_PTR?REG_GPR:REG_PTR, 
884                 sym, 0, TRUE)) {
885     // so we can, but we won't
886     for (i=0; i<sym->nRegs; i++) {
887       freeReg (sym->regs[i], TRUE);
888       sym->regs[i]=NULL;
889     }
890     return FALSE;
891   }
892   D1(fprintf (stderr, "  %s will cause a spill\n", sym->name));
893   return TRUE;
894 }
895
896 /*-----------------------------------------------------------------*/
897 /* positionRegs - the allocator can allocate same registers to res- */
898 /* ult and operand, if this happens make sure they are in the same */
899 /* position as the operand otherwise chaos results                 */
900 /*-----------------------------------------------------------------*/
901 static int
902 positionRegs (symbol * result, symbol * opsym)
903 {
904   int count = min (result->nRegs, opsym->nRegs);
905   int i, j = 0, shared = 0;
906   int changed = 0;
907   
908   /* if the result has been spilt then cannot share */
909   if (opsym->isspilt)
910     return 0;
911  again:
912   shared = 0;
913   /* first make sure that they actually share */
914   for (i = 0; i < count; i++)
915     {
916       for (j = 0; j < count; j++)
917         {
918           if (result->regs[i] == opsym->regs[j] && i != j)
919             {
920               shared = 1;
921               goto xchgPositions;
922             }
923         }
924     }
925  xchgPositions:
926   if (shared)
927     {
928       regs *tmp = result->regs[i];
929       result->regs[i] = result->regs[j];
930       result->regs[j] = tmp;
931       changed ++;
932       D2(fprintf (stderr, "positionRegs: rearranged regs for %s and %s\n",
933                   result->name, opsym->name));
934       goto again;
935     }
936   return changed;
937 }
938
939 /*-----------------------------------------------------------------*/
940 /* serialRegAssign - serially allocate registers to the variables  */
941 /*-----------------------------------------------------------------*/
942 static void
943 serialRegAssign (eBBlock ** ebbs, int count)
944 {
945   int i;
946   
947   /* for all blocks */
948   for (i = 0; i < count; i++) {
949     
950     iCode *ic;
951     
952     if (ebbs[i]->noPath &&
953         (ebbs[i]->entryLabel != entryLabel &&
954          ebbs[i]->entryLabel != returnLabel))
955       continue;
956     
957     /* of all instructions do */
958     for (ic = ebbs[i]->sch; ic; ic = ic->next) {
959       
960       /* if result is present && is a true symbol */
961       if (IC_RESULT (ic) && ic->op != IFX &&
962           IS_TRUE_SYMOP (IC_RESULT (ic))) {
963         OP_SYMBOL (IC_RESULT (ic))->allocreq++;
964       }
965       
966       /* take away registers from live
967          ranges that end at this instruction */
968       deassignLRs (ic, ebbs[i]);
969       
970       /* some don't need registers */
971       if (SKIP_IC2 (ic) ||
972           ic->op == JUMPTABLE ||
973           ic->op == IFX ||
974           ic->op == IPUSH ||
975           ic->op == IPOP ||
976           (IC_RESULT (ic) && POINTER_SET (ic)))
977         continue;
978       
979       /* now we need to allocate registers
980          only for the result */
981       if (IC_RESULT (ic)) {
982         symbol *sym = OP_SYMBOL (IC_RESULT (ic));
983         bitVect *spillable;
984         int willCS;
985         
986         /* if it does not need or is spilt 
987            or is already assigned to registers
988            or will not live beyond this instructions */
989         if (!sym->nRegs ||
990             sym->isspilt ||
991             bitVectBitValue (_G.regAssigned, sym->key) ||
992             sym->liveTo <= ic->seq)
993           continue;
994         
995         /* if some liverange has been spilt at the block level
996            and this one live beyond this block then spil this
997            to be safe */
998         if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq) {
999           spillThis (sym);
1000           continue;
1001         }
1002         /* if trying to allocate this will cause
1003            a spill and there is nothing to spill 
1004            or this one is rematerializable then
1005            spill this one */
1006         willCS = willCauseSpill (sym);
1007         spillable = computeSpillable (ic);
1008         if (sym->remat || (willCS && bitVectIsZero (spillable))) {                    
1009           spillThis (sym);
1010           continue;                   
1011         }
1012         
1013         /* If the live range preceeds the point of definition 
1014            then ideally we must take into account registers that 
1015            have been allocated after sym->liveFrom but freed
1016            before ic->seq. This is complicated, so spill this
1017            symbol instead and let fillGaps handle the allocation. */
1018         if (sym->liveFrom < ic->seq) {
1019             spillThis (sym);
1020             continue;                 
1021         }
1022         
1023         /* if it has a spillocation & is used less than
1024            all other live ranges then spill this */
1025         if (willCS) {
1026           if (sym->usl.spillLoc) {
1027             symbol *leastUsed = leastUsedLR (liveRangesWith (spillable,
1028                                                              allLRs, ebbs[i], ic));
1029             if (leastUsed && leastUsed->used > sym->used) {
1030               spillThis (sym);
1031               continue;
1032             }
1033           } else {
1034             /* if none of the liveRanges have a spillLocation then better
1035                to spill this one than anything else already assigned to registers */
1036             if (liveRangesWith(spillable,noSpilLoc,ebbs[i],ic)) {
1037               /* if this is local to this block then we might find a block spil */
1038               if (!(sym->liveFrom >= ebbs[i]->fSeq && sym->liveTo <= ebbs[i]->lSeq)) {
1039                 spillThis (sym);
1040                 continue;
1041               }
1042             }
1043           }
1044         }
1045         
1046         /* else we assign registers to it */
1047         _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
1048         _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, sym->key);
1049         
1050         if (sym->regType == REG_PTR)
1051           getRegPtr (ic, ebbs[i], sym, 0);
1052         else
1053           getRegGpr (ic, ebbs[i], sym, 0);
1054         
1055         /* if it shares registers with operands make sure
1056            that they are in the same position */
1057         if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) &&
1058             OP_SYMBOL (IC_LEFT (ic))->nRegs && ic->op != '=') {
1059           positionRegs (OP_SYMBOL (IC_RESULT (ic)),
1060                         OP_SYMBOL (IC_LEFT (ic)));
1061         }
1062         /* do the same for the right operand */
1063         if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) &&
1064             OP_SYMBOL (IC_RIGHT (ic))->nRegs) {
1065           positionRegs (OP_SYMBOL (IC_RESULT (ic)),
1066                         OP_SYMBOL (IC_RIGHT (ic)));
1067         }
1068       }
1069     }
1070   }
1071 }
1072
1073 /*-----------------------------------------------------------------*/
1074 /* rUmaskForOp :- returns register mask for an operand             */
1075 /*-----------------------------------------------------------------*/
1076 bitVect *xa51_rUmaskForOp (operand * op) {
1077   bitVect *rumask;
1078   symbol *sym;
1079   int j;
1080   
1081   /* only temporaries are assigned registers */
1082   if (!IS_ITEMP (op))
1083     return NULL;
1084   
1085   sym = OP_SYMBOL (op);
1086   
1087   /* if spilt or no registers assigned to it 
1088      then nothing */
1089   if (sym->isspilt || !sym->nRegs || !sym->regs[0])
1090     return NULL;
1091   
1092   rumask = newBitVect (xa51_nRegs);
1093   
1094   for (j = 0; j < sym->nRegs; j++) {
1095     rumask = bitVectSetBit (rumask,
1096                             sym->regs[j]->rIdx);
1097   }
1098   return rumask;
1099 }
1100
1101 /*-----------------------------------------------------------------*/
1102 /* regsUsedIniCode :- returns bit vector of registers used in iCode */
1103 /*-----------------------------------------------------------------*/
1104 static bitVect *
1105 regsUsedIniCode (iCode * ic)
1106 {
1107   bitVect *rmask = newBitVect (xa51_nRegs);
1108   
1109   /* do the special cases first */
1110   if (ic->op == IFX)
1111     {
1112       rmask = bitVectUnion (rmask,
1113                             xa51_rUmaskForOp (IC_COND (ic)));
1114       goto ret;
1115     }
1116   
1117   /* for the jumptable */
1118   if (ic->op == JUMPTABLE)
1119     {
1120       rmask = bitVectUnion (rmask,
1121                             xa51_rUmaskForOp (IC_JTCOND (ic)));
1122       
1123       goto ret;
1124     }
1125   
1126   /* of all other cases */
1127   if (IC_LEFT (ic))
1128     rmask = bitVectUnion (rmask,
1129                           xa51_rUmaskForOp (IC_LEFT (ic)));
1130   
1131   
1132   if (IC_RIGHT (ic))
1133     rmask = bitVectUnion (rmask,
1134                           xa51_rUmaskForOp (IC_RIGHT (ic)));
1135   
1136   if (IC_RESULT (ic))
1137     rmask = bitVectUnion (rmask,
1138                           xa51_rUmaskForOp (IC_RESULT (ic)));
1139   
1140  ret:
1141   return rmask;
1142 }
1143
1144 /*-----------------------------------------------------------------*/
1145 /* createRegMask - for each instruction will determine the regsUsed */
1146 /*-----------------------------------------------------------------*/
1147 static void
1148 createRegMask (eBBlock ** ebbs, int count)
1149 {
1150   int i;
1151   
1152   /* for all blocks */
1153   for (i = 0; i < count; i++)
1154     {
1155       iCode *ic;
1156       
1157       if (ebbs[i]->noPath &&
1158           (ebbs[i]->entryLabel != entryLabel &&
1159            ebbs[i]->entryLabel != returnLabel))
1160         continue;
1161       
1162       /* for all instructions */
1163       for (ic = ebbs[i]->sch; ic; ic = ic->next)
1164         {
1165           
1166           int j;
1167           
1168           if (SKIP_IC2 (ic) || !ic->rlive)
1169             continue;
1170           
1171           /* first mark the registers used in this
1172              instruction */
1173           ic->rUsed = regsUsedIniCode (ic);
1174           _G.funcrUsed = bitVectUnion (_G.funcrUsed, ic->rUsed);
1175           
1176           /* now create the register mask for those 
1177              registers that are in use : this is a
1178              super set of ic->rUsed */
1179           ic->rMask = newBitVect (xa51_nRegs + 1);
1180           
1181           /* for all live Ranges alive at this point */
1182           for (j = 1; j < ic->rlive->size; j++)
1183             {
1184               symbol *sym;
1185               int k;
1186               
1187               /* if not alive then continue */
1188               if (!bitVectBitValue (ic->rlive, j))
1189                 continue;
1190               
1191               /* find the live range we are interested in */
1192               if (!(sym = hTabItemWithKey (liveRanges, j)))
1193                 {
1194                   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1195                           "createRegMask cannot find live range");
1196                   exit (0);
1197                 }
1198               
1199               /* if no register assigned to it */
1200               if (!sym->nRegs || sym->isspilt)
1201                 continue;
1202               
1203               /* for all the registers allocated to it */
1204               for (k = 0; k < sym->nRegs; k++)
1205                 if (sym->regs[k])
1206                   ic->rMask =
1207                     bitVectSetBit (ic->rMask, sym->regs[k]->rIdx);
1208             }
1209         }
1210     }
1211 }
1212
1213 /*-----------------------------------------------------------------*/
1214 /* rematStr - returns the rematerialized string for a remat var    */
1215 /*-----------------------------------------------------------------*/
1216 static char *
1217 rematStr (symbol * sym)
1218 {
1219   char *s = buffer;
1220   iCode *ic = sym->rematiCode;
1221   
1222   while (1)
1223     {
1224       
1225       /* if plus or minus print the right hand side */
1226       if (ic->op == '+' || ic->op == '-')
1227         {
1228           sprintf (s, "0x%04x %c ", (int) operandLitValue (IC_RIGHT (ic)),
1229                    ic->op);
1230           s += strlen (s);
1231           ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
1232           continue;
1233         }
1234       
1235       /* cast then continue */
1236       if (IS_CAST_ICODE(ic)) {
1237         ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1238         continue;
1239       }
1240       /* we reached the end */
1241       sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
1242       break;
1243     }
1244   
1245   return buffer;
1246 }
1247
1248 /*-----------------------------------------------------------------*/
1249 /* regTypeNum - computes the type & number of registers required   */
1250 /*-----------------------------------------------------------------*/
1251 static void
1252 regTypeNum (eBBlock *ebbs)
1253 {
1254   symbol *sym;
1255   int k;
1256   iCode *ic;
1257   
1258   /* for each live range do */
1259   for (sym = hTabFirstItem (liveRanges, &k); sym;
1260        sym = hTabNextItem (liveRanges, &k))
1261     {
1262       
1263       /* if used zero times then no registers needed */
1264       if ((sym->liveTo - sym->liveFrom) == 0)
1265         continue;
1266       
1267       
1268       /* if the live range is a temporary */
1269       if (sym->isitmp)
1270         {
1271           
1272           /* if the type is marked as a conditional */
1273           if (sym->regType == REG_CND)
1274             continue;
1275           
1276           /* if used in return only then we don't 
1277              need registers */
1278 #if 0 // not yet
1279           if (sym->ruonly || sym->accuse)
1280             {
1281               if (IS_AGGREGATE (sym->type) || sym->isptr)
1282                 sym->type = aggrToPtr (sym->type, FALSE);
1283               continue;
1284             }
1285 #endif
1286           
1287           /* if the symbol has only one definition &
1288              that definition is a get_pointer */
1289           if (bitVectnBitsOn (sym->defs) == 1 &&
1290               (ic = hTabItemWithKey (iCodehTab,
1291                                      bitVectFirstBit (sym->defs))) &&
1292               POINTER_GET (ic) &&
1293               !sym->noSpilLoc &&
1294               !IS_BITVAR (sym->etype))
1295             {
1296               /* and that pointer is remat in data space */
1297               if (OP_SYMBOL (IC_LEFT (ic))->remat &&
1298                   !IS_CAST_ICODE(OP_SYMBOL (IC_LEFT (ic))->rematiCode) &&
1299                   DCL_TYPE (aggrToPtr (operandType(IC_LEFT(ic)), FALSE)) == POINTER)
1300                 {
1301                   /* create a psuedo symbol & force a spil */
1302                   symbol *psym = newSymbol (rematStr (OP_SYMBOL (IC_LEFT (ic))), 1);
1303                   psym->type = sym->type;
1304                   psym->etype = sym->etype;
1305                   strcpy (psym->rname, psym->name);
1306                   sym->isspilt = 1;
1307                   sym->usl.spillLoc = psym;
1308 #if 0 // an alternative fix for bug #480076
1309                   /* now this is a useless assignment to itself */
1310                   remiCodeFromeBBlock (ebbs, ic);
1311 #else
1312                   /* now this really is an assignment to itself, make it so;
1313                      it will be optimized out later */
1314                   ic->op='=';
1315                   IC_RIGHT(ic)=IC_RESULT(ic);
1316                   IC_LEFT(ic)=NULL;
1317 #endif
1318                   continue;
1319                 }
1320               
1321               /* if in data space or idata space then try to
1322                  allocate pointer register */
1323               
1324             }
1325           
1326           /* if not then we require registers */
1327 #if 0
1328           sym->nRegs = ((IS_AGGREGATE (sym->type) || sym->isptr) ?
1329                         getSize (sym->type = aggrToPtr (sym->type, FALSE)) :
1330                         getSize (sym->type));
1331 #else
1332           {
1333             int size=((IS_AGGREGATE (sym->type) || sym->isptr) ?
1334                       getSize (sym->type = aggrToPtr (sym->type, FALSE)) :
1335                       getSize (sym->type));
1336             switch (size) 
1337               {
1338               case 1: // byte
1339               case 2: // word or pointer
1340                 sym->nRegs=1;
1341                 break;
1342               case 3: // generic pointer
1343                 sym->nRegs=2;
1344                 break;
1345               case 4: // dword or float
1346                 sym->nRegs=2;
1347                 break;
1348               default: 
1349                 fprintf (stderr, "regTypeNum: unknown size\n");
1350                 exit (1);
1351               }
1352           }
1353 #endif
1354           
1355           if (sym->nRegs > 4)
1356             {
1357               fprintf (stderr, "allocated more than 4 or 0 registers for type ");
1358               printTypeChain (sym->type, stderr);
1359               fprintf (stderr, "\n");
1360               exit (1);
1361             }
1362           
1363           /* determine the type of register required */
1364           if (IS_PTR (sym->type))
1365             sym->regType = REG_PTR;
1366           else
1367             sym->regType = REG_GPR;
1368           
1369         }
1370       else
1371         /* for the first run we don't provide */
1372         /* registers for true symbols we will */
1373         /* see how things go                  */
1374         sym->nRegs = 0;
1375     }
1376   
1377 }
1378
1379 /*-----------------------------------------------------------------*/
1380 /* deallocStackSpil - this will set the stack pointer back         */
1381 /*-----------------------------------------------------------------*/
1382 static
1383 DEFSETFUNC (deallocStackSpil)
1384 {
1385   symbol *sym = item;
1386   
1387   deallocLocal (sym);
1388   return 0;
1389 }
1390
1391 /*-----------------------------------------------------------------*/
1392 /* packRegsForAssign - register reduction for assignment           */
1393 /*-----------------------------------------------------------------*/
1394 static int
1395 packRegsForAssign (iCode * ic, eBBlock * ebp)
1396 {
1397   iCode *dic, *sic;
1398   
1399   if (!IS_ITEMP (IC_RIGHT (ic)) ||
1400       OP_LIVETO (IC_RIGHT (ic)) > ic->seq) {
1401     return 0;
1402   }
1403
1404   /* find the definition of iTempNN scanning backwards */
1405   for (dic = ic->prev; dic; dic = dic->prev) {
1406     
1407     /* if there is a function call then don't pack it */
1408     if ((dic->op == CALL || dic->op == PCALL)) {
1409       dic = NULL;
1410       break;
1411     }
1412     
1413     if (SKIP_IC2 (dic))
1414       continue;
1415     
1416     if (IS_SYMOP (IC_RESULT (dic)) &&
1417         IC_RESULT (dic)->key == IC_RIGHT (ic)->key) {
1418       break;
1419     }
1420     
1421   }
1422   
1423   if (!dic)
1424     return 0;                   /* did not find */
1425
1426   /* found the definition */
1427   /* replace the result with the result of */
1428   /* this assignment and remove this assignment */
1429   bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
1430   IC_RESULT (dic) = IC_RESULT (ic);
1431   
1432   if (IS_ITEMP (IC_RESULT (dic)) && 
1433       OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq)
1434     {
1435       OP_SYMBOL (IC_RESULT (dic))->liveFrom = dic->seq;
1436     }
1437   /* delete from liverange table also 
1438      delete from all the points inbetween and the new
1439      one */
1440   for (sic = dic; sic != ic; sic = sic->next)
1441     {
1442       bitVectUnSetBit (sic->rlive, IC_RESULT (ic)->key);
1443       if (IS_ITEMP (IC_RESULT (dic)))
1444         bitVectSetBit (sic->rlive, IC_RESULT (dic)->key);
1445     }
1446   
1447   remiCodeFromeBBlock (ebp, ic);
1448   bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
1449   hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
1450   OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
1451   return 1;
1452   
1453 }
1454
1455 /*-----------------------------------------------------------------*/
1456 /* findAssignToSym : scanning backwards looks for first assig found */
1457 /*-----------------------------------------------------------------*/
1458 static iCode *
1459 findAssignToSym (operand * op, iCode * ic)
1460 {
1461   iCode *dic;
1462   
1463   for (dic = ic->prev; dic; dic = dic->prev)
1464     {
1465       
1466       /* if definition by assignment */
1467       if (dic->op == '=' &&
1468           !POINTER_SET (dic) &&
1469           IC_RESULT (dic)->key == op->key
1470           /*          &&  IS_TRUE_SYMOP(IC_RIGHT(dic)) */
1471           )
1472         {
1473           
1474           /* we are interested only if defined in far space */
1475           /* or in stack space in case of + & - */
1476           
1477           /* if assigned to a non-symbol then return
1478              FALSE */
1479           if (!IS_SYMOP (IC_RIGHT (dic)))
1480             return NULL;
1481           
1482           /* if the symbol is in far space then
1483              we should not */
1484           if (isOperandInFarSpace (IC_RIGHT (dic)))
1485             return NULL;
1486           
1487           /* for + & - operations make sure that
1488              if it is on the stack it is the same
1489              as one of the three operands */
1490           if ((ic->op == '+' || ic->op == '-') &&
1491               OP_SYMBOL (IC_RIGHT (dic))->onStack)
1492             {
1493               
1494               if (IC_RESULT (ic)->key != IC_RIGHT (dic)->key &&
1495                   IC_LEFT (ic)->key != IC_RIGHT (dic)->key &&
1496                   IC_RIGHT (ic)->key != IC_RIGHT (dic)->key)
1497                 return NULL;
1498             }
1499           
1500           break;
1501           
1502         }
1503       
1504       /* if we find an usage then we cannot delete it */
1505       if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key)
1506         return NULL;
1507       
1508       if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key)
1509         return NULL;
1510       
1511       if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key)
1512         return NULL;
1513     }
1514   
1515   /* now make sure that the right side of dic
1516      is not defined between ic & dic */
1517   if (dic)
1518     {
1519       iCode *sic = dic->next;
1520       
1521       for (; sic != ic; sic = sic->next)
1522         if (IC_RESULT (sic) &&
1523             IC_RESULT (sic)->key == IC_RIGHT (dic)->key)
1524           return NULL;
1525     }
1526   
1527   return dic;
1528   
1529   
1530 }
1531
1532 /*-----------------------------------------------------------------*/
1533 /* packRegsForSupport :- reduce some registers for support calls   */
1534 /*-----------------------------------------------------------------*/
1535 static int
1536 packRegsForSupport (iCode * ic, eBBlock * ebp)
1537 {
1538   int change = 0;
1539   iCode *dic, *sic;
1540   
1541   /* for the left & right operand :- look to see if the
1542      left was assigned a true symbol in far space in that
1543      case replace them */
1544
1545   if (IS_ITEMP (IC_LEFT (ic)) &&
1546       OP_SYMBOL (IC_LEFT (ic))->liveTo <= ic->seq)
1547     {
1548       dic = findAssignToSym (IC_LEFT (ic), ic);
1549       
1550       if (!dic)
1551         goto right;
1552       
1553       /* found it we need to remove it from the
1554          block */
1555       for (sic = dic; sic != ic; sic = sic->next)
1556         bitVectUnSetBit (sic->rlive, IC_LEFT (ic)->key);
1557       
1558       OP_SYMBOL(IC_LEFT (ic))=OP_SYMBOL(IC_RIGHT (dic));
1559       IC_LEFT (ic)->key = OP_SYMBOL(IC_RIGHT (dic))->key;
1560       remiCodeFromeBBlock (ebp, dic);
1561       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
1562       hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
1563       change++;
1564     }
1565   
1566   /* do the same for the right operand */
1567  right:
1568   if (!change &&
1569       IS_ITEMP (IC_RIGHT (ic)) &&
1570       OP_SYMBOL (IC_RIGHT (ic))->liveTo <= ic->seq)
1571     {
1572       iCode *dic = findAssignToSym (IC_RIGHT (ic), ic);
1573       iCode *sic;
1574       
1575       if (!dic)
1576         return change;
1577       
1578       /* if this is a subtraction & the result
1579          is a true symbol in far space then don't pack */
1580       if (ic->op == '-' && IS_TRUE_SYMOP (IC_RESULT (dic)))
1581         {
1582           sym_link *etype = getSpec (operandType (IC_RESULT (dic)));
1583           if (IN_FARSPACE (SPEC_OCLS (etype)))
1584             return change;
1585         }
1586       /* found it we need to remove it from the
1587          block */
1588       for (sic = dic; sic != ic; sic = sic->next)
1589         bitVectUnSetBit (sic->rlive, IC_RIGHT (ic)->key);
1590       
1591       IC_RIGHT (ic)->operand.symOperand =
1592         IC_RIGHT (dic)->operand.symOperand;
1593       IC_RIGHT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
1594       
1595       remiCodeFromeBBlock (ebp, dic);
1596       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
1597       hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
1598       change++;
1599     }
1600   
1601   return change;
1602 }
1603
1604 #define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1605
1606
1607 /*-----------------------------------------------------------------*/
1608 /* packRegsForOneuse : - will reduce some registers for single Use */
1609 /*-----------------------------------------------------------------*/
1610 static iCode *
1611 packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
1612 {
1613   bitVect *uses;
1614   iCode *dic, *sic;
1615
1616   /* if returning a literal then do nothing */
1617   if (!IS_SYMOP (op))
1618     return NULL;
1619   
1620   if (ic->op != RETURN &&
1621       ic->op != SEND &&
1622       !POINTER_SET (ic) &&
1623       !POINTER_GET (ic))
1624     return NULL;
1625   
1626   /* this routine will mark the a symbol as used in one 
1627      instruction use only && if the defintion is local 
1628      (ie. within the basic block) && has only one definition &&
1629      that definiion is either a return value from a 
1630      function or does not contain any variables in
1631      far space */
1632   uses = bitVectCopy (OP_USES (op));
1633   bitVectUnSetBit (uses, ic->key);      /* take away this iCode */
1634   if (!bitVectIsZero (uses))    /* has other uses */
1635     return NULL;
1636   
1637   /* if it has only one defintion */
1638   if (bitVectnBitsOn (OP_DEFS (op)) > 1)
1639     return NULL;                /* has more than one definition */
1640   
1641   /* get that definition */
1642   if (!(dic =
1643         hTabItemWithKey (iCodehTab,
1644                          bitVectFirstBit (OP_DEFS (op)))))
1645     return NULL;
1646   
1647 #if 0
1648   /* if that only usage is a cast */
1649   if (dic->op == CAST) {
1650     /* to a bigger type */
1651     if (getSize(OP_SYM_TYPE(IC_RESULT(dic))) > 
1652         getSize(OP_SYM_TYPE(IC_RIGHT(dic)))) {
1653       /* than we can not, since we cannot predict the usage of b & acc */
1654       return NULL;
1655     }
1656   }
1657 #endif
1658   
1659   /* found the definition now check if it is local */
1660   if (dic->seq < ebp->fSeq ||
1661       dic->seq > ebp->lSeq)
1662     return NULL;                /* non-local */
1663   
1664   /* now check if it is the return from
1665      a function call */
1666   if (dic->op == CALL || dic->op == PCALL)
1667     {
1668       if (ic->op != SEND && ic->op != RETURN &&
1669           !POINTER_SET(ic) && !POINTER_GET(ic))
1670         {
1671           OP_SYMBOL (op)->ruonly = 1;
1672           return dic;
1673         }
1674       dic = dic->next;
1675     }
1676   
1677 #if 0  
1678   /* otherwise check that the definition does
1679      not contain any symbols in far space */
1680   if (isOperandInFarSpace (IC_LEFT (dic)) ||
1681       isOperandInFarSpace (IC_RIGHT (dic)) ||
1682       IS_OP_RUONLY (IC_LEFT (ic)) ||
1683       IS_OP_RUONLY (IC_RIGHT (ic)))
1684     {
1685       return NULL;
1686     }
1687 #endif
1688
1689 #if 0  
1690   /* if pointer set then make sure the pointer
1691      is one byte */
1692   if (POINTER_SET (dic) &&
1693       !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
1694     return NULL;
1695   
1696   if (POINTER_GET (dic) &&
1697       !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
1698     return NULL;
1699 #endif
1700   
1701   sic = dic;
1702   
1703   /* also make sure the intervenening instructions
1704      don't have any thing in far space */
1705   for (dic = dic->next; dic && dic != ic && sic != ic; dic = dic->next)
1706     {
1707       
1708       /* if there is an intervening function call then no */
1709       if (dic->op == CALL || dic->op == PCALL)
1710         return NULL;
1711
1712 #if 0
1713       /* if pointer set then make sure the pointer
1714          is one byte */
1715       if (POINTER_SET (dic) &&
1716           !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
1717         return NULL;
1718       
1719       if (POINTER_GET (dic) &&
1720           !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
1721         return NULL;
1722 #endif
1723       
1724       /* if address of & the result is remat the okay */
1725       if (dic->op == ADDRESS_OF &&
1726           OP_SYMBOL (IC_RESULT (dic))->remat)
1727         continue;
1728
1729 #if 0      
1730       /* if operand has size of three or more & this
1731          operation is a '*','/' or '%' then 'b' may
1732          cause a problem */
1733       if ((dic->op == '%' || dic->op == '/' || dic->op == '*') &&
1734           getSize (operandType (op)) >= 3)
1735         return NULL;
1736 #endif
1737       
1738 #if 0
1739       /* if left or right or result is in far space */
1740       if (isOperandInFarSpace (IC_LEFT (dic)) ||
1741           isOperandInFarSpace (IC_RIGHT (dic)) ||
1742           isOperandInFarSpace (IC_RESULT (dic)) ||
1743           IS_OP_RUONLY (IC_LEFT (dic)) ||
1744           IS_OP_RUONLY (IC_RIGHT (dic)) ||
1745           IS_OP_RUONLY (IC_RESULT (dic)))
1746         {
1747           return NULL;
1748         }
1749       /* if left or right or result is on stack */
1750       if (isOperandOnStack(IC_LEFT(dic)) ||
1751           isOperandOnStack(IC_RIGHT(dic)) ||
1752           isOperandOnStack(IC_RESULT(dic))) {
1753         return NULL;
1754       }
1755 #endif
1756     }
1757   
1758   OP_SYMBOL (op)->ruonly = 1;
1759   fprintf (stderr, "%s is used only once in line %d.\n", 
1760            OP_SYMBOL(op)->name, ic->lineno);
1761   return sic;
1762   
1763 }
1764
1765 /*-----------------------------------------------------------------*/
1766 /* isBitwiseOptimizable - requirements of JEAN LOUIS VERN          */
1767 /*-----------------------------------------------------------------*/
1768 static bool
1769 isBitwiseOptimizable (iCode * ic)
1770 {
1771   sym_link *ltype = getSpec (operandType (IC_LEFT (ic)));
1772   sym_link *rtype = getSpec (operandType (IC_RIGHT (ic)));
1773   
1774   /* bitwise operations are considered optimizable
1775      under the following conditions (Jean-Louis VERN) 
1776      
1777      x & lit
1778      bit & bit
1779      bit & x
1780      bit ^ bit
1781      bit ^ x
1782      x   ^ lit
1783      x   | lit
1784      bit | bit
1785      bit | x
1786   */
1787   if (IS_LITERAL(rtype) ||
1788       (IS_BITVAR (ltype) && IN_BITSPACE (SPEC_OCLS (ltype))))
1789     return TRUE;
1790   else
1791     return FALSE;
1792 }
1793
1794 /*-----------------------------------------------------------------*/
1795 /* packForPush - hueristics to reduce iCode for pushing            */
1796 /*-----------------------------------------------------------------*/
1797 static void
1798 packForPush (iCode * ic, eBBlock * ebp)
1799 {
1800   iCode *dic, *lic;
1801   bitVect *dbv;
1802
1803   if (ic->op != IPUSH || !IS_ITEMP (IC_LEFT (ic)))
1804     return;
1805   
1806   /* must have only definition & one usage */
1807   if (bitVectnBitsOn (OP_DEFS (IC_LEFT (ic))) != 1 ||
1808       bitVectnBitsOn (OP_USES (IC_LEFT (ic))) != 1)
1809     return;
1810   
1811   /* find the definition */
1812   if (!(dic = hTabItemWithKey (iCodehTab,
1813                                bitVectFirstBit (OP_DEFS (IC_LEFT (ic))))))
1814     return;
1815   
1816   if (dic->op != '=' || POINTER_SET (dic))
1817     return;
1818   
1819   /* make sure the right side does not have any definitions
1820      inbetween */
1821   dbv = OP_DEFS(IC_RIGHT(dic));
1822   for (lic = ic; lic && lic != dic ; lic = lic->prev) {
1823     if (bitVectBitValue(dbv,lic->key)) 
1824       return ;
1825   }
1826   /* make sure they have the same type */
1827   {
1828     sym_link *itype=operandType(IC_LEFT(ic));
1829     sym_link *ditype=operandType(IC_RIGHT(dic));
1830     
1831     if (SPEC_USIGN(itype)!=SPEC_USIGN(ditype) ||
1832         SPEC_LONG(itype)!=SPEC_LONG(ditype))
1833       return;
1834   }
1835   /* extend the live range of replaced operand if needed */
1836   if (OP_SYMBOL(IC_RIGHT(dic))->liveTo < ic->seq) {
1837     OP_SYMBOL(IC_RIGHT(dic))->liveTo = ic->seq;
1838   }
1839   /* we now know that it has one & only one def & use
1840      and the that the definition is an assignment */
1841   IC_LEFT (ic) = IC_RIGHT (dic);
1842   
1843   remiCodeFromeBBlock (ebp, dic);
1844   bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
1845   hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
1846 }
1847
1848 /*-----------------------------------------------------------------*/
1849 /* packRegisters - does some transformations to reduce register    */
1850 /*                   pressure                                      */
1851 /*-----------------------------------------------------------------*/
1852 static void packRegisters (eBBlock * ebp) {
1853   iCode *ic;
1854   int change = 0;
1855   
1856   while (1) {
1857     change = 0;
1858     
1859     for (ic = ebp->sch; ic; ic = ic->next) {
1860       if (ic->op == '=')
1861         change += packRegsForAssign (ic, ebp);
1862     }
1863     
1864     if (!change)
1865       break;
1866   }
1867   
1868   for (ic = ebp->sch; ic; ic = ic->next)
1869     {
1870       /* if the condition of an if instruction
1871          is defined in the previous instruction and
1872          this is the only usage then
1873          mark the itemp as a conditional */
1874       if ((IS_CONDITIONAL (ic) ||
1875            (IS_BITWISE_OP(ic) && isBitwiseOptimizable (ic)))) {
1876         if (ic->next && ic->next->op == IFX &&
1877             bitVectnBitsOn (OP_USES(IC_RESULT(ic)))==1 &&
1878             isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) &&
1879             OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq) {
1880           OP_SYMBOL (IC_RESULT (ic))->regType = REG_CND;
1881           continue;
1882         }
1883       }
1884
1885 #if 0
1886       /* if this is an itemp & result of an address of a true sym 
1887          then mark this as rematerialisable   */
1888       if (ic->op == ADDRESS_OF &&
1889           IS_ITEMP (IC_RESULT (ic)) &&
1890           IS_TRUE_SYMOP (IC_LEFT (ic)) &&
1891           bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
1892           !OP_SYMBOL (IC_LEFT (ic))->onStack)
1893         {
1894           OP_SYMBOL (IC_RESULT (ic))->remat = 1;
1895           OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
1896           OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
1897         }
1898
1899       /* if straight assignment then carry remat flag if
1900          this is the only definition */
1901       if (ic->op == '=' &&
1902           !POINTER_SET (ic) &&
1903           IS_SYMOP (IC_RIGHT (ic)) &&
1904           OP_SYMBOL (IC_RIGHT (ic))->remat &&
1905           !IS_CAST_ICODE(OP_SYMBOL (IC_RIGHT (ic))->rematiCode) &&
1906           bitVectnBitsOn (OP_SYMBOL (IC_RESULT (ic))->defs) <= 1)
1907         {
1908           
1909           OP_SYMBOL (IC_RESULT (ic))->remat =
1910             OP_SYMBOL (IC_RIGHT (ic))->remat;
1911           OP_SYMBOL (IC_RESULT (ic))->rematiCode =
1912             OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1913         }
1914       
1915       /* if cast to a generic pointer & the pointer being
1916          cast is remat, then we can remat this cast as well */
1917       if (ic->op == CAST && 
1918           IS_SYMOP(IC_RIGHT(ic)) &&
1919           OP_SYMBOL(IC_RIGHT(ic))->remat ) {
1920         sym_link *to_type = operandType(IC_LEFT(ic));
1921         sym_link *from_type = operandType(IC_RIGHT(ic));
1922         if (IS_GENPTR(to_type) && IS_PTR(from_type)) {                
1923           OP_SYMBOL (IC_RESULT (ic))->remat = 1;
1924           OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
1925           OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
1926         }
1927       }
1928       
1929       /* if this is a +/- operation with a rematerizable 
1930          then mark this as rematerializable as well */
1931       if ((ic->op == '+' || ic->op == '-') &&
1932           (IS_SYMOP (IC_LEFT (ic)) &&
1933            IS_ITEMP (IC_RESULT (ic)) &&
1934            IS_OP_LITERAL (IC_RIGHT (ic))) &&
1935           OP_SYMBOL (IC_LEFT (ic))->remat &&
1936           (!IS_SYMOP (IC_RIGHT (ic)) || !IS_CAST_ICODE(OP_SYMBOL (IC_RIGHT (ic))->rematiCode)) &&
1937           bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1)
1938         {
1939           OP_SYMBOL (IC_RESULT (ic))->remat = 1;
1940           OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
1941           OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
1942         }
1943 #endif
1944       
1945       /* mark the pointer usages */
1946       if (POINTER_SET (ic))
1947         OP_SYMBOL (IC_RESULT (ic))->uptr = 1;
1948       
1949       if (POINTER_GET (ic))
1950         OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
1951       
1952       /* reduce for support function calls */
1953       if (ic->supportRtn || ic->op == '+' || ic->op == '-')
1954         packRegsForSupport (ic, ebp);
1955       
1956       /* some cases the redundant moves can
1957          can be eliminated for return statements */
1958       if (ic->op == RETURN || ic->op == SEND) {
1959           packRegsForOneuse (ic, IC_LEFT (ic), ebp);
1960         }
1961       
1962       /* if pointer set & left has a size more than
1963          one and right is not in far space */
1964       if (POINTER_SET (ic) &&
1965           !isOperandInFarSpace (IC_RIGHT (ic)) &&
1966           !OP_SYMBOL (IC_RESULT (ic))->remat &&
1967           !IS_OP_RUONLY (IC_RIGHT (ic)) &&
1968           getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1)
1969         
1970         packRegsForOneuse (ic, IC_RESULT (ic), ebp);
1971       
1972       /* if pointer get */
1973       if (POINTER_GET (ic) &&
1974           !isOperandInFarSpace (IC_RESULT (ic)) &&
1975           !OP_SYMBOL (IC_LEFT (ic))->remat &&
1976           !IS_OP_RUONLY (IC_RESULT (ic)) &&
1977           getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1)
1978         
1979         packRegsForOneuse (ic, IC_LEFT (ic), ebp);
1980       
1981       
1982       /* if this is cast for intergral promotion then
1983          check if only use of  the definition of the 
1984          operand being casted/ if yes then replace
1985          the result of that arithmetic operation with 
1986          this result and get rid of the cast */
1987       if (ic->op == CAST)
1988         {
1989           sym_link *fromType = operandType (IC_RIGHT (ic));
1990           sym_link *toType = operandType (IC_LEFT (ic));
1991           
1992           if (IS_INTEGRAL (fromType) && IS_INTEGRAL (toType) &&
1993               getSize (fromType) != getSize (toType) &&
1994               SPEC_USIGN (fromType) == SPEC_USIGN (toType))
1995             {
1996               
1997               iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
1998               if (dic)
1999                 {
2000                   if (IS_ARITHMETIC_OP (dic))
2001                     {                  
2002                       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
2003                       IC_RESULT (dic) = IC_RESULT (ic);
2004                       remiCodeFromeBBlock (ebp, ic);
2005                       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
2006                       hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
2007                       OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
2008                       ic = ic->prev;
2009                     }
2010                   else
2011                     OP_SYMBOL (IC_RIGHT (ic))->ruonly = 0;
2012                 }
2013             }
2014           else
2015             {
2016               
2017               /* if the type from and type to are the same
2018                  then if this is the only use then packit */
2019               if (compareType (operandType (IC_RIGHT (ic)),
2020                                operandType (IC_LEFT (ic))) == 1)
2021                 {
2022                   iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
2023                   if (dic)
2024                     {
2025                       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
2026                       IC_RESULT (dic) = IC_RESULT (ic);
2027                       remiCodeFromeBBlock (ebp, ic);
2028                       bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
2029                       hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
2030                       OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
2031                       ic = ic->prev;
2032                     }
2033                 }
2034             }
2035         }
2036       
2037       /* pack for PUSH 
2038          iTempNN := (some variable in farspace) V1
2039          push iTempNN ;
2040          -------------
2041          push V1
2042       */
2043       if (ic->op == IPUSH)
2044         {
2045           packForPush (ic, ebp);
2046         }
2047     }
2048 }
2049
2050 /*-----------------------------------------------------------------*/
2051 /* assignRegisters - assigns registers to each live range as need  */
2052 /*-----------------------------------------------------------------*/
2053 void
2054 xa51_assignRegisters (eBBlock ** ebbs, int count)
2055 {
2056   iCode *ic;
2057   int i;
2058   
2059   setToNull ((void *) &_G.funcrUsed);
2060   setToNull ((void *) &_G.totRegAssigned);
2061   _G.stackExtend = 0;
2062   
2063   /* change assignments this will remove some
2064      live ranges reducing some register pressure */
2065   for (i = 0; i < count; i++)
2066     packRegisters (ebbs[i]);
2067
2068   /* liveranges probably changed by register packing
2069      so we compute them again */
2070   recomputeLiveRanges (ebbs, count);
2071
2072   if (options.dump_pack)
2073     dumpEbbsToFileExt (DUMP_PACK, ebbs, count);
2074   
2075   /* first determine for each live range the number of 
2076      registers & the type of registers required for each */
2077   regTypeNum (*ebbs);
2078   
2079   /* and serially allocate registers */
2080   serialRegAssign (ebbs, count);
2081   
2082   freeAllRegs ();
2083   
2084   /* if stack was extended then tell the user */
2085   if (_G.stackExtend)
2086     {
2087       werror(I_EXTENDED_STACK_SPILS,
2088              _G.stackExtend,currFunc->name,"");
2089       _G.stackExtend = 0;
2090     }
2091   
2092   /* after that create the register mask
2093      for each of the instruction */
2094   createRegMask (ebbs, count);
2095   
2096   /* redo that offsets for stacked automatic variables */
2097   redoStackOffsets ();
2098   
2099   if (options.dump_rassgn)
2100     {
2101       dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count);
2102       dumpLiveRanges (DUMP_LRANGE, liveRanges);
2103     }
2104   
2105   /* do the overlaysegment stuff SDCCmem.c */
2106   doOverlays (ebbs, count);
2107   
2108   /* now get back the chain */
2109   ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count));
2110   
2111   genXA51Code (ic);
2112   
2113   /* free up any _G.stackSpil locations allocated */
2114   applyToSet (_G.stackSpil, deallocStackSpil);
2115   _G.slocNum = 0;
2116   setToNull ((void *) &_G.stackSpil);
2117   setToNull ((void *) &_G.spiltSet);
2118   /* mark all registers as free */
2119   freeAllRegs ();
2120   
2121   return;
2122 }