Martins fix for sdcdb
[fw/sdcc] / src / SDCCopt.c
index 374c34d29ee904546a9e3bb7f082e0bd72927628..2e1ff9a6f2c65a1ef891b34b196723441501310d 100644 (file)
@@ -324,6 +324,8 @@ found:
 
 }
 
+extern operand *geniCodeRValue (operand *, bool);
+
 /*-----------------------------------------------------------------*/
 /* convilong - converts int or long mults or divs to fcalls        */
 /*-----------------------------------------------------------------*/
@@ -338,8 +340,34 @@ convilong (iCode * ic, eBBlock * ebp, sym_link * type, int op)
   int su;
   int bytesPushed=0;
 
-  remiCodeFromeBBlock (ebp, ic);
-
+  // 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++)
     {
@@ -830,7 +858,7 @@ eBBlockFromiCode (iCode * ic)
     dumpEbbsToFileExt (DUMP_RAW1, ebbs, count);
 
   /* do common subexpression elimination for each block */
-  change = cseAllBlocks (ebbs, saveCount);
+  change = cseAllBlocks (ebbs, saveCount, FALSE);
 
   /* dumpraw if asked for */
   if (options.dump_raw)
@@ -846,10 +874,15 @@ eBBlockFromiCode (iCode * ic)
   /* global common subexpression elimination  */
   if (optimize.global_cse)
     {
-      change += cseAllBlocks (ebbs, saveCount);
+      change += cseAllBlocks (ebbs, saveCount, FALSE);
       if (options.dump_gcse)
        dumpEbbsToFileExt (DUMP_GCSE, ebbs, saveCount);
     }
+  else
+    {
+      // compute the dataflow only
+      assert(cseAllBlocks (ebbs, saveCount, TRUE)==0);
+    }
   /* kill dead code */
   kchange = killDeadCode (ebbs, saveCount);
 
@@ -871,7 +904,7 @@ eBBlockFromiCode (iCode * ic)
   if (lchange || kchange)
     {
       computeDataFlow (ebbs, saveCount);
-      change += cseAllBlocks (ebbs, saveCount);
+      change += cseAllBlocks (ebbs, saveCount, FALSE);
       if (options.dump_loop)
        dumpEbbsToFileExt (DUMP_LOOPG, ebbs, count);
 
@@ -886,24 +919,26 @@ eBBlockFromiCode (iCode * ic)
 
     }
 
-  // this is a good place to check missing return values
-  if (currFunc) {
-    if (!IS_VOID(currFunc->type->next)) {
-      eBBlock *bp;
-      // make sure all predecessors of the last block end in a return
-      for (bp=setFirstItem(ebbs[saveCount-1]->predList); 
-          bp; 
-          bp=setNextItem(ebbs[saveCount-1]->predList)) {
-       if (bp->ech->op != RETURN) {
-         werror (W_VOID_FUNC, currFunc->name);
+  /* sort it back by block number */
+  qsort (ebbs, saveCount, sizeof (eBBlock *), bbNumCompare);
+
+  if (!options.lessPedantic) {
+    // this is a good place to check missing return values
+    if (currFunc) {
+      if (!IS_VOID(currFunc->etype)) {
+       eBBlock *bp;
+       // make sure all predecessors of the last block end in a return
+       for (bp=setFirstItem(ebbs[saveCount-1]->predList); 
+            bp; 
+            bp=setNextItem(ebbs[saveCount-1]->predList)) {
+         if (bp->ech->op != RETURN) {
+           werror (W_VOID_FUNC, currFunc->name);
+         }
        }
       }
     }
   }
 
-  /* sort it back by block number */
-  qsort (ebbs, saveCount, sizeof (eBBlock *), bbNumCompare);
-
   /* if cyclomatic info requested then print it */
   if (options.cyclomatic)
     printCyclomatic (ebbs, saveCount);
@@ -932,8 +967,6 @@ eBBlockFromiCode (iCode * ic)
   setToNull ((void **) &graphEdges);
   ebbs = NULL;
   
-  currFunc=NULL;
-
   return NULL;
 }