* device/lib/pic16/Makefile.common.in: added MODELFLAGS again, it was erroneously...
[fw/sdcc] / src / SDCCloop.c
index 0be4da81cb3dcaf2976c81905cb3f69313716e4a..556f452ea2289a1625b7586a9536cab55ab2be64 100644 (file)
@@ -39,14 +39,14 @@ newInduction (operand * sym, unsigned int op,
 {
   induction *ip;
 
-  ip = Safe_calloc (1, sizeof (induction));
+  ip = Safe_alloc ( sizeof (induction));
 
   ip->sym = sym;
   ip->asym = asym;
   ip->op = op;
   ip->cval = constVal;
   ip->ic = ic;
-  updateSpillLocation(ic,1);
+//updateSpillLocation(ic,1);
   return ip;
 }
 
@@ -58,7 +58,7 @@ newRegion ()
 {
   region *lp;
 
-  lp = Safe_calloc (1, sizeof (region));
+  lp = Safe_alloc ( sizeof (region));
 
   return lp;
 }
@@ -148,7 +148,7 @@ intersectLoopSucc (set * lexits, eBBlock ** ebbs)
 /*-----------------------------------------------------------------*/
 /* loopInsert will insert a block into the loop set                */
 /*-----------------------------------------------------------------*/
-static void 
+static void
 loopInsert (set ** regionSet, eBBlock * block)
 {
   if (!isinSet (*regionSet, block))
@@ -188,7 +188,7 @@ DEFSETFUNC (isNotInBlocks)
 /* hasIncomingDefs - has definitions coming into the loop. i.e.    */
 /* check to see if the preheaders outDefs has any definitions      */
 /*-----------------------------------------------------------------*/
-int 
+int
 hasIncomingDefs (region * lreg, operand * op)
 {
   eBBlock *preHdr = lreg->entry->preHeader;
@@ -202,7 +202,7 @@ hasIncomingDefs (region * lreg, operand * op)
 /* findLoopEndSeq - will return the sequence number of the last    */
 /* iCode with the maximum dfNumber in the region                   */
 /*-----------------------------------------------------------------*/
-int 
+int
 findLoopEndSeq (region * lreg)
 {
   eBBlock *block;
@@ -231,10 +231,10 @@ DEFSETFUNC (addToExitsMarkDepth)
   V_ARG (region *, lr);
 
   /* mark the loop depth of this block */
-  if (!ebp->depth)
+  //if (!ebp->depth)
+  if (ebp->depth<depth)
     ebp->depth = depth;
 
-  /* put the loop region info in the block */
   /* NOTE: here we will update only the inner most loop
      that it is a part of */
   if (!ebp->partOfLoop)
@@ -306,14 +306,14 @@ DEFSETFUNC (addDefInExprs)
   V_ARG (int, count);
 
   addSetHead (&ebp->inExprs, cdp);
-  cseBBlock (ebp, 0, ebbs, count);
+  cseBBlock (ebp, optimize.global_cse, ebbs, count);
   return 0;
 }
 
 /*-----------------------------------------------------------------*/
 /* assignmentsToSym - for a set of blocks determine # time assigned */
 /*-----------------------------------------------------------------*/
-int 
+int
 assignmentsToSym (set * sset, operand * sym)
 {
   eBBlock *ebp;
@@ -328,7 +328,7 @@ assignmentsToSym (set * sset, operand * sym)
          in this block */
       bitVect *defs = bitVectIntersect (ebp->ldefs, OP_DEFS (sym));
       assigns += bitVectnBitsOn (defs);
-      setToNull ((void **) &defs);
+      setToNull ((void *) &defs);
 
     }
 
@@ -339,7 +339,7 @@ assignmentsToSym (set * sset, operand * sym)
 /*-----------------------------------------------------------------*/
 /* isOperandInvariant - determines if an operand is an invariant   */
 /*-----------------------------------------------------------------*/
-int 
+int
 isOperandInvariant (operand * op, region * theLoop, set * lInvars)
 {
   int opin = 0;
@@ -379,7 +379,22 @@ DEFSETFUNC (pointerAssigned)
   eBBlock *ebp = item;
   V_ARG (operand *, op);
 
-  return ebp->hasFcall || bitVectBitValue (ebp->ptrsSet, op->key);
+  if (ebp->hasFcall)
+    return 1;
+
+  if (bitVectBitValue (ebp->ptrsSet, op->key))
+    return 1;
+
+  /* Unfortunately, one of the other pointer set operations  */
+  /* may be using an alias of this operand, and the above    */
+  /* test would miss it. To be thorough, some aliasing       */
+  /* analysis should be done here. In the meantime, be       */
+  /* conservative and assume any other pointer set operation */
+  /* is dangerous                                            */
+  if (!bitVectIsZero (ebp->ptrsSet))
+    return 1;
+
+  return 0;
 }
 
 /*-----------------------------------------------------------------*/
@@ -401,7 +416,7 @@ DEFSETFUNC (hasNonPtrUse)
 /*-----------------------------------------------------------------*/
 /* loopInvariants - takes loop invariants out of region            */
 /*-----------------------------------------------------------------*/
-int 
+int
 loopInvariants (region * theLoop, eBBlock ** ebbs, int count)
 {
   eBBlock *lBlock;
@@ -416,8 +431,8 @@ loopInvariants (region * theLoop, eBBlock ** ebbs, int count)
       theLoop->exits == NULL)
     return 0;
 
-  /* we will do the elimination for those blocks        */
-  /* in the loop that dominates all exits from the loop */
+  /* we will do the elimination for those blocks       */
+  /* in the loop that dominate all exits from the loop */
   for (lBlock = setFirstItem (theLoop->regBlocks); lBlock;
        lBlock = setNextItem (theLoop->regBlocks))
     {
@@ -445,16 +460,33 @@ loopInvariants (region * theLoop, eBBlock ** ebbs, int count)
          int lin, rin;
          cseDef *ivar;
 
-         /* if there are function calls in this block and this
-            is a pointer get, the function could have changed it
-            so skip, ISO-C99 according to David A. Long */
-         if (fCallsInBlock && POINTER_GET(ic)) {
-           continue;
+         /* TODO this is only needed if the call is between
+            here and the definition, but I am too lazy to do that now */
+
+         /* if there are function calls in this block */
+         if (fCallsInBlock) {
+
+           /* if this is a pointer get */
+           if (POINTER_GET(ic)) {
+             continue;
+           }
+
+           /* if this is an assignment from a global */
+           if (ic->op=='=' && isOperandGlobal(IC_RIGHT(ic))) {
+             continue;
+           }
          }
 
          if (SKIP_IC (ic) || POINTER_SET (ic) || ic->op == IFX)
            continue;
 
+         /* iTemp assignment from a literal may be invariant, but it
+            will needlessly increase register pressure if the
+            iCode(s) that use this iTemp are not also invariant */
+         if (ic->op=='=' && IS_ITEMP (IC_RESULT (ic))
+             && IS_OP_LITERAL (IC_RIGHT (ic)))
+           continue;
+
          /* if result is volatile then skip */
          if (IC_RESULT (ic) &&
              (isOperandVolatile (IC_RESULT (ic), TRUE) ||
@@ -467,7 +499,7 @@ loopInvariants (region * theLoop, eBBlock ** ebbs, int count)
            continue;
 
          lin = rin = 0;
-         
+
          /* special case */
          /* if address of then it is an invariant */
          if (ic->op == ADDRESS_OF &&
@@ -481,14 +513,14 @@ loopInvariants (region * theLoop, eBBlock ** ebbs, int count)
                 that the pointer set does not exist in
                 any of the blocks */
              if (POINTER_GET (ic) &&
-                 (applyToSet (theLoop->regBlocks, 
+                 (applyToSet (theLoop->regBlocks,
                               pointerAssigned, IC_LEFT (ic))))
                lin = 0;
          }
-         
+
          /* do the same for right */
          rin = isOperandInvariant (IC_RIGHT (ic), theLoop, lInvars);
-         
+
          /* if this is a POINTER_GET then special case, make sure all
             usages within the loop are POINTER_GET any other usage
             would mean that this is not an invariant , since the pointer
@@ -497,18 +529,19 @@ loopInvariants (region * theLoop, eBBlock ** ebbs, int count)
              applyToSet (theLoop->regBlocks, hasNonPtrUse, IC_LEFT (ic)))
            continue;
 
-         /* if both the left & right are invariants : then check that */
-         /* this definition exists in the out definition of all the  */
-         /* blocks, this will ensure that this is not assigned any   */
-         /* other value in the loop , and not used in this block     */
+
+          /* if both the left & right are invariants : then check that */
+         /* this definition exists in the out definition of all the   */
+         /* blocks, this will ensure that this is not assigned any    */
+         /* other value in the loop, and not used in this block       */
          /* prior to this definition which means only this definition */
-         /* is used in this loop                                     */
+         /* is used in this loop                                      */
          if (lin && rin && IC_RESULT (ic))
            {
              eBBlock *sBlock;
              set *lSet = setFromSet (theLoop->regBlocks);
 
-             /* if this block does not dominate all exists */
+             /* if this block does not dominate all exits */
              /* make sure this defintion is not used anywhere else */
              if (!domsAllExits)
                {
@@ -544,6 +577,20 @@ loopInvariants (region * theLoop, eBBlock ** ebbs, int count)
                    }
                  else if (bitVectBitsInCommon (sBlock->defSet, OP_DEFS (IC_RESULT (ic))))
                    break;
+
+                  if (IC_RESULT(ic))
+                    {
+                      iCode *ic2;
+                      /* check that this definition is not assigned */
+                      /* any other value in this block */
+                      for (ic2 = sBlock->sch; ic2; ic2 = ic2->next)
+                        {
+                          if ((ic != ic2) && (isOperandEqual(IC_RESULT(ic), IC_RESULT(ic2))))
+                            break;
+                        }
+                      if (ic2) /* found another definition */
+                        break;
+                    }
                }
 
              if (sBlock)
@@ -557,7 +604,9 @@ loopInvariants (region * theLoop, eBBlock ** ebbs, int count)
              /* now we know it is a true invariant */
              /* remove it from the insts chain & put */
              /* in the invariant set                */
-             OP_SYMBOL (IC_RESULT (ic))->isinvariant = 1;
+
+              OP_SYMBOL (IC_RESULT (ic))->isinvariant = 1;
+              SPIL_LOC (IC_RESULT (ic)) = NULL;
              remiCodeFromeBBlock (lBlock, ic);
 
              /* maintain the data flow */
@@ -620,7 +669,7 @@ loopInvariants (region * theLoop, eBBlock ** ebbs, int count)
 /*-----------------------------------------------------------------*/
 /* addressTaken - returns true if the symbol is found in the addrof */
 /*-----------------------------------------------------------------*/
-int 
+int
 addressTaken (set * sset, operand * sym)
 {
   set *loop;
@@ -798,13 +847,6 @@ basicInduction (region * loopReg, eBBlock ** ebbs, int count)
          OP_SYMBOL (IC_RESULT (indIc))->isind = 1;
          ip = newInduction (IC_RIGHT (ic), dic->op, litValue, indIc, NULL);
 
-         if (1) {
-           fprintf (stderr, "%s:%d: stupid way to avoid bug #467035, but\n"
-                    "this will keep the regressions tests going.\n",
-                    __FILE__, __LINE__);
-           continue;
-         }
-
          /* replace the inducted variable by the iTemp */
          replaceSymBySym (loopReg->regBlocks, IC_RESULT (ic), IC_RIGHT (ic));
 
@@ -814,7 +856,6 @@ basicInduction (region * loopReg, eBBlock ** ebbs, int count)
          if (nexits == 1)
            {
              eBBlock *exit = setFirstItem (loopReg->exits);
-
              /* if it is the same block then there is no
                 need to move it about */
              if (exit != lBlock)
@@ -852,7 +893,18 @@ basicInduction (region * loopReg, eBBlock ** ebbs, int count)
                      if (bitVectBitValue (loopSuccs, i))
                        {
 
-                         eBBlock *eblock = ebbs[i];
+                         eBBlock *eblock = NULL;
+                         int j;
+
+                         /* Need to search for bbnum == i since ebbs is  */
+                         /* sorted by dfnum; a direct index won't do.  */
+                         for (j=0; j<count; j++)
+                           if (ebbs[j]->bbnum == i)
+                             {
+                               eblock = ebbs[j];
+                               break;
+                             }
+                         assert(eblock);
 
                          /* if the successor does not belong to the loop
                             and will be executed after the loop : then
@@ -864,9 +916,9 @@ basicInduction (region * loopReg, eBBlock ** ebbs, int count)
                              iCode *newic = newiCode ('=', NULL,
                                        operandFromOperand (IC_RIGHT (ic)));
                              IC_RESULT (newic) = operandFromOperand (IC_RESULT (ic));
-                             OP_DEFS (IC_RESULT (newic)) =
+                             OP_DEFS(IC_RESULT (newic))=
                                bitVectSetBit (OP_DEFS (IC_RESULT (newic)), newic->key);
-                             OP_USES (IC_RIGHT (newic)) =
+                             OP_USES(IC_RIGHT (newic))=
                                bitVectSetBit (OP_USES (IC_RIGHT (newic)), newic->key);
                              /* and add it */
                              if (eblock->sch && eblock->sch->op == LABEL)
@@ -892,7 +944,7 @@ basicInduction (region * loopReg, eBBlock ** ebbs, int count)
 /*-----------------------------------------------------------------*/
 /* loopInduction - remove induction variables from a loop          */
 /*-----------------------------------------------------------------*/
-int 
+int
 loopInduction (region * loopReg, eBBlock ** ebbs, int count)
 {
   int change = 0;
@@ -1050,10 +1102,10 @@ loopInduction (region * loopReg, eBBlock ** ebbs, int count)
       /* add the induction variable vector to the last
          block in the loop */
       lastBlock->isLastInLoop = 1;
-      lastBlock->linds = indVect;
+      lastBlock->linds = bitVectUnion(lastBlock->linds,indVect);
     }
 
-  setToNull ((void **) &indVars);
+  setToNull ((void *) &indVars);
   return change;
 }
 
@@ -1081,7 +1133,7 @@ DEFSETFUNC (mergeRegions)
       if (lp->entry == theLoop->entry)
        {
          theLoop->regBlocks = unionSets (theLoop->regBlocks,
-                                         lp->regBlocks, THROW_BOTH);
+                                         lp->regBlocks, THROW_DEST);
          lp->merged = 1;
        }
     }
@@ -1164,6 +1216,7 @@ createLoopRegions (eBBlock ** ebbs, int count)
 
   applyToSet (allRegion, mergeInnerLoops, allRegion, &maxDepth);
   maxDepth++;
+
   /* now create all the exits .. also */
   /* create an ordered set of loops   */
   /* i.e. we process loops in the inner to outer order */
@@ -1182,7 +1235,7 @@ createLoopRegions (eBBlock ** ebbs, int count)
 /*-----------------------------------------------------------------*/
 /* loopOptimizations - identify region & remove invariants & ind   */
 /*-----------------------------------------------------------------*/
-int 
+int
 loopOptimizations (hTab * orderedLoops, eBBlock ** ebbs, int count)
 {
   region *lp;