* src/SDCCopt.c (killDeadCode): checking for right operand can cause
[fw/sdcc] / src / SDCCopt.c
index 4e9c2a7be560647efde1841a42b6a0a9efcf780c..af7d6b6d2e9bf456e6e98ea4c03fc4d2e67ec7d3 100644 (file)
@@ -176,7 +176,10 @@ 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 */
@@ -264,6 +267,9 @@ 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
@@ -354,6 +360,9 @@ 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
@@ -388,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++)
     {
@@ -517,6 +500,9 @@ 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
@@ -570,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 == '%')
            {
@@ -611,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))
@@ -870,11 +879,20 @@ killDeadCode (eBBlock ** ebbs, int count)
              if (IC_RESULT (ic) && isOperandVolatile (IC_RESULT (ic), FALSE))
                continue;
 
+             /* We also cannot remove the iCode, when an operand is volatile.       */
+             /* Even read access can cause side effects on some hardware registers! */
+
+             /* if the left operand is volatile then continue */
+             if (IC_LEFT(ic) && isOperandVolatile (IC_LEFT (ic), TRUE))
+               continue;
+
+
              /* if the result is a temp & isaddr then skip */
              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 */
@@ -938,6 +956,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++;