Fixed pointer post increment problem
[fw/sdcc] / src / mcs51 / ralloc.c
index e741f9bbf6c64bca3599357cb78189cb942cb503..aaa47ce21bdd617cc95e56ee02f1f7645ca2c96c 100644 (file)
@@ -393,9 +393,11 @@ noOverLap (set * itmpStack, symbol * fsym)
   for (sym = setFirstItem (itmpStack); sym;
        sym = setNextItem (itmpStack))
     {
-      if (sym->liveTo > fsym->liveFrom)
-       return 0;
+           if (sym->liveFrom < fsym->liveTo &&
+               sym->liveTo   > fsym->liveTo) return 0;
 
+           if (sym->liveFrom < fsym->liveFrom &&
+               sym->liveTo > fsym->liveFrom) return 0;
     }
 
   return 1;
@@ -453,8 +455,7 @@ spillLRWithPtrReg (symbol * forSym)
     {
       int j;
 
-      /* if no registers assigned to it or
-         spilt */
+      /* if no registers assigned to it or spilt */
       /* if it does not overlap with this then 
          not need to spill it */
 
@@ -1072,146 +1073,138 @@ xchgPositions:
 static void
 serialRegAssign (eBBlock ** ebbs, int count)
 {
-  int i;
+    int i;
 
-  /* for all blocks */
-  for (i = 0; i < count; i++)
-    {
+    /* for all blocks */
+    for (i = 0; i < count; i++) {
 
-      iCode *ic;
+       iCode *ic;
 
-      if (ebbs[i]->noPath &&
-         (ebbs[i]->entryLabel != entryLabel &&
-          ebbs[i]->entryLabel != returnLabel))
-       continue;
+       if (ebbs[i]->noPath &&
+           (ebbs[i]->entryLabel != entryLabel &&
+            ebbs[i]->entryLabel != returnLabel))
+           continue;
 
-      /* of all instructions do */
-      for (ic = ebbs[i]->sch; ic; ic = ic->next)
-       {
+       /* of all instructions do */
+       for (ic = ebbs[i]->sch; ic; ic = ic->next) {
 
-         /* if this is an ipop that means some live
-            range will have to be assigned again */
-         if (ic->op == IPOP)
-           reassignLR (IC_LEFT (ic));
-
-         /* if result is present && is a true symbol */
-         if (IC_RESULT (ic) && ic->op != IFX &&
-             IS_TRUE_SYMOP (IC_RESULT (ic)))
-           OP_SYMBOL (IC_RESULT (ic))->allocreq = 1;
-
-         /* take away registers from live
-            ranges that end at this instruction */
-         deassignLRs (ic, ebbs[i]);
-
-         /* some don't need registers */
-         if (SKIP_IC2 (ic) ||
-             ic->op == JUMPTABLE ||
-             ic->op == IFX ||
-             ic->op == IPUSH ||
-             ic->op == IPOP ||
-             (IC_RESULT (ic) && POINTER_SET (ic)))
-           continue;
+           /* if this is an ipop that means some live
+              range will have to be assigned again */
+           if (ic->op == IPOP)
+               reassignLR (IC_LEFT (ic));
 
-         /* now we need to allocate registers
-            only for the result */
-         if (IC_RESULT (ic))
-           {
-             symbol *sym = OP_SYMBOL (IC_RESULT (ic));
-             bitVect *spillable;
-             int willCS;
-             int j;
-             int ptrRegSet = 0;
-
-             /* if it does not need or is spilt 
-                or is already assigned to registers
-                or will not live beyond this instructions */
-             if (!sym->nRegs ||
-                 sym->isspilt ||
-                 bitVectBitValue (_G.regAssigned, sym->key) ||
-                 sym->liveTo <= ic->seq)
-               continue;
+           /* if result is present && is a true symbol */
+           if (IC_RESULT (ic) && ic->op != IFX &&
+               IS_TRUE_SYMOP (IC_RESULT (ic)))
+               OP_SYMBOL (IC_RESULT (ic))->allocreq = 1;
 
-             /* if some liverange has been spilt at the block level
-                and this one live beyond this block then spil this
-                to be safe */
-             if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq)
-               {
-                 spillThis (sym);
-                 continue;
-               }
-             /* if trying to allocate this will cause
-                a spill and there is nothing to spill 
-                or this one is rematerializable then
-                spill this one */
-             willCS = willCauseSpill (sym->nRegs, sym->regType);
-             spillable = computeSpillable (ic);
-             if (sym->remat ||
-                 (willCS && bitVectIsZero (spillable)))
-               {
+           /* take away registers from live
+              ranges that end at this instruction */
+           deassignLRs (ic, ebbs[i]);
 
-                 spillThis (sym);
-                 continue;
+           /* some don't need registers */
+           if (SKIP_IC2 (ic) ||
+               ic->op == JUMPTABLE ||
+               ic->op == IFX ||
+               ic->op == IPUSH ||
+               ic->op == IPOP ||
+               (IC_RESULT (ic) && POINTER_SET (ic)))
+               continue;
 
+           /* now we need to allocate registers
+              only for the result */
+           if (IC_RESULT (ic)) {
+               symbol *sym = OP_SYMBOL (IC_RESULT (ic));
+               bitVect *spillable;
+               int willCS;
+               int j;
+               int ptrRegSet = 0;
+
+               /* if it does not need or is spilt 
+                  or is already assigned to registers
+                  or will not live beyond this instructions */
+               if (!sym->nRegs ||
+                   sym->isspilt ||
+                   bitVectBitValue (_G.regAssigned, sym->key) ||
+                   sym->liveTo <= ic->seq)
+                   continue;
+
+               /* if some liverange has been spilt at the block level
+                  and this one live beyond this block then spil this
+                  to be safe */
+               if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq) {
+                   spillThis (sym);
+                   continue;
+               }
+               /* if trying to allocate this will cause
+                  a spill and there is nothing to spill 
+                  or this one is rematerializable then
+                  spill this one */
+               willCS = willCauseSpill (sym->nRegs, sym->regType);
+               spillable = computeSpillable (ic);
+               if (sym->remat || (willCS && bitVectIsZero (spillable))) {                    
+                   spillThis (sym);
+                   continue;                 
                }
 
-             /* if it has a spillocation & is used less than
-                all other live ranges then spill this */
-             if (willCS && sym->usl.spillLoc)
-               {
-
-                 symbol *leastUsed =
-                 leastUsedLR (liveRangesWith (spillable,
-                                              allLRs,
-                                              ebbs[i],
-                                              ic));
-                 if (leastUsed &&
-                     leastUsed->used > sym->used)
-                   {
-                     spillThis (sym);
-                     continue;
+               /* if it has a spillocation & is used less than
+                  all other live ranges then spill this */
+               if (willCS) {
+                   if (sym->usl.spillLoc) {
+                       symbol *leastUsed = leastUsedLR (liveRangesWith (spillable,
+                                                                        allLRs, ebbs[i], ic));
+                       if (leastUsed && leastUsed->used > sym->used) {
+                           spillThis (sym);
+                           continue;
+                       }
+                   } else {
+                       /* 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 we need ptr regs for the right side
-                then mark it */
-             if (POINTER_GET (ic) && IS_SYMOP (IC_LEFT (ic))
-                 && getSize (OP_SYMBOL (IC_LEFT (ic))->type)
-                 <= PTRSIZE)
-               {
-                 mcs51_ptrRegReq++;
-                 ptrRegSet = 1;
+               /* if we need ptr regs for the right side
+                  then mark it */
+               if (POINTER_GET (ic) && IS_SYMOP (IC_LEFT (ic))
+                   && getSize (OP_SYMBOL (IC_LEFT (ic))->type) <= (unsigned int) PTRSIZE) {
+                   mcs51_ptrRegReq++;
+                   ptrRegSet = 1;
+               }
+               /* else we assign registers to it */
+               _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
+
+               for (j = 0; j < sym->nRegs; j++) {
+                   if (sym->regType == REG_PTR)
+                       sym->regs[j] = getRegPtr (ic, ebbs[i], sym);
+                   else
+                       sym->regs[j] = getRegGpr (ic, ebbs[i], sym);
+
+                   /* if the allocation falied which means
+                      this was spilt then break */
+                   if (!sym->regs[j])
+                       break;
                }
-             /* else we assign registers to it */
-             _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
-
-             for (j = 0; j < sym->nRegs; j++)
-               {
-                 if (sym->regType == REG_PTR)
-                   sym->regs[j] = getRegPtr (ic, ebbs[i], sym);
-                 else
-                   sym->regs[j] = getRegGpr (ic, ebbs[i], sym);
 
-                 /* if the allocation falied which means
-                    this was spilt then break */
-                 if (!sym->regs[j])
-                   break;
+               /* if it shares registers with operands make sure
+                  that they are in the same position */
+               if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) &&
+                   OP_SYMBOL (IC_LEFT (ic))->nRegs && ic->op != '=') {
+                   positionRegs (OP_SYMBOL (IC_RESULT (ic)),
+                                 OP_SYMBOL (IC_LEFT (ic)), ic->lineno);
                }
-             /* if it shares registers with operands make sure
-                that they are in the same position */
-             if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) &&
-                 OP_SYMBOL (IC_LEFT (ic))->nRegs && ic->op != '=')
-               positionRegs (OP_SYMBOL (IC_RESULT (ic)),
-                             OP_SYMBOL (IC_LEFT (ic)), ic->lineno);
-             /* do the same for the right operand */
-             if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) &&
-                 OP_SYMBOL (IC_RIGHT (ic))->nRegs)
-               positionRegs (OP_SYMBOL (IC_RESULT (ic)),
-                             OP_SYMBOL (IC_RIGHT (ic)), ic->lineno);
-
-             if (ptrRegSet)
-               {
-                 mcs51_ptrRegReq--;
-                 ptrRegSet = 0;
+               /* do the same for the right operand */
+               if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) &&
+                   OP_SYMBOL (IC_RIGHT (ic))->nRegs) {
+                   positionRegs (OP_SYMBOL (IC_RESULT (ic)),
+                                 OP_SYMBOL (IC_RIGHT (ic)), ic->lineno);
+               }
+
+               if (ptrRegSet) {
+                   mcs51_ptrRegReq--;
+                   ptrRegSet = 0;
                }
 
            }
@@ -1439,6 +1432,7 @@ regTypeNum ()
              (ic = hTabItemWithKey (iCodehTab,
                                     bitVectFirstBit (sym->defs))) &&
              POINTER_GET (ic) &&
+             !sym->noSpilLoc &&
              !IS_BITVAR (sym->etype))
            {
 
@@ -1529,7 +1523,6 @@ farSpacePackable (iCode * ic)
      symbol on the right */
   for (dic = ic->prev; dic; dic = dic->prev)
     {
-
       /* if the definition is a call then no */
       if ((dic->op == CALL || dic->op == PCALL) &&
          IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
@@ -1591,37 +1584,29 @@ static int
 packRegsForAssign (iCode * ic, eBBlock * ebp)
 {
   iCode *dic, *sic;
-  sym_link *etype = operandType (IC_RIGHT (ic));
+  //sym_link *etype = operandType (IC_RIGHT (ic));
 
   if (!IS_ITEMP (IC_RIGHT (ic)) ||
       OP_SYMBOL (IC_RIGHT (ic))->isind ||
-      OP_LIVETO (IC_RIGHT (ic)) > ic->seq ||
-      IS_BITFIELD (etype))
+      OP_LIVETO (IC_RIGHT (ic)) > ic->seq
+      /* why? || IS_BITFIELD (etype) */ )
     {
       return 0;
     }
 
   /* if the true symbol is defined in far space or on stack
      then we should not since this will increase register pressure */
-  if (isOperandInFarSpace (IC_RESULT (ic)))
-    {
-      if ((dic = farSpacePackable (ic)))
-       goto pack;
-      else
-       return 0;
+  if (isOperandInFarSpace(IC_RESULT(ic)) && !farSpacePackable(ic)) {
+    return 0;
+  }
 
-    }
   /* find the definition of iTempNN scanning backwards if we find a 
      a use of the true symbol in before we find the definition then 
      we cannot */
   for (dic = ic->prev; dic; dic = dic->prev)
     {
-
-      /* if there is a function call and this is
-         a parameter & not my parameter then don't pack it */
-      if ((dic->op == CALL || dic->op == PCALL) &&
-         (OP_SYMBOL (IC_RESULT (ic))->_isparm &&
-          !OP_SYMBOL (IC_RESULT (ic))->ismyparm))
+      /* if there is a function call then don't pack it */
+      if ((dic->op == CALL || dic->op == PCALL))
        {
          dic = NULL;
          break;
@@ -1812,6 +1797,7 @@ packRegsForSupport (iCode * ic, eBBlock * ebp)
   /* for the left & right operand :- look to see if the
      left was assigned a true symbol in far space in that
      case replace them */
+
   if (IS_ITEMP (IC_LEFT (ic)) &&
       OP_SYMBOL (IC_LEFT (ic))->liveTo <= ic->seq)
     {
@@ -1835,7 +1821,7 @@ packRegsForSupport (iCode * ic, eBBlock * ebp)
     }
 
   /* do the same for the right operand */
-right:
+ right:
   if (!change &&
       IS_ITEMP (IC_RIGHT (ic)) &&
       OP_SYMBOL (IC_RIGHT (ic))->liveTo <= ic->seq)
@@ -1911,12 +1897,22 @@ packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
   if (bitVectnBitsOn (OP_DEFS (op)) > 1)
     return NULL;               /* has more than one definition */
 
-  /* get the that definition */
+  /* get that definition */
   if (!(dic =
        hTabItemWithKey (iCodehTab,
                         bitVectFirstBit (OP_DEFS (op)))))
     return NULL;
 
+  /* if that only usage is a cast */
+  if (dic->op == CAST) {
+    /* to a bigger type */
+    if (getSize(OP_SYM_TYPE(IC_RESULT(dic))) > 
+       getSize(OP_SYM_TYPE(IC_RIGHT(dic)))) {
+      /* than we can not, since we cannot predict the usage of b & acc */
+      return NULL;
+    }
+  }
+
   /* found the definition now check if it is local */
   if (dic->seq < ebp->fSeq ||
       dic->seq > ebp->lSeq)
@@ -1997,6 +1993,12 @@ packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
        {
          return NULL;
        }
+      /* if left or right or result is on stack */
+      if (isOperandOnStack(IC_LEFT(dic)) ||
+         isOperandOnStack(IC_RIGHT(dic)) ||
+         isOperandOnStack(IC_RESULT(dic))) {
+       return NULL;
+      }
     }
 
   OP_SYMBOL (op)->ruonly = 1;
@@ -2016,17 +2018,17 @@ isBitwiseOptimizable (iCode * ic)
   /* bitwise operations are considered optimizable
      under the following conditions (Jean-Louis VERN) 
 
-     x & lit   <== jwk: should be x && lit
+     x & lit
      bit & bit
      bit & x
      bit ^ bit
      bit ^ x
-     x   ^ lit <== jwk: should be x ^^ lit
-     x   | lit <== jwk: should be x || lit
+     x   ^ lit
+     x   | lit
      bit | bit
      bit | x
-   */
-  if ( /* jwk IS_LITERAL (rtype) || */
+  */
+  if (IS_LITERAL(rtype) ||
       (IS_BITVAR (ltype) && IN_BITSPACE (SPEC_OCLS (ltype))))
     return TRUE;
   else
@@ -2138,6 +2140,10 @@ packRegsForAccUse (iCode * ic)
       IC_LEFT (uic)->key != IC_RESULT (ic)->key)
     return;
 
+#if 0
+  // this is too dangerous and need further restrictions
+  // see bug #447547
+
   /* if one of them is a literal then we can */
   if ((IC_LEFT (uic) && IS_OP_LITERAL (IC_LEFT (uic))) ||
       (IC_RIGHT (uic) && IS_OP_LITERAL (IC_RIGHT (uic))))
@@ -2145,6 +2151,7 @@ packRegsForAccUse (iCode * ic)
       OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
       return;
     }
+#endif
 
   /* if the other one is not on stack then we can */
   if (IC_LEFT (uic)->key == IC_RESULT (ic)->key &&
@@ -2195,13 +2202,27 @@ packForPush (iCode * ic, eBBlock * ebp)
   /* make sure the right side does not have any definitions
      inbetween */
   dbv = OP_DEFS(IC_RIGHT(dic));
-  for (lic = ic; lic != dic ; lic = lic->prev) {
-         if (bitVectBitValue(dbv,lic->key)) return ;
+  for (lic = ic; lic && lic != dic ; lic = lic->prev) {
+    if (bitVectBitValue(dbv,lic->key)) 
+      return ;
+  }
+  /* make sure they have the same type */
+  {
+    sym_link *itype=operandType(IC_LEFT(ic));
+    sym_link *ditype=operandType(IC_RIGHT(dic));
+
+    if (SPEC_USIGN(itype)!=SPEC_USIGN(ditype) ||
+       SPEC_LONG(itype)!=SPEC_LONG(ditype))
+      return;
+  }
+  /* extend the live range of replaced operand if needed */
+  if (OP_SYMBOL(IC_RIGHT(dic))->liveTo < ic->seq) {
+         OP_SYMBOL(IC_RIGHT(dic))->liveTo = ic->seq;
   }
   /* we now we know that it has one & only one def & use
      and the that the definition is an assignment */
   IC_LEFT (ic) = IC_RIGHT (dic);
-
+   
   remiCodeFromeBBlock (ebp, dic);
   hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
 }
@@ -2238,8 +2259,7 @@ packRegisters (eBBlock * ebp)
 
   for (ic = ebp->sch; ic; ic = ic->next)
     {
-
-      /* if this is an itemp & result of a address of a true sym 
+      /* if this is an itemp & result of an address of a true sym 
          then mark this as rematerialisable   */
       if (ic->op == ADDRESS_OF &&
          IS_ITEMP (IC_RESULT (ic)) &&
@@ -2278,8 +2298,6 @@ packRegisters (eBBlock * ebp)
           bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
           IS_OP_LITERAL (IC_RIGHT (ic))))
        {
-
-         //int i = operandLitValue (IC_RIGHT (ic));
          OP_SYMBOL (IC_RESULT (ic))->remat = 1;
          OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
          OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
@@ -2317,11 +2335,13 @@ packRegisters (eBBlock * ebp)
        }
 
       /* if the condition of an if instruction
-         is defined in the previous instruction then
+         is defined in the previous instruction and
+        this is the only usage then
          mark the itemp as a conditional */
       if ((IS_CONDITIONAL (ic) ||
           (IS_BITWISE_OP(ic) && isBitwiseOptimizable (ic))) &&
          ic->next && ic->next->op == IFX &&
+         bitVectnBitsOn (OP_USES(IC_RESULT(ic)))==1 &&
          isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) &&
          OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq)
        {
@@ -2337,8 +2357,14 @@ packRegisters (eBBlock * ebp)
          can be eliminated for return statements */
       if ((ic->op == RETURN || ic->op == SEND) &&
          !isOperandInFarSpace (IC_LEFT (ic)) &&
-         options.model == MODEL_SMALL)
-       packRegsForOneuse (ic, IC_LEFT (ic), ebp);
+         options.model == MODEL_SMALL) {
+       if (0 && options.stackAuto) {
+         /* we should check here if acc will be clobbered for stack
+            offset calculations */
+       } else {
+         packRegsForOneuse (ic, IC_LEFT (ic), ebp);
+       }
+      }
 
       /* if pointer set & left has a size more than
          one and right is not in far space */
@@ -2379,7 +2405,7 @@ packRegisters (eBBlock * ebp)
              if (dic)
                {
                  if (IS_ARITHMETIC_OP (dic))
-                   {
+                   {                  
                      IC_RESULT (dic) = IC_RESULT (ic);
                      remiCodeFromeBBlock (ebp, ic);
                      hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
@@ -2395,7 +2421,7 @@ packRegisters (eBBlock * ebp)
 
              /* if the type from and type to are the same
                 then if this is the only use then packit */
-             if (checkType (operandType (IC_RIGHT (ic)),
+             if (compareType (operandType (IC_RIGHT (ic)),
                             operandType (IC_LEFT (ic))) == 1)
                {
                  iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
@@ -2440,7 +2466,6 @@ packRegisters (eBBlock * ebp)
          getSize (operandType (IC_RESULT (ic))) <= 2)
 
        packRegsForAccUse (ic);
-
     }
 }
 
@@ -2455,12 +2480,7 @@ mcs51_assignRegisters (eBBlock ** ebbs, int count)
 
   setToNull ((void *) &_G.funcrUsed);
   mcs51_ptrRegReq = _G.stackExtend = _G.dataExtend = 0;
-  /* if not register extentions then reduce number
-     of registers */
-  if (options.regExtend)
-    mcs51_nRegs = 13;
-  else
-    mcs51_nRegs = 8;
+  mcs51_nRegs = 8;
 
   /* change assignments this will remove some
      live ranges reducing some register pressure */
@@ -2468,7 +2488,7 @@ mcs51_assignRegisters (eBBlock ** ebbs, int count)
     packRegisters (ebbs[i]);
 
   if (options.dump_pack)
-    dumpEbbsToFileExt (".dumppack", ebbs, count);
+    dumpEbbsToFileExt (DUMP_PACK, ebbs, count);
 
   /* first determine for each live range the number of 
      registers & the type of registers required for each */
@@ -2501,8 +2521,8 @@ mcs51_assignRegisters (eBBlock ** ebbs, int count)
 
   if (options.dump_rassgn)
     {
-      dumpEbbsToFileExt (".dumprassgn", ebbs, count);
-      dumpLiveRanges (".dumplrange", liveRanges);
+      dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count);
+      dumpLiveRanges (DUMP_LRANGE, liveRanges);
     }
 
   /* do the overlaysegment stuff SDCCmem.c */
@@ -2511,7 +2531,6 @@ mcs51_assignRegisters (eBBlock ** ebbs, int count)
   /* now get back the chain */
   ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count));
 
-
   gen51Code (ic);
 
   /* free up any _G.stackSpil locations allocated */