* as/hc08/asm.h,
[fw/sdcc] / src / SDCCcse.c
index dc51ea481d0603be56001d7fb85efdf63dfa0ce5..350e6bb92abe46548b6510e023843eeb539734ff 100644 (file)
@@ -83,8 +83,8 @@ pcseDef (void *item, va_list ap)
 
 void ReplaceOpWithCheaperOp(operand **op, operand *cop) {
 #ifdef RANGEHUNT
-  printf ("ReplaceOpWithCheaperOp %s with %s: ", 
-         IS_SYMOP((*op)) ? OP_SYMBOL((*op))->name : "!SYM", 
+  printf ("ReplaceOpWithCheaperOp %s with %s: ",
+         IS_SYMOP((*op)) ? OP_SYMBOL((*op))->name : "!SYM",
          IS_SYMOP(cop) ? OP_SYMBOL(cop)->name : "!SYM");
   // if op is a register equivalent
   if (IS_ITEMP(cop) && OP_SYMBOL((*op))->isreqv) {
@@ -107,7 +107,7 @@ void ReplaceOpWithCheaperOp(operand **op, operand *cop) {
 /* replaceAllSymBySym - replaces all operands by operand in an     */
 /*                      instruction chain                          */
 /*-----------------------------------------------------------------*/
-void 
+void
 replaceAllSymBySym (iCode * ic, operand * from, operand * to, bitVect ** ndpset)
 {
   iCode *lic;
@@ -325,8 +325,8 @@ DEFSETFUNC (findCheaperOp)
       IS_ITEMP (IC_RESULT (cdp->diCode)))
     *opp = IC_RESULT (cdp->diCode);
 
-  if ((*opp) && 
-      (isOperandLiteral(*opp) || !checkSign || 
+  if ((*opp) &&
+      (isOperandLiteral(*opp) || !checkSign ||
        (checkSign &&
        IS_SPEC(operandType (cop)) && IS_SPEC(operandType (*opp)) &&
        (SPEC_USIGN(operandType (cop))==SPEC_USIGN(operandType (*opp)) &&
@@ -353,11 +353,11 @@ DEFSETFUNC (findCheaperOp)
          *opp = operandFromOperand (*opp);
          (*opp)->isaddr = cop->isaddr;
        }
-         
+
       if (IS_SPEC(operandType (cop)) && IS_SPEC(operandType (*opp)) &&
          SPEC_NOUN(operandType(cop)) != SPEC_NOUN(operandType(*opp)))
        {
-           // special case: we can make an unsigned char literal 
+           // special case: we can make an unsigned char literal
            // into an int literal with no cost.
            if (isOperandLiteral(*opp)
             && SPEC_NOUN(operandType(*opp)) == V_CHAR
@@ -372,9 +372,9 @@ DEFSETFUNC (findCheaperOp)
                *opp = NULL;
                return 0;
            }
-           
+
         }
-         
+
       return 1;
 
     }
@@ -517,7 +517,7 @@ DEFSETFUNC (ifOperandsHave)
 /*-----------------------------------------------------------------*/
 /* ifDefSymIs - if a definition is found in the set                */
 /*-----------------------------------------------------------------*/
-int 
+int
 ifDefSymIs (set * cseSet, operand * sym)
 {
   cseDef *loop;
@@ -554,7 +554,7 @@ DEFSETFUNC (ifDefSymIsX)
 /*-----------------------------------------------------------------*/
 /* ifDiCodeIs - returns truw if diCode is same                     */
 /*-----------------------------------------------------------------*/
-int 
+int
 ifDiCodeIs (set * cseSet, iCode * ic)
 {
   cseDef *loop;
@@ -633,8 +633,8 @@ iCode *findBackwardDef(operand *op,iCode *ic)
 /*-----------------------------------------------------------------*/
 /* algebraicOpts - does some algebraic optimizations               */
 /*-----------------------------------------------------------------*/
-void 
-algebraicOpts (iCode * ic)
+static void
+algebraicOpts (iCode * ic, eBBlock * ebp)
 {
   /* we don't deal with the following iCodes
      here */
@@ -825,8 +825,10 @@ algebraicOpts (iCode * ic)
                {
                  ic->op = CAST;
                  IC_LEFT (ic)->type = TYPE;
+                 IC_LEFT (ic)->isLiteral = 0;
                  setOperandType (IC_LEFT (ic), operandType (IC_RESULT (ic)));
                }
+             return;
            }
        }
 
@@ -862,6 +864,7 @@ algebraicOpts (iCode * ic)
                  IC_RIGHT (ic) = IC_LEFT (ic);
                  IC_LEFT (ic) = op;
                  IC_LEFT (ic)->type = TYPE;
+                 IC_LEFT (ic)->isLiteral = 0;
                  setOperandType (IC_LEFT (ic), operandType (IC_RESULT (ic)));
                }
              return;
@@ -948,6 +951,201 @@ algebraicOpts (iCode * ic)
          IC_LEFT (ic) = NULL;
          SET_ISADDR (IC_RESULT (ic), 0);
        }
+      break;
+    case BITWISEAND:
+      /* if both operands are equal */
+      /* if yes turn it into assignment */
+      if (isOperandEqual (IC_LEFT (ic), IC_RIGHT (ic)))
+        {
+          if (IS_OP_VOLATILE (IC_LEFT (ic)))
+           {
+             iCode *newic = newiCode (DUMMY_READ_VOLATILE, NULL, IC_LEFT (ic));
+             IC_RESULT (newic) = IC_LEFT (ic);
+             newic->lineno = ic->lineno;
+             addiCodeToeBBlock (ebp, newic, ic->next);
+           }
+         ic->op = '=';
+         IC_LEFT (ic) = NULL;
+         SET_RESULT_RIGHT (ic);
+         return;
+       }
+      /* swap literal to right ic */
+      if (IS_OP_LITERAL (IC_LEFT (ic)))
+        {
+         operand *op;
+
+         op = IC_LEFT (ic);
+         IC_LEFT (ic) = IC_RIGHT (ic);
+         IC_RIGHT (ic) = op;
+       }
+      if (IS_OP_LITERAL (IC_RIGHT (ic)))
+        {
+         /* if BITWISEAND then check if one of them is a zero */
+         /* if yes turn it into 0 assignment */
+         if (operandLitValue (IC_RIGHT (ic)) == 0.0)
+           {
+             if (IS_OP_VOLATILE (IC_LEFT (ic)))
+               {
+                 iCode *newic = newiCode (DUMMY_READ_VOLATILE, NULL, IC_LEFT (ic));
+                 IC_RESULT (newic) = IC_LEFT (ic);
+                 newic->lineno = ic->lineno;
+                 addiCodeToeBBlock (ebp, newic, ic->next);
+               }
+             ic->op = '=';
+             IC_LEFT (ic) = NULL;
+             SET_RESULT_RIGHT (ic);
+             return;
+           }
+         /* if BITWISEAND then check if one of them is 0xff... */
+         /* if yes turn it into assignment */
+         {
+           unsigned val;
+
+           switch (getSize (operandType (IC_RIGHT (ic))))
+             {
+             case 1:
+               val = 0xff;
+               break;
+             case 2:
+               val = 0xffff;
+               break;
+             case 4:
+               val = 0xffffffff;
+               break;
+             default:
+               return;
+             }
+           if (((unsigned) operandLitValue (IC_RIGHT (ic)) & val) == val)
+           {
+             ic->op = '=';
+             IC_RIGHT (ic) = IC_LEFT (ic);
+             IC_LEFT (ic) = NULL;
+             SET_RESULT_RIGHT (ic);
+             return;
+           }
+         }
+       }
+      break;
+    case '|':
+      /* if both operands are equal */
+      /* if yes turn it into assignment */
+      if (isOperandEqual (IC_LEFT (ic), IC_RIGHT (ic)))
+        {
+          if (IS_OP_VOLATILE (IC_LEFT (ic)))
+           {
+             iCode *newic = newiCode (DUMMY_READ_VOLATILE, NULL, IC_LEFT (ic));
+             IC_RESULT (newic) = IC_LEFT (ic);
+             newic->lineno = ic->lineno;
+             addiCodeToeBBlock (ebp, newic, ic->next);
+           }
+           ic->op = '=';
+           IC_LEFT (ic) = NULL;
+           SET_RESULT_RIGHT (ic);
+           return;
+       }
+      /* swap literal to right ic */
+      if (IS_OP_LITERAL (IC_LEFT (ic)))
+        {
+         operand *op;
+
+         op = IC_LEFT (ic);
+         IC_LEFT (ic) = IC_RIGHT (ic);
+         IC_RIGHT (ic) = op;
+       }
+      if (IS_OP_LITERAL (IC_RIGHT (ic)))
+        {
+         /* if BITWISEOR then check if one of them is a zero */
+         /* if yes turn it into assignment */
+         if (operandLitValue (IC_RIGHT (ic)) == 0.0)
+           {
+             ic->op = '=';
+             IC_RIGHT (ic) = IC_LEFT (ic);
+             IC_LEFT (ic) = NULL;
+             SET_RESULT_RIGHT (ic);
+             return;
+           }
+         /* if BITWISEOR then check if one of them is 0xff... */
+         /* if yes turn it into 0xff... assignment */
+         {
+           unsigned val;
+
+           switch (getSize (operandType (IC_RIGHT (ic))))
+             {
+             case 1:
+               val = 0xff;
+               break;
+             case 2:
+               val = 0xffff;
+               break;
+             case 4:
+               val = 0xffffffff;
+               break;
+             default:
+               return;
+             }
+           if (((unsigned) operandLitValue (IC_RIGHT (ic)) & val) == val)
+             {
+               if (IS_OP_VOLATILE (IC_LEFT (ic)))
+               {
+                 iCode *newic = newiCode (DUMMY_READ_VOLATILE, NULL, IC_LEFT (ic));
+                 IC_RESULT (newic) = IC_LEFT (ic);
+                 newic->lineno = ic->lineno;
+                 addiCodeToeBBlock (ebp, newic, ic->next);
+               }
+               ic->op = '=';
+               IC_LEFT (ic) = NULL;
+               SET_RESULT_RIGHT (ic);
+               return;
+             }
+         }
+       }
+      break;
+    case '^':
+      /* if both operands are equal */
+      /* if yes turn it into 0 assignment */
+      if (isOperandEqual (IC_LEFT (ic), IC_RIGHT (ic)))
+        {
+          if (IS_OP_VOLATILE (IC_LEFT (ic)))
+           {
+             iCode *newic = newiCode (DUMMY_READ_VOLATILE, NULL, IC_LEFT (ic));
+             IC_RESULT (newic) = IC_LEFT (ic);
+             newic->lineno = ic->lineno;
+             addiCodeToeBBlock (ebp, newic, ic->next);
+
+             newic = newiCode (DUMMY_READ_VOLATILE, NULL, IC_LEFT (ic));
+             IC_RESULT (newic) = IC_LEFT (ic);
+             newic->lineno = ic->lineno;
+             addiCodeToeBBlock (ebp, newic, ic->next);
+           }
+           ic->op = '=';
+           IC_RIGHT (ic) = operandFromLit (0);
+           IC_LEFT (ic) = NULL;
+           SET_RESULT_RIGHT (ic);
+           return;
+       }
+      /* swap literal to right ic */
+      if (IS_OP_LITERAL (IC_LEFT (ic)))
+        {
+         operand *op;
+
+         op = IC_LEFT (ic);
+         IC_LEFT (ic) = IC_RIGHT (ic);
+         IC_RIGHT (ic) = op;
+       }
+      /* if XOR then check if one of them is a zero */
+      /* if yes turn it into assignment */
+      if (IS_OP_LITERAL (IC_RIGHT (ic)))
+       {
+         if (operandLitValue (IC_RIGHT (ic)) == 0.0)
+           {
+             ic->op = '=';
+             IC_RIGHT (ic) = IC_LEFT (ic);
+             IC_LEFT (ic) = NULL;
+             SET_RESULT_RIGHT (ic);
+             return;
+           }
+       }
+      break;
     }
 
   return;
@@ -956,7 +1154,7 @@ algebraicOpts (iCode * ic)
 /*-----------------------------------------------------------------*/
 /* updateSpillLocation - keeps track of register spill location    */
 /*-----------------------------------------------------------------*/
-void 
+void
 updateSpillLocation (iCode * ic, int induction)
 {
        sym_link *setype;
@@ -1290,9 +1488,9 @@ deleteGetPointers (set ** cseSet, set ** pss, operand * op, eBBlock * ebb)
             list . This will take care of situations like
             iTemp1 = iTemp0 + 8;
             iTemp2 = iTemp1 + 8; */
-         if (isinSetWith (compItems, (void*)IC_LEFT (cdp->diCode), 
+         if (isinSetWith (compItems, (void*)IC_LEFT (cdp->diCode),
                           (insetwithFunc)isOperandEqual) ||
-             isinSetWith (compItems, (void*)IC_RIGHT (cdp->diCode), 
+             isinSetWith (compItems, (void*)IC_RIGHT (cdp->diCode),
                           (insetwithFunc)isOperandEqual))
            {
              addSet (&compItems, IC_RESULT (cdp->diCode));
@@ -1340,7 +1538,7 @@ DEFSETFUNC (delGetPointerSucc)
 /*-----------------------------------------------------------------*/
 /* fixUpTypes - KLUGE HACK fixup a lowering problem                */
 /*-----------------------------------------------------------------*/
-static void 
+static void
 fixUpTypes (iCode * ic)
 {
   sym_link *t1 = operandType (IC_LEFT (ic)), *t2;
@@ -1417,7 +1615,7 @@ static int isSignedOp (iCode *ic)
 /*             system. also the most important, since almost all   */
 /*             data flow related information is computed by it     */
 /*-----------------------------------------------------------------*/
-int 
+int
 cseBBlock (eBBlock * ebb, int computeOnly,
           eBBlock ** ebbs, int count)
 {
@@ -1435,12 +1633,12 @@ cseBBlock (eBBlock * ebb, int computeOnly,
   cseSet = setFromSet (ebb->inExprs);
 
   /* these will be computed by this routine */
-  setToNull ((void **) &ebb->outDefs);
-  setToNull ((void **) &ebb->defSet);
-  setToNull ((void **) &ebb->usesDefs);
-  setToNull ((void **) &ebb->ptrsSet);
-  setToNull ((void **) &ebb->addrOf);
-  setToNull ((void **) &ebb->ldefs);
+  setToNull ((void *) &ebb->outDefs);
+  setToNull ((void *) &ebb->defSet);
+  setToNull ((void *) &ebb->usesDefs);
+  setToNull ((void *) &ebb->ptrsSet);
+  setToNull ((void *) &ebb->addrOf);
+  setToNull ((void *) &ebb->ldefs);
 
   ebb->outDefs = bitVectCopy (ebb->inDefs);
   bitVectDefault = iCodeKey;
@@ -1539,10 +1737,13 @@ cseBBlock (eBBlock * ebb, int computeOnly,
       /* if jumptable then mark the usage */
       if (ic->op == JUMPTABLE)
        {
-         OP_USES(IC_JTCOND (ic))=
-           bitVectSetBit (OP_USES (IC_JTCOND (ic)), ic->key);
-         setUsesDefs (IC_JTCOND (ic), ebb->defSet,
-                      ebb->outDefs, &ebb->usesDefs);
+          if (IS_SYMOP (IC_JTCOND (ic)))
+           {
+             OP_USES(IC_JTCOND (ic)) =
+               bitVectSetBit (OP_USES (IC_JTCOND (ic)), ic->key);
+             setUsesDefs (IC_JTCOND (ic), ebb->defSet,
+                          ebb->outDefs, &ebb->usesDefs);
+           }
          continue;
        }
 
@@ -1551,7 +1752,7 @@ cseBBlock (eBBlock * ebb, int computeOnly,
 
       if (!computeOnly) {
        /* do some algebraic optimizations if possible */
-       algebraicOpts (ic);
+       algebraicOpts (ic, ebb);
        while (constFold (ic, cseSet));
       }
 
@@ -1587,7 +1788,7 @@ cseBBlock (eBBlock * ebb, int computeOnly,
          /* update the spill location for this */
          updateSpillLocation (ic,0);
 
-         if (POINTER_SET (ic) && 
+         if (POINTER_SET (ic) &&
              !(IS_BITFIELD (OP_SYMBOL (IC_RESULT (ic))->etype)))
            {
              pdop = NULL;
@@ -1658,11 +1859,11 @@ cseBBlock (eBBlock * ebb, int computeOnly,
            change = 1;
          }
        }
-       
+
       /* if left or right changed then do algebraic */
       if (!computeOnly && change)
        {
-         algebraicOpts (ic);
+         algebraicOpts (ic, ebb);
          while (constFold (ic, cseSet));
        }
 
@@ -1693,15 +1894,15 @@ cseBBlock (eBBlock * ebb, int computeOnly,
          if (pdic && compareType (operandType (IC_RESULT (pdic)),
                                 operandType (IC_RESULT (ic))) != 1)
            pdic = NULL;
-         if (pdic && port->cseOk && (*port->cseOk)(ic,pdic) == 0) 
+         if (pdic && port->cseOk && (*port->cseOk)(ic,pdic) == 0)
              pdic = NULL;
        }
 
       /* Alternate code */
       if (pdic && IS_ITEMP(IC_RESULT(ic))) {
        if (POINTER_GET(ic) && bitVectBitValue(ebb->ptrsSet,IC_LEFT(ic)->key)) {
-         /* Mmm, found an equivalent pointer get at a lower level. 
-            This could be a loop however with the same pointer set 
+         /* Mmm, found an equivalent pointer get at a lower level.
+            This could be a loop however with the same pointer set
             later on */
        } else {
          /* if previous definition found change this to an assignment */
@@ -1709,7 +1910,7 @@ cseBBlock (eBBlock * ebb, int computeOnly,
          IC_LEFT(ic) = NULL;
          IC_RIGHT(ic) = operandFromOperand(IC_RESULT(pdic));
          SET_ISADDR(IC_RESULT(ic),0);
-         SET_ISADDR(IC_RIGHT (ic),0);    
+         SET_ISADDR(IC_RIGHT (ic),0);
        }
       }
 
@@ -1817,7 +2018,7 @@ cseBBlock (eBBlock * ebb, int computeOnly,
        }
     }
 
-  setToNull ((void **) &ebb->outExprs);
+  setToNull ((void *) &ebb->outExprs);
   ebb->outExprs = cseSet;
   ebb->outDefs = bitVectUnion (ebb->outDefs, ebb->defSet);
   ebb->ptrsSet = bitVectUnion (ebb->ptrsSet, ebb->inPtrsSet);
@@ -1827,7 +2028,7 @@ cseBBlock (eBBlock * ebb, int computeOnly,
 /*-----------------------------------------------------------------*/
 /* cseAllBlocks - will sequentially go thru & do cse for all blocks */
 /*-----------------------------------------------------------------*/
-int 
+int
 cseAllBlocks (eBBlock ** ebbs, int count, int computeOnly)
 {
   int i;