More builtin function additions for TININative
[fw/sdcc] / src / ds390 / ralloc.c
index ca8e0ab3487d08e63fb43e126988692dd81a9220..b462b81be9f862eebb6ef310f998450c2c103469 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
@@ -1285,6 +1299,32 @@ 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 */
+
+    for (sym = hTabFirstItem(liveRanges,&key) ; sym ; 
+        sym = hTabNextItem(liveRanges,&key)) {
+
+       if (sym->uptr && !sym->ruonly && getSize(sym->type) < 4) {
+           if (packRegsDPTRuse(operandFromSymbol(sym))) {
+
+                D (fprintf (stderr, "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;
+           }
+       }
+    }
+
     /* look for livernages that was spilt by the allocator */
     for (sym = hTabFirstItem(liveRanges,&key) ; sym ; 
         sym = hTabNextItem(liveRanges,&key)) {
@@ -1293,7 +1333,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 ++) {
@@ -1325,7 +1365,7 @@ static void fillGaps()
                sym->regs[i] = getRegGprNoSpil ();                
        }
 
-       /* for all its definitions check if the registers
+       /* for all its definitions & uses check if the registers
           allocated needs positioning NOTE: we can position
           only ONCE if more than One positioning required 
           then give up */
@@ -1348,18 +1388,36 @@ static void fillGaps()
                if (pdone > 1) break;
            }
        }
+               for (i = 0 ; i < sym->uses->size ; i++ ) {
+           if (bitVectBitValue(sym->uses,i)) {
+               iCode *ic;
+               if (!(ic = hTabItemWithKey(iCodehTab,i))) continue ;
+               if (SKIP_IC(ic)) continue;
+               if (!IS_ASSIGN_ICODE(ic)) continue ;
+
+               /* if result is assigned to registers */
+               if (IS_SYMOP(IC_RESULT(ic)) && 
+                   bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RESULT(ic))->key)) {
+                   pdone += positionRegs(sym,OP_SYMBOL(IC_RESULT(ic)));
+               }
+               if (pdone > 1) break;
+           }
+       }
        /* had to position more than once GIVE UP */
        if (pdone > 1) {
            /* UNDO all the changes we made to try this */
-           sym->isspilt = 0;
+           sym->isspilt = 1;
            for (i=0; i < sym->nRegs ; i++ ) {
                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 (fprintf (stderr, "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 (fprintf (stderr, "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--;
@@ -1370,8 +1428,8 @@ static void fillGaps()
 /*-----------------------------------------------------------------*/
 /* rUmaskForOp :- returns register mask for an operand             */
 /*-----------------------------------------------------------------*/
-static bitVect *
-rUmaskForOp (operand * op)
+bitVect *
+ds390_rUmaskForOp (operand * op)
 {
   bitVect *rumask;
   symbol *sym;
@@ -1411,7 +1469,7 @@ regsUsedIniCode (iCode * ic)
   if (ic->op == IFX)
     {
       rmask = bitVectUnion (rmask,
-                           rUmaskForOp (IC_COND (ic)));
+                           ds390_rUmaskForOp (IC_COND (ic)));
       goto ret;
     }
 
@@ -1419,7 +1477,7 @@ regsUsedIniCode (iCode * ic)
   if (ic->op == JUMPTABLE)
     {
       rmask = bitVectUnion (rmask,
-                           rUmaskForOp (IC_JTCOND (ic)));
+                           ds390_rUmaskForOp (IC_JTCOND (ic)));
 
       goto ret;
     }
@@ -1427,16 +1485,16 @@ regsUsedIniCode (iCode * ic)
   /* of all other cases */
   if (IC_LEFT (ic))
     rmask = bitVectUnion (rmask,
-                         rUmaskForOp (IC_LEFT (ic)));
+                         ds390_rUmaskForOp (IC_LEFT (ic)));
 
 
   if (IC_RIGHT (ic))
     rmask = bitVectUnion (rmask,
-                         rUmaskForOp (IC_RIGHT (ic)));
+                         ds390_rUmaskForOp (IC_RIGHT (ic)));
 
   if (IC_RESULT (ic))
     rmask = bitVectUnion (rmask,
-                         rUmaskForOp (IC_RESULT (ic)));
+                         ds390_rUmaskForOp (IC_RESULT (ic)));
 
 ret:
   return rmask;
@@ -1857,6 +1915,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)
@@ -1874,6 +1933,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;
@@ -1962,8 +2022,9 @@ findAssignToSym (operand * op, iCode * ic)
 /*-----------------------------------------------------------------*/
 static int
 packRegsForSupport (iCode * ic, eBBlock * ebp)
-{
+{    
   int change = 0;
+  
   /* for the left & right operand :- look to see if the
      left was assigned a true symbol in far space in that
      case replace them */
@@ -1984,6 +2045,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++;
@@ -2019,6 +2081,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++;
     }
@@ -2033,7 +2096,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
@@ -2063,35 +2126,48 @@ 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;
 
-       /* if CALL then make sure it is VOID || return value not used */
+       /* if CALL then make sure it is VOID || return value not used 
+          or the return value is assigned to this one */
        if (ic->op == CALL) {
            if (OP_SYMBOL(IC_RESULT(ic))->liveTo == 
                OP_SYMBOL(IC_RESULT(ic))->liveFrom) continue ;
            etype = getSpec(type = operandType(IC_RESULT(ic)));
-           if (getSize(type) == 0) continue ;
+#if 0
+           if (getSize(type) == 0 || isOperandEqual(op,IC_RESULT(ic))) 
+#endif
+           if (getSize(type) == 0)
+               continue ;
            return NULL ;
        }
 
        /* 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)))) return NULL ;
 
-       /* 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 ;
 
-       if (POINTER_SET(ic) && isOperandEqual(IC_RIGHT(ic),op) &&
-           getSize(operandType(IC_RESULT(ic))) > 1) return NULL;
+       /* pointerSet */
+       if (POINTER_SET(ic) && !isOperandEqual(IC_RESULT(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;
 
@@ -2100,7 +2176,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)) && 
@@ -2108,12 +2184,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;
@@ -2157,6 +2234,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)
@@ -2232,9 +2314,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)) &&
@@ -2337,6 +2424,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);
 }
 
@@ -2444,6 +2532,9 @@ packRegisters (eBBlock * ebp)
       if (POINTER_GET (ic))
        OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
 
+      if (ic->op == RETURN && IS_SYMOP (IC_LEFT(ic)))
+         OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
+
       if (!SKIP_IC2 (ic))
        {
          /* if we are using a symbol on the stack
@@ -2499,9 +2590,11 @@ packRegisters (eBBlock * ebp)
        }
 #endif
 
+#if 0 /* unsafe */
       /* reduce for support function calls */
       if (ic->supportRtn || ic->op == '+' || ic->op == '-')
        packRegsForSupport (ic, ebp);
+#endif
 
       /* some cases the redundant moves can
          can be eliminated for return statements */
@@ -2509,11 +2602,15 @@ 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);      
+      if (ic->op == CALL) {
+         sym_link *ftype = operandType(IC_LEFT(ic));
+         if (getSize(operandType(IC_RESULT(ic))) <= 4 &&
+             !IFFUNC_ISBUILTIN(ftype)) {
+             packRegsDPTRuse (IC_RESULT (ic));   
+         }
       }
 
       /* if pointer set & left has a size more than
@@ -2524,7 +2621,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 */
@@ -2534,7 +2631,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
@@ -2552,13 +2649,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;
@@ -2575,11 +2674,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;
@@ -2636,7 +2737,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 */
@@ -2656,7 +2757,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)