* src/SDCCicode.h: moved CRITICAL and ENDCRITICAL from SKIP_IC2 to SKIP_IC
[fw/sdcc] / src / SDCCopt.c
index a4c7de2261b6a42e56537c9821350e8ce2ef8f14..f7e67ce66cf3bd6f195da5534f806dc214ff4b21 100644 (file)
@@ -176,6 +176,23 @@ cnvToFcall (iCode * ic, eBBlock * ebp)
   IC_RESULT (newic) = IC_RESULT (ic);
   newic->lineno = lineno;
   newic->parmBytes+=bytesPushed;
+  ebp->hasFcall = 1;
+  if (currFunc)
+    FUNC_HASFCALL (currFunc->type) = 1;
+    
+  if(TARGET_IS_PIC16) {
+       /* normally these functions aren't marked external, so we can use their
+        * _extern field to marked as already added to symbol table */
+
+       if(!SPEC_EXTR(func->etype)) {
+           memmap *seg = SPEC_OCLS(OP_SYMBOL(IC_LEFT(newic))->etype);
+               
+               SPEC_EXTR(func->etype) = 1;
+               seg = SPEC_OCLS( func->etype );
+               addSet(&seg->syms, func);
+       }
+  }
+
   addiCodeToeBBlock (ebp, newic, ip);
 }
 
@@ -250,9 +267,25 @@ found:
   newic = newiCode (CALL, operandFromSymbol (func), NULL);
   IC_RESULT (newic) = IC_RESULT (ic);
   newic->parmBytes+=bytesPushed;
+  ebp->hasFcall = 1;
+  if (currFunc)
+    FUNC_HASFCALL (currFunc->type) = 1;
+
+  if(TARGET_IS_PIC16) {
+       /* normally these functions aren't marked external, so we can use their
+        * _extern field to marked as already added to symbol table */
+
+       if(!SPEC_EXTR(func->etype)) {
+           memmap *seg = SPEC_OCLS(OP_SYMBOL(IC_LEFT(newic))->etype);
+               
+               SPEC_EXTR(func->etype) = 1;
+               seg = SPEC_OCLS( func->etype );
+               addSet(&seg->syms, func);
+       }
+  }
+
   addiCodeToeBBlock (ebp, newic, ip);
   newic->lineno = linenno;
-
 }
 
 /*-----------------------------------------------------------------*/
@@ -327,9 +360,25 @@ found:
   newic = newiCode (CALL, operandFromSymbol (func), NULL);
   IC_RESULT (newic) = IC_RESULT (ic);
   newic->parmBytes+=bytesPushed;
+  ebp->hasFcall = 1;
+  if (currFunc)
+    FUNC_HASFCALL (currFunc->type) = 1;
+
+  if(TARGET_IS_PIC16) {
+       /* normally these functions aren't marked external, so we can use their
+        * _extern field to marked as already added to symbol table */
+
+       if(!SPEC_EXTR(func->etype)) {
+           memmap *seg = SPEC_OCLS(OP_SYMBOL(IC_LEFT(newic))->etype);
+               
+               SPEC_EXTR(func->etype) = 1;
+               seg = SPEC_OCLS( func->etype );
+               addSet(&seg->syms, func);
+       }
+  }
+
   addiCodeToeBBlock (ebp, newic, ip);
   newic->lineno = lineno;
-
 }
 
 extern operand *geniCodeRValue (operand *, bool);
@@ -348,34 +397,8 @@ convilong (iCode * ic, eBBlock * ebp, sym_link * type, int op)
   int su;
   int bytesPushed=0;
 
-  // Easy special case which avoids function call: modulo by a literal power 
-  // of two can be replaced by a bitwise AND.
-  if (op == '%' && isOperandLiteral(IC_RIGHT(ic)))
-  {
-      unsigned litVal = (unsigned)(operandLitValue(IC_RIGHT(ic)));
-      
-      // See if literal value is a power of 2.
-      while (litVal && !(litVal & 1))
-      {
-         litVal >>= 1;
-      }
-      if (litVal)
-      {
-         // discard first high bit set.
-         litVal >>= 1;
-      }
-         
-      if (!litVal)
-      {
-         ic->op = BITWISEAND;
-         IC_RIGHT(ic) = operandFromLit(operandLitValue(IC_RIGHT(ic)) - 1);
-         return;
-      }
-  }
-    
   remiCodeFromeBBlock (ebp, ic);    
     
-    
   /* depending on the type */
   for (bwd = 0; bwd < 3; bwd++)
     {
@@ -477,6 +500,23 @@ found:
   IC_RESULT (newic) = IC_RESULT (ic);
   newic->lineno = lineno;
   newic->parmBytes+=bytesPushed; // to clear the stack after the call
+  ebp->hasFcall = 1;
+  if (currFunc)
+    FUNC_HASFCALL (currFunc->type) = 1;
+
+  if(TARGET_IS_PIC16) {
+       /* normally these functions aren't marked external, so we can use their
+        * _extern field to marked as already added to symbol table */
+
+       if(!SPEC_EXTR(func->etype)) {
+           memmap *seg = SPEC_OCLS(OP_SYMBOL(IC_LEFT(newic))->etype);
+               
+               SPEC_EXTR(func->etype) = 1;
+               seg = SPEC_OCLS( func->etype );
+               addSet(&seg->syms, func);
+       }
+  }
+
   addiCodeToeBBlock (ebp, newic, ip);
 }
 
@@ -516,6 +556,32 @@ convertToFcall (eBBlock ** ebbs, int count)
                cnvToFloatCast (ic, ebbs[i]);
            }
 
+          // Easy special case which avoids function call: modulo by a literal power
+          // of two can be replaced by a bitwise AND.
+          if (ic->op == '%' && isOperandLiteral(IC_RIGHT(ic)) &&
+              IS_UNSIGNED(operandType(IC_LEFT(ic))))
+            {
+              unsigned litVal = abs(operandLitValue(IC_RIGHT(ic)));
+
+              // See if literal value is a power of 2.
+              while (litVal && !(litVal & 1))
+                {
+                  litVal >>= 1;
+                }
+              if (litVal)
+                {
+                  // discard lowest set bit.
+                  litVal >>= 1;
+                }
+
+              if (!litVal)
+                {
+                  ic->op = BITWISEAND;
+                  IC_RIGHT(ic) = operandFromLit(operandLitValue(IC_RIGHT(ic)) - 1);
+                  continue;
+                }
+            }
+
          /* if long / int mult or divide or mod */
          if (ic->op == '*' || ic->op == '/' || ic->op == '%')
            {
@@ -557,10 +623,7 @@ convertToFcall (eBBlock ** ebbs, int count)
 static int
 isLocalWithoutDef (symbol * sym)
 {
-  if (!sym->level)
-    return 0;
-  
-  if (IS_STATIC (sym->etype))
+  if (!IS_AUTO (sym))
     return 0;
   
   if (IS_VOLATILE (sym->type))
@@ -716,6 +779,51 @@ replaceRegEqv (eBBlock ** ebbs, int count)
     }
 }
 
+/*-----------------------------------------------------------------*/
+/* findReqv - search for a register equivalent                     */
+/*-----------------------------------------------------------------*/
+operand *
+findReqv (symbol * prereqv, eBBlock ** ebbs, int count)
+{
+  int i;
+  iCode * ic;
+  
+  /* for all blocks do */
+  for (i=0; i<count; i++)
+    {
+      /* for all instructions in the block do */
+      for (ic = ebbs[i]->sch; ic; ic = ic->next)
+       {
+         if (ic->op == IFX)
+           {
+             if (IS_ITEMP (IC_COND (ic))
+                 && OP_SYMBOL (IC_COND (ic))->prereqv == prereqv)
+               return IC_COND (ic);
+           }
+         else if (ic->op == JUMPTABLE)
+           {
+             if (IS_ITEMP (IC_JTCOND (ic))
+                 && OP_SYMBOL (IC_JTCOND (ic))->prereqv == prereqv)
+               return IC_JTCOND (ic);
+           }
+         else
+           {
+             if (IS_ITEMP (IC_LEFT (ic))
+                 && OP_SYMBOL (IC_LEFT (ic))->prereqv == prereqv)
+               return IC_LEFT (ic);
+             if (IS_ITEMP (IC_RIGHT (ic))
+                 && OP_SYMBOL (IC_RIGHT (ic))->prereqv == prereqv)
+               return IC_RIGHT (ic);
+             if (IS_ITEMP (IC_RESULT (ic))
+                 && OP_SYMBOL (IC_RESULT (ic))->prereqv == prereqv)
+               return IC_RESULT (ic);
+           }
+       }
+    }
+  
+  return NULL;
+}
+
 /*-----------------------------------------------------------------*/
 /* killDeadCode - eliminates dead assignments                      */
 /*-----------------------------------------------------------------*/
@@ -775,7 +883,8 @@ killDeadCode (eBBlock ** ebbs, int count)
              if (IC_RESULT (ic) && POINTER_SET (ic))
                continue;
               
-              if (POINTER_GET (ic) && IS_VOLATILE (operandType (IC_LEFT (ic))->next))
+              if (POINTER_GET (ic) && IS_VOLATILE (operandType (IC_LEFT (ic))->next)
+                 && !SPIL_LOC (IC_RESULT (ic)))
                 continue;
 
              /* if the result is used in the remainder of the */
@@ -824,7 +933,10 @@ killDeadCode (eBBlock ** ebbs, int count)
                  bool volRight = IS_SYMOP (IC_RIGHT (ic)) 
                                  && isOperandVolatile (IC_RIGHT (ic), FALSE);
 
-                 
+                 /* a dead address-of operation should die, even if volatile */
+                 if (ic->op == ADDRESS_OF)
+                   volLeft = FALSE;
+
                  if (ic->next && ic->seqPoint == ic->next->seqPoint
                      && (ic->next->op == '+' || ic->next->op == '-'))
                    {
@@ -836,6 +948,16 @@ killDeadCode (eBBlock ** ebbs, int count)
                        volRight = FALSE;
                    }
                  
+                 if (POINTER_GET (ic) && IS_VOLATILE (operandType (IC_LEFT (ic))->next))
+                   {
+                     if (SPIL_LOC (IC_RESULT (ic)))
+                       {
+                         IC_RESULT (ic) = newiTempFromOp (IC_RESULT (ic));
+                         SPIL_LOC (IC_RESULT (ic)) = NULL;
+                       }
+                     continue;
+                   }
+                 
                  change = 1;
                  gchange++;
                  
@@ -846,6 +968,29 @@ killDeadCode (eBBlock ** ebbs, int count)
                  /* and defset of the block */
                  bitVectUnSetBit (ebbs[i]->defSet, ic->key);
 
+                 /* If this is the last of a register equivalent, */
+                 /* look for a successor register equivalent. */
+                 bitVectUnSetBit (OP_DEFS (IC_RESULT (ic)), ic->key);
+                 if (IS_ITEMP (IC_RESULT (ic))
+                     && OP_SYMBOL (IC_RESULT (ic))->isreqv
+                     && bitVectIsZero (OP_DEFS (IC_RESULT (ic))))
+                   {
+                     symbol * resultsym = OP_SYMBOL (IC_RESULT (ic));
+                     symbol * prereqv = resultsym->prereqv;
+                     
+                     if (OP_SYMBOL (prereqv->reqv) == resultsym)
+                       {
+                         operand * newreqv;
+
+                         IC_RESULT (ic) = NULL;
+                         newreqv = findReqv (prereqv, ebbs, count);
+                         if (newreqv)
+                           {
+                             prereqv->reqv = newreqv;
+                           }
+                       }
+                   }
+
                  /* delete the result */
                  IC_RESULT (ic) = NULL;
                  
@@ -938,6 +1083,76 @@ discardDeadParamReceives (eBBlock ** ebbs, int count)
     }
 }
 
+/*-----------------------------------------------------------------*/
+/* optimizeCastCast - remove unneeded intermediate casts.          */
+/* Integer promotion may cast (un)signed char to int and then      */
+/* recast the int to (un)signed long. If the signedness of the     */
+/* char and long are the same, the cast can be safely performed in */
+/* a single step.                                                  */
+/*-----------------------------------------------------------------*/
+static void 
+optimizeCastCast (eBBlock ** ebbs, int count)
+{
+  int i;
+  iCode *ic;
+  iCode *uic;
+  sym_link * type1;
+  sym_link * type2;
+  sym_link * type3;
+  symbol * sym;
+
+  for (i = 0; i < count; i++)
+    {
+      for (ic = ebbs[i]->sch; ic; ic = ic->next)
+       {
+         
+         if (ic->op == CAST && IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
+           {
+             type1 = operandType (IC_RIGHT (ic));
+             type2 = operandType (IC_RESULT (ic));
+
+             /* Look only for a cast from an integer type to an */
+             /* integer type that has no loss of bits */
+             if (!IS_INTEGRAL (type1) || !IS_INTEGRAL (type2))
+               continue;
+             if (getSize (type2) < getSize (type1))
+               continue;
+             
+             /* There must be only one use of this first result */
+             if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) != 1)
+               continue;
+             
+             /* This use must be a second cast */
+             uic = hTabItemWithKey (iCodehTab,
+                       bitVectFirstBit (OP_USES (IC_RESULT (ic))));
+             if (!uic || uic->op != CAST)
+               continue;
+  
+             /* It must be a cast to another integer type that */
+             /* has no loss of bits */
+             type3 = operandType (IC_RESULT (uic));
+             if (!IS_INTEGRAL (type3))
+                continue;
+             if (getSize (type3) < getSize (type2))
+                continue;
+             
+             /* The signedness between the first and last types */
+             /* must match */
+             if (SPEC_USIGN (type3) != SPEC_USIGN (type1))
+                continue;
+
+             /* Change the first cast to a simple assignment and */
+             /* let the second cast do all the work */
+             ic->op = '=';
+             IC_LEFT (ic) = NULL;
+             sym = OP_SYMBOL (IC_RESULT (ic));
+             sym->type = copyLinkChain (type1);
+             sym->etype = getSpec (sym->type);
+           }
+       }
+    }
+}
+
 /*-----------------------------------------------------------------*/
 /* eBBlockFromiCode - creates extended basic blocks from iCode     */
 /*                    will return an array of eBBlock pointers     */
@@ -995,6 +1210,8 @@ eBBlockFromiCode (iCode * ic)
   if (options.dump_raw)
     dumpEbbsToFileExt (DUMP_RAW1, ebbs, count);
 
+  optimizeCastCast (ebbs, saveCount);
+    
   /* do common subexpression elimination for each block */
   change = cseAllBlocks (ebbs, saveCount, FALSE);