a) Moved DPL, DPH, DPX & B before XREGn . ralloc.c/ralloc.h
[fw/sdcc] / src / ds390 / ralloc.c
index c00e4994125c62c03157108b9cce720123f64175..8722a5c9be145231a3676c81bbc7a6b3b214ae14 100644 (file)
@@ -36,6 +36,8 @@
 /* since the pack the registers depending strictly on the MCU      */
 /*-----------------------------------------------------------------*/
 
+#define D(x)
+
 /* Global data */
 static struct
   {
@@ -66,20 +68,21 @@ regs regs390[] =
   {REG_GPR, R7_IDX, REG_GPR, "r7", "ar7", "0", 7, 1, 1},
   {REG_PTR, R0_IDX, REG_PTR, "r0", "ar0", "0", 0, 1, 1},
   {REG_PTR, R1_IDX, REG_PTR, "r1", "ar1", "0", 1, 1, 1},
+  {REG_GPR, DPL_IDX, REG_GPR, "dpl", "dpl", "dpl", 0, 0, 0},
+  {REG_GPR, DPH_IDX, REG_GPR, "dph", "dph", "dph", 0, 0, 0},
+  {REG_GPR, DPX_IDX, REG_GPR, "dpx", "dpx", "dpx", 0, 0, 0},
+  {REG_GPR, B_IDX, REG_GPR, "b", "b", "b", 0, 0, 0},
   {REG_GPR, X8_IDX, REG_GPR, "x8", "x8", "xreg", 0, 0, 0},
   {REG_GPR, X9_IDX, REG_GPR, "x9", "x9", "xreg", 1, 0, 0},
   {REG_GPR, X10_IDX, REG_GPR, "x10", "x10", "xreg", 2, 0, 0},
   {REG_GPR, X11_IDX, REG_GPR, "x11", "x11", "xreg", 3, 0, 0},
   {REG_GPR, X12_IDX, REG_GPR, "x12", "x12", "xreg", 4, 0, 0},
   {REG_CND, CND_IDX, REG_GPR, "C", "C", "xreg", 0, 0, 0},
-  {REG_GPR, DPL_IDX, REG_GPR, "dpl", "dpl", "dpl", 0, 0, 0},
-  {REG_GPR, DPH_IDX, REG_GPR, "dph", "dph", "dph", 0, 0, 0},
-  {REG_GPR, DPX_IDX, REG_GPR, "dpx", "dpx", "dpx", 0, 0, 0},
-  {REG_GPR, B_IDX, REG_GPR, "b", "b", "b", 0, 0, 0},
 };
 int ds390_nRegs = 13;
 static void spillThis (symbol *);
 static void freeAllRegs ();
+static iCode * packRegsDPTRuse (operand *);
 
 /*-----------------------------------------------------------------*/
 /* allocReg - allocates register of given type                     */
@@ -212,6 +215,16 @@ allDefsOutOfRange (bitVect * defs, int fseq, int toseq)
   return TRUE;
 }
 
+/*-----------------------------------------------------------------*/
+/* isOperandInReg - returns true if operand is currently in regs   */
+/*-----------------------------------------------------------------*/
+static int isOperandInReg(operand *op)
+{
+    if (!IS_SYMOP(op)) return 0;
+
+    return bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(op)->key);
+}
+
 /*-----------------------------------------------------------------*/
 /* computeSpillable - given a point find the spillable live ranges */
 /*-----------------------------------------------------------------*/
@@ -523,6 +536,7 @@ createStackSpil (symbol * sym)
   }
   SPEC_EXTR (sloc->etype) = 0;
   SPEC_STAT (sloc->etype) = 0;
+  SPEC_VOLATILE(sloc->etype) = 0;
 
   /* we don't allow it to be allocated`
      onto the external stack since : so we
@@ -1219,8 +1233,11 @@ serialRegAssign (eBBlock ** ebbs, int count)
                        /* if none of the liveRanges have a spillLocation then better
                           to spill this one than anything else already assigned to registers */
                        if (liveRangesWith(spillable,noSpilLoc,ebbs[i],ic)) {
-                           spillThis (sym);
-                           continue;
+                           /* if this is local to this block then we might find a block spil */
+                           if (!(sym->liveFrom >= ebbs[i]->fSeq && sym->liveTo <= ebbs[i]->lSeq)) {
+                               spillThis (sym);
+                               continue;
+                           }
                        }
                    }
                }
@@ -1282,6 +1299,30 @@ static void fillGaps()
     int key =0;    
     
     if (getenv("DISABLE_FILL_GAPS")) return;
+    
+    /* First try to do DPTRuse once more since now we know what got into
+       registers */
+#if 1
+    for (sym = hTabFirstItem(liveRanges,&key) ; sym ; 
+        sym = hTabNextItem(liveRanges,&key)) {
+
+       if (sym->uptr && !sym->ruonly && getSize(sym->type) < 4) {
+           if (packRegsDPTRuse(operandFromSymbol(sym))) {
+
+                D (printf ("FILL GAPS: found more DPTR use for %s in func %s\n",sym->name, currFunc ? currFunc->name : "UNKNOWN"));
+               /* if this was ssigned to registers then */
+               if (bitVectBitValue(_G.totRegAssigned,sym->key)) {
+
+                   /* take it out of the register assigned set */
+                   bitVectUnSetBit(_G.totRegAssigned,sym->key);
+                   sym->nRegs = 0;                 
+               } else if (sym->usl.spillLoc) sym->usl.spillLoc->allocreq--;
+
+               sym->isspilt = sym->spillA = 0;
+           }
+       }
+    }
+#endif    
     /* look for livernages that was spilt by the allocator */
     for (sym = hTabFirstItem(liveRanges,&key) ; sym ; 
         sym = hTabNextItem(liveRanges,&key)) {
@@ -1290,7 +1331,7 @@ static void fillGaps()
        int pdone = 0;
 
        if (!sym->spillA || !sym->clashes || sym->remat) continue ;
-       
+
        /* find the liveRanges this one clashes with, that are
           still assigned to registers & mark the registers as used*/
        for ( i = 0 ; i < sym->clashes->size ; i ++) {
@@ -1353,10 +1394,10 @@ static void fillGaps()
                sym->regs[i] = NULL;
            }
            freeAllRegs();
-           printf("Fill Gap gave up due to positioning for %s in function %s\n",sym->name, currFunc ? currFunc->name : "UNKNOWN");
+           D (printf ("Fill Gap gave up due to positioning for %s in function %s\n",sym->name, currFunc ? currFunc->name : "UNKNOWN"));
            continue ;      
        }
-       printf("FILLED GAP for %s in function %s\n",sym->name, currFunc ? currFunc->name : "UNKNOWN");
+       D (printf ("FILLED GAP for %s in function %s\n",sym->name, currFunc ? currFunc->name : "UNKNOWN"));
        _G.totRegAssigned = bitVectSetBit(_G.totRegAssigned,sym->key);
        sym->isspilt = sym->spillA = 0 ;
        sym->usl.spillLoc->allocreq--;
@@ -1854,6 +1895,7 @@ pack:
   /* found the definition */
   /* replace the result with the result of */
   /* this assignment and remove this assignment */
+  bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
   IC_RESULT (dic) = IC_RESULT (ic);
 
   if (IS_ITEMP (IC_RESULT (dic)) && OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq)
@@ -1871,6 +1913,7 @@ pack:
     }
 
   remiCodeFromeBBlock (ebp, ic);
+  bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
   hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
   OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
   return 1;
@@ -1981,6 +2024,7 @@ packRegsForSupport (iCode * ic, eBBlock * ebp)
       IC_LEFT (ic)->operand.symOperand =
        IC_RIGHT (dic)->operand.symOperand;
       IC_LEFT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
+      bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
       remiCodeFromeBBlock (ebp, dic);
       hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
       change++;
@@ -2016,6 +2060,7 @@ right:
       IC_RIGHT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
 
       remiCodeFromeBBlock (ebp, dic);
+      bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
       hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
       change++;
     }
@@ -2030,7 +2075,7 @@ right:
 /* packRegsDPTRuse : - will reduce some registers for single Use */
 /*-----------------------------------------------------------------*/
 static iCode *
-packRegsDPTRuse (iCode * lic, operand * op, eBBlock * ebp)
+packRegsDPTRuse (operand * op)
 {
     /* go thru entire liveRange of this variable & check for
        other possible usage of DPTR , if we don't find it the
@@ -2041,7 +2086,7 @@ packRegsDPTRuse (iCode * lic, operand * op, eBBlock * ebp)
     iCode *ic, *dic;
     sym_link *type, *etype;
     
-    if (!IS_SYMOP(op)) return NULL;
+    if (!IS_SYMOP(op) || !IS_ITEMP(op)) return NULL;
     if (OP_SYMBOL(op)->remat || OP_SYMBOL(op)->ruonly) return NULL; 
 
     /* first check if any overlapping liverange has already been
@@ -2060,6 +2105,8 @@ packRegsDPTRuse (iCode * lic, operand * op, eBBlock * ebp)
     for (; ic && ic->seq <= OP_SYMBOL(op)->liveTo;
         ic = hTabNextItem(iCodeSeqhTab,&key)) {
 
+       if (SKIP_IC3(ic)) continue;
+
        /* if PCALL cannot be sure give up */
        if (ic->op == PCALL) return NULL;
 
@@ -2075,20 +2122,26 @@ packRegsDPTRuse (iCode * lic, operand * op, eBBlock * ebp)
        /* special case of add with a [remat] */
        if (ic->op == '+' && 
            OP_SYMBOL(IC_LEFT(ic))->remat &&
-           !isOperandInFarSpace(IC_RIGHT(ic))) continue ;
+           (!isOperandInFarSpace(IC_RIGHT(ic)) || 
+            isOperandInReg(IC_RIGHT(ic)))) continue ;
 
-       /* special case */
+       /* special case */
        /* pointerGet */
-       if (POINTER_GET(ic) && isOperandEqual(IC_RESULT(ic),op) &&
-           getSize(operandType(IC_LEFT(ic))) > 1) return NULL ;
+       if (POINTER_GET(ic) && !isOperandEqual(IC_LEFT(ic),op) &&
+           getSize(operandType(IC_LEFT(ic))) > 1 ) return NULL ;
+
+       /* pointerSet */
+       if (POINTER_SET(ic) && !isOperandEqual(IC_RESULT(ic),op) &&
+           getSize(operandType(IC_RESULT(ic))) > 1 ) return NULL;
 
-       if (POINTER_SET(ic) && isOperandEqual(IC_RIGHT(ic),op) &&
-           getSize(operandType(IC_RESULT(ic))) > 1) return NULL;
+       /* conditionals can destroy 'b' - make sure B wont be used in this one*/
+       if ((IS_CONDITIONAL(ic) || ic->op == '*' || ic->op == '/' ) && 
+           getSize(operandType(op)) > 3) return NULL;
 
        /* general case */
        if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) && 
            !isOperandEqual(IC_RESULT(ic),op) &&
-           (isOperandInFarSpace(IC_RESULT(ic)) || 
+           ((isOperandInFarSpace(IC_RESULT(ic)) && !isOperandInReg(IC_RESULT(ic))) || 
             OP_SYMBOL(IC_RESULT(ic))->ruonly   ||
             OP_SYMBOL(IC_RESULT(ic))->onStack)) return NULL;
 
@@ -2097,7 +2150,7 @@ packRegsDPTRuse (iCode * lic, operand * op, eBBlock * ebp)
            (OP_SYMBOL(IC_RIGHT(ic))->liveTo > ic->seq || 
             IS_TRUE_SYMOP(IC_RIGHT(ic))               ||
             OP_SYMBOL(IC_RIGHT(ic))->ruonly) &&
-           (isOperandInFarSpace(IC_RIGHT(ic)) || 
+           ((isOperandInFarSpace(IC_RIGHT(ic)) && !isOperandInReg(IC_RIGHT(ic)))|| 
             OP_SYMBOL(IC_RIGHT(ic))->onStack)) return NULL;
 
        if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) && 
@@ -2105,12 +2158,13 @@ packRegsDPTRuse (iCode * lic, operand * op, eBBlock * ebp)
            (OP_SYMBOL(IC_LEFT(ic))->liveTo > ic->seq || 
             IS_TRUE_SYMOP(IC_LEFT(ic))               ||
             OP_SYMBOL(IC_LEFT(ic))->ruonly) &&
-           (isOperandInFarSpace(IC_LEFT(ic)) || 
+           ((isOperandInFarSpace(IC_LEFT(ic)) && !isOperandInReg(IC_LEFT(ic)))|| 
             OP_SYMBOL(IC_LEFT(ic))->onStack)) return NULL;
        
        if (IC_LEFT(ic) && IC_RIGHT(ic) && 
            IS_ITEMP(IC_LEFT(ic)) && IS_ITEMP(IC_RIGHT(ic)) &&
-           isOperandInFarSpace(IC_LEFT(ic)) && isOperandInFarSpace(IC_RIGHT(ic)))
+           (isOperandInFarSpace(IC_LEFT(ic)) && !isOperandInReg(IC_LEFT(ic))) && 
+           (isOperandInFarSpace(IC_RIGHT(ic)) && !isOperandInReg(IC_RIGHT(ic))))
            return NULL;
     }
     OP_SYMBOL(op)->ruonly = 1;
@@ -2154,6 +2208,11 @@ packRegsForAccUse (iCode * ic)
 {
   iCode *uic;
 
+  /* if this is an aggregate, e.g. a one byte char array */
+  if (IS_AGGREGATE(operandType(IC_RESULT(ic)))) {
+    return;
+  }
+
   /* if + or - then it has to be one byte result */
   if ((ic->op == '+' || ic->op == '-')
       && getSize (operandType (IC_RESULT (ic))) > 1)
@@ -2229,9 +2288,14 @@ packRegsForAccUse (iCode * ic)
 
   /* make sure that the result of this icode is not on the
      stack, since acc is used to compute stack offset */
+#if 0
   if (IS_TRUE_SYMOP (IC_RESULT (uic)) &&
       OP_SYMBOL (IC_RESULT (uic))->onStack)
     return;
+#else
+  if (isOperandOnStack(IC_RESULT(uic)))
+    return;
+#endif
 
   /* if either one of them in far space then we cannot */
   if ((IS_TRUE_SYMOP (IC_LEFT (uic)) &&
@@ -2334,6 +2398,7 @@ packForPush (iCode * ic, eBBlock * ebp)
   IC_LEFT (ic) = IC_RIGHT (dic);
 
   remiCodeFromeBBlock (ebp, dic);
+  bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
   hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
 }
 
@@ -2506,11 +2571,11 @@ packRegisters (eBBlock * ebp)
          !isOperandInFarSpace (IC_LEFT (ic)) &&
          !options.model) {
         
-         packRegsDPTRuse (ic, IC_LEFT (ic), ebp);
+         packRegsDPTRuse (IC_LEFT (ic));
       }
 
       if ((ic->op == CALL && getSize(operandType(IC_RESULT(ic))) <= 4)) {
-         packRegsDPTRuse (ic, IC_RESULT (ic), ebp);      
+         packRegsDPTRuse (IC_RESULT (ic));       
       }
 
       /* if pointer set & left has a size more than
@@ -2521,7 +2586,7 @@ packRegisters (eBBlock * ebp)
          !IS_OP_RUONLY (IC_RIGHT (ic)) &&
          getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1) {
          
-         packRegsDPTRuse (ic, IC_RESULT (ic), ebp);
+         packRegsDPTRuse (IC_RESULT (ic));
       }
 
       /* if pointer get */
@@ -2531,7 +2596,7 @@ packRegisters (eBBlock * ebp)
          !IS_OP_RUONLY (IC_RESULT (ic)) &&
          getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1) {
 
-         packRegsDPTRuse (ic, IC_LEFT (ic), ebp);
+         packRegsDPTRuse (IC_LEFT (ic));
       }
 
       /* if this is cast for intergral promotion then
@@ -2549,13 +2614,15 @@ packRegisters (eBBlock * ebp)
              SPEC_USIGN (fromType) == SPEC_USIGN (toType))
            {
 
-             iCode *dic = packRegsDPTRuse (ic, IC_RIGHT (ic), ebp);
+             iCode *dic = packRegsDPTRuse (IC_RIGHT (ic));
              if (dic)
                {
                  if (IS_ARITHMETIC_OP (dic))
                    {
+                     bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
                      IC_RESULT (dic) = IC_RESULT (ic);
                      remiCodeFromeBBlock (ebp, ic);
+                     bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
                      hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
                      OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
                      ic = ic->prev;
@@ -2572,11 +2639,13 @@ packRegisters (eBBlock * ebp)
              if (compareType (operandType (IC_RIGHT (ic)),
                             operandType (IC_LEFT (ic))) == 1)
                {
-                 iCode *dic = packRegsDPTRuse (ic, IC_RIGHT (ic), ebp);
+                 iCode *dic = packRegsDPTRuse (IC_RIGHT (ic));
                  if (dic)
                    {
+                     bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
                      IC_RESULT (dic) = IC_RESULT (ic);
                      remiCodeFromeBBlock (ebp, ic);
+                     bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
                      hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
                      OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
                      ic = ic->prev;
@@ -2633,7 +2702,7 @@ ds390_assignRegisters (eBBlock ** ebbs, int count)
   setToNull ((void *) &_G.totRegAssigned);  
   setToNull ((void *) &_G.funcrUsed);  
   ds390_ptrRegReq = _G.stackExtend = _G.dataExtend = 0;
-  ds390_nRegs = 18;
+  ds390_nRegs = 12;
   if (options.model != MODEL_FLAT24) options.stack10bit = 0;
   /* change assignments this will remove some
      live ranges reducing some register pressure */
@@ -2653,7 +2722,7 @@ ds390_assignRegisters (eBBlock ** ebbs, int count)
   ds390_nRegs = 8;
   freeAllRegs ();
   fillGaps();
-  ds390_nRegs = 18;
+  ds390_nRegs = 12;
 
   /* if stack was extended then tell the user */
   if (_G.stackExtend)