* src/SDCC.lex (check_type),
[fw/sdcc] / src / SDCCpeeph.c
index a4341f1f2e34757362be8b045d44f779c443e498..075cad2abc12af5ba428411386de4a84553bac5b 100644 (file)
@@ -61,7 +61,7 @@ void pic16_peepRules2pCode(peepRule *);
 #endif
 
 /*-----------------------------------------------------------------*/
-/* pcDistance - afinds a label back ward or forward                */
+/* pcDistance - finds a label backward or forward                  */
 /*-----------------------------------------------------------------*/
 
 static int
@@ -74,16 +74,19 @@ pcDistance (lineNode * cpos, char *lbl, bool back)
   SNPRINTF (buff, sizeof(buff), "%s:", lbl);
   while (pl)
     {
-
       if (pl->line &&
           !pl->isComment &&
           !pl->isLabel &&
-          !pl->isDebug) {
-                if (port->peep.getSize) {
-                        dist += port->peep.getSize(pl);
-                } else {
-                        dist += 3;
-                }
+          !pl->isDebug)
+        {
+          if (port->peep.getSize)
+            {
+              dist += port->peep.getSize(pl);
+            }
+          else
+            {
+              dist += 3;
+            }
         }
 
       if (strncmp (pl->line, buff, strlen (buff)) == 0)
@@ -98,16 +101,6 @@ pcDistance (lineNode * cpos, char *lbl, bool back)
   return 0;
 }
 
-/*-----------------------------------------------------------------*/
-/* flat24bitModeAndPortDS390 -                                     */
-/*-----------------------------------------------------------------*/
-FBYNAME (flat24bitModeAndPortDS390)
-{
-    return (((strcmp(port->target,"ds390") == 0) ||
-             (strcmp(port->target,"ds400") == 0)) &&
-            (options.model == MODEL_FLAT24));
-}
-
 /*-----------------------------------------------------------------*/
 /* portIsDS390 - return true if port is DS390                      */
 /*-----------------------------------------------------------------*/
@@ -133,10 +126,13 @@ FBYNAME (xramMovcOption)
   return (options.xram_movc && (strcmp(port->target,"mcs51") == 0));
 }
 
-
-
-
-
+/*-----------------------------------------------------------------*/
+/* useAcallAjmp - Enable replacement of lcall/ljmp with acall/ajmp */
+/*-----------------------------------------------------------------*/
+FBYNAME (useAcallAjmp)
+{
+  return (options.acall_ajmp && (strcmp(port->target,"mcs51") == 0));
+}
 
 /*-----------------------------------------------------------------*/
 /* labelInRange - will check to see if label %5 is within range    */
@@ -162,7 +158,7 @@ FBYNAME (labelInRange)
     return FALSE;
 
   /* calculate the label distance : the jump for reladdr can be
-     +/- 127 bytes, here Iam assuming that an average 8051
+     +/- 127 bytes, here I am assuming that an average 8051
      instruction is 2 bytes long, so if the label is more than
      63 intructions away, the label is considered out of range
      for a relative jump. we could get more precise this will
@@ -177,7 +173,6 @@ FBYNAME (labelInRange)
   return TRUE;
 }
 
-
 /*-----------------------------------------------------------------*/
 /* labelJTInRange - will check to see if label %5 and up are       */
 /* within range.                                                   */
@@ -221,7 +216,6 @@ FBYNAME (labelJTInRange)
   return TRUE;
 }
 
-
 /*-----------------------------------------------------------------*/
 /* labelIsReturnOnly - Check if label %5 is followed by RET        */
 /*-----------------------------------------------------------------*/
@@ -248,7 +242,7 @@ FBYNAME (labelIsReturnOnly)
         {
           if (strncmp(pl->line, label, len) == 0)
             break; /* Found Label */
-          if (strlen(pl->line) != 7     || !ISCHARDIGIT(*(pl->line))   ||
+          if (strlen(pl->line) != 7       || !ISCHARDIGIT(*(pl->line))   ||
               !ISCHARDIGIT(*(pl->line+1)) || !ISCHARDIGIT(*(pl->line+2)) ||
               !ISCHARDIGIT(*(pl->line+3)) || !ISCHARDIGIT(*(pl->line+4)) ||
               *(pl->line+5) != '$')
@@ -266,7 +260,7 @@ FBYNAME (labelIsReturnOnly)
     return FALSE; /* next line not valid */
   p = pl->line;
   for (p = pl->line; *p && ISCHARSPACE(*p); p++)
-          ;
+    ;
 
   retInst = "ret";
   if (TARGET_IS_HC08)
@@ -276,7 +270,6 @@ FBYNAME (labelIsReturnOnly)
   return FALSE;
 }
 
-
 /*-----------------------------------------------------------------*/
 /* labelIsUncondJump - Check if label %5 is followed by an         */
 /* unconditional jump and put the destination of that jump in %6   */
@@ -353,12 +346,13 @@ FBYNAME (labelIsUncondJump)
       if (*q==',')
         return FALSE; /* conditional jump */
     }
+  if (strcmp(p, q) == 0)
+    return FALSE; /* labels are equal */
   /* now put the destination in %6 */
   bindVar (6, &p, &vars);
   return TRUE;
 }
 
-
 /*-----------------------------------------------------------------*/
 /* okToRemoveSLOC - Check if label %1 is a SLOC and not other      */
 /* usage of it in the code depends on a value from this section    */
@@ -404,7 +398,29 @@ FBYNAME (deadMove)
   if (port->peep.deadMove)
     return port->peep.deadMove (reg, currPl, head);
 
-  fprintf (stderr, "Function deadMove not initialized in port structure\n"); 
+  fprintf (stderr, "Function deadMove not initialized in port structure\n");
+  return FALSE;
+}
+
+/*-----------------------------------------------------------------*/
+/* notUsed - Check, if value in register is not read again         */
+/*-----------------------------------------------------------------*/
+FBYNAME (notUsed)
+{
+  const char *what;
+
+  if(cmdLine[0] != '\'')
+    what = hTabItemWithKey (vars, 1);
+  else
+  {
+    cmdLine[strlen(cmdLine) - 1] = 0;
+    what = cmdLine + 1;
+  }
+
+  if (port->peep.notUsed)
+    return port->peep.notUsed (what, endPl, head);
+
+  fprintf (stderr, "Function notUsed not initialized in port structure\n");
   return FALSE;
 }
 
@@ -518,7 +534,6 @@ FBYNAME (operandsNotSame6)
     return TRUE;
 }
 
-
 /*-----------------------------------------------------------------*/
 /* operandsNotSame7- check if any pair of %1,%2,%3,.. are the same */
 /*-----------------------------------------------------------------*/
@@ -689,7 +704,6 @@ FBYNAME (labelRefCount)
   return rc;
 }
 
-
 /* labelRefCountChange:
  * takes two parameters: a variable (bound to a label name)
  * and a signed int for changing the reference count.
@@ -766,7 +780,6 @@ FBYNAME (labelRefCountChange)
   return rc;
 }
 
-
 /* Within the context of the lines currPl through endPl, determine
 ** if the variable var contains a symbol that is volatile. Returns
 ** TRUE only if it is certain that this was not volatile (the symbol
@@ -831,22 +844,52 @@ notVolatileVariable(char *var, lineNode *currPl, lineNode *endPl)
           {
           case IFX:
             op = IC_COND (cl->ic);
-            if (IS_SYMOP (op) && !strcmp(OP_SYMBOL (op)->rname,symname) )
-              return !op->isvolatile;
+            if (IS_SYMOP (op) &&
+                ( !strcmp(OP_SYMBOL (op)->rname, symname) ||
+                  (OP_SYMBOL (op)->isspilt &&
+                   SPIL_LOC (op) &&
+                   !strcmp(SPIL_LOC (op)->rname, symname)) ))
+              {
+                return !op->isvolatile;
+              }
           case JUMPTABLE:
             op = IC_JTCOND (cl->ic);
-            if (IS_SYMOP (op) && !strcmp(OP_SYMBOL (op)->rname,symname) )
-              return !op->isvolatile;
+            if (IS_SYMOP (op) &&
+                ( !strcmp(OP_SYMBOL (op)->rname, symname) ||
+                  (OP_SYMBOL (op)->isspilt &&
+                   SPIL_LOC (op) &&
+                   !strcmp(SPIL_LOC (op)->rname, symname)) ))
+              {
+                return !op->isvolatile;
+              }
           default:
             op = IC_LEFT (cl->ic);
-            if (IS_SYMOP (op) && !strcmp(OP_SYMBOL (op)->rname,symname) )
-              return !op->isvolatile;
+            if (IS_SYMOP (op) &&
+                ( !strcmp(OP_SYMBOL (op)->rname, symname) ||
+                  (OP_SYMBOL (op)->isspilt &&
+                   SPIL_LOC (op) &&
+                   !strcmp(SPIL_LOC (op)->rname, symname)) ))
+              {
+                return !op->isvolatile;
+              }
             op = IC_RIGHT (cl->ic);
-            if (IS_SYMOP (op) && !strcmp(OP_SYMBOL (op)->rname,symname) )
-              return !op->isvolatile;
+            if (IS_SYMOP (op) &&
+                ( !strcmp(OP_SYMBOL (op)->rname, symname) ||
+                  (OP_SYMBOL (op)->isspilt &&
+                   SPIL_LOC (op) &&
+                   !strcmp(SPIL_LOC (op)->rname, symname)) ))
+              {
+                return !op->isvolatile;
+              }
             op = IC_RESULT (cl->ic);
-            if (IS_SYMOP (op) && !strcmp(OP_SYMBOL (op)->rname,symname) )
-              return !op->isvolatile;
+            if (IS_SYMOP (op) &&
+                ( !strcmp(OP_SYMBOL (op)->rname, symname) ||
+                  (OP_SYMBOL (op)->isspilt &&
+                   SPIL_LOC (op) &&
+                   !strcmp(SPIL_LOC (op)->rname, symname)) ))
+              {
+                return !op->isvolatile;
+              }
           }
       }
   }
@@ -945,7 +988,6 @@ FBYNAME (notVolatile)
 
   return TRUE;
 
-
 error:
   fprintf (stderr,
            "*** internal error: notVolatile peephole restriction"
@@ -953,7 +995,6 @@ error:
   return FALSE;
 }
 
-
 /*------------------------------------------------------------------*/
 /* setFromConditionArgs - parse a peephole condition's arguments    */
 /* to produce a set of strings, one per argument. Variables %x will */
@@ -1029,12 +1070,14 @@ operandBaseName (const char *op)
         return "a";
       if (!strncmp (op, "ar", 2) && ISCHARDIGIT(*(op+2)) && !*(op+3))
         return op+1;
+      // bug 1739475, temp fix
+      if (op[0] == '@')
+        return operandBaseName(op+1);
     }
 
   return op;
 }
 
-
 /*-------------------------------------------------------------------*/
 /* operandsNotRelated - returns true if the condition's operands are */
 /* not related (taking into account register name aliases). N-way    */
@@ -1075,7 +1118,6 @@ FBYNAME (operandsNotRelated)
   return TRUE;
 }
 
-
 /*-------------------------------------------------------------------*/
 /* operandsLiteral - returns true of the condition's operands are    */
 /* literals.                                                         */
@@ -1108,103 +1150,93 @@ FBYNAME (operandsLiteral)
   return TRUE;
 }
 
-
+static const struct ftab
+{
+  char *fname;
+  int (*func) (hTab *, lineNode *, lineNode *, lineNode *, char *);
+}
+ftab[] =                                // sorted on the number of times used
+{                                       // in the peephole rules on 2007-10-29
+  {
+    "labelRefCount", labelRefCount                  //105
+  },
+  {
+    "notVolatile", notVolatile                      //85
+  },
+  {
+    "labelRefCountChange", labelRefCountChange      //74
+  },
+  {
+    "labelInRange", labelInRange                    //37
+  },
+  {
+    "labelJTInRange", labelJTInRange                //13
+  },
+  {
+    "operandsNotRelated", operandsNotRelated        //9
+  },
+  {
+    "24bitMode", flat24bitMode                      //9
+  },
+  {
+    "operandsNotSame", operandsNotSame              //8
+  },
+  {
+    "operandsNotSame3", operandsNotSame3
+  },
+  {
+    "operandsNotSame4", operandsNotSame4
+  },
+  {
+    "operandsNotSame5", operandsNotSame5
+  },
+  {
+    "operandsNotSame6", operandsNotSame6
+  },
+  {
+    "operandsNotSame7", operandsNotSame7
+  },
+  {
+    "operandsNotSame8", operandsNotSame8
+  },
+  {
+    "xramMovcOption", xramMovcOption
+  },
+  {
+    "portIsDS390", portIsDS390
+  },
+  {
+    "labelIsReturnOnly", labelIsReturnOnly
+  },
+  {
+    "labelIsUncondJump", labelIsUncondJump
+  },
+  {
+    "okToRemoveSLOC", okToRemoveSLOC
+  },
+  {
+    "deadMove", deadMove
+  },
+  {
+    "operandsLiteral", operandsLiteral
+  },
+  {
+    "useAcallAjmp", useAcallAjmp
+  },
+  {
+    "notUsed", notUsed
+  }
+};
 /*-----------------------------------------------------------------*/
 /* callFuncByName - calls a function as defined in the table       */
 /*-----------------------------------------------------------------*/
 static int
 callFuncByName (char *fname,
                 hTab * vars,
-                lineNode * currPl,
-                lineNode * endPl,
+                lineNode * currPl, /* first source line matched */
+                lineNode * endPl,  /* last source line matched */
                 lineNode * head)
 {
-  struct ftab
-  {
-    char *fname;
-    int (*func) (hTab *, lineNode *, lineNode *, lineNode *, char *);
-  }
-  ftab[] =
-  {
-    {
-      "labelInRange", labelInRange
-    }
-    ,
-    {
-      "labelJTInRange", labelJTInRange
-    }
-    ,
-    {
-      "operandsNotSame", operandsNotSame
-    }
-    ,
-    {
-      "operandsNotSame3", operandsNotSame3
-    }
-    ,
-    {
-      "operandsNotSame4", operandsNotSame4
-    }
-    ,
-    {
-      "operandsNotSame5", operandsNotSame5
-    }
-    ,
-    {
-      "operandsNotSame6", operandsNotSame6
-    }
-    ,
-    {
-      "operandsNotSame7", operandsNotSame7
-    }
-    ,
-    {
-      "operandsNotSame8", operandsNotSame8
-    }
-    ,
-    {
-      "24bitMode", flat24bitMode
-    }
-    ,
-    {
-      "xramMovcOption", xramMovcOption
-    }
-    ,
-    {
-      "labelRefCount", labelRefCount
-    }
-    ,
-    {
-      "portIsDS390", portIsDS390
-    },
-    {
-      "labelIsReturnOnly", labelIsReturnOnly
-    },
-    {
-      "labelIsUncondJump", labelIsUncondJump
-    },
-    {
-      "okToRemoveSLOC", okToRemoveSLOC
-    },
-    {
-      "deadMove", deadMove
-    },
-    {
-      "24bitModeAndPortDS390", flat24bitModeAndPortDS390
-    },
-    {
-      "notVolatile", notVolatile
-    },
-    {
-      "operandsNotRelated", operandsNotRelated
-    },
-    {
-      "operandsLiteral", operandsLiteral
-    },
-    {
-      "labelRefCountChange", labelRefCountChange
-    }
-  };
   int   i;
   char  *cmdCopy, *funcName, *funcArgs, *cmdTerm;
   char  c;
@@ -1561,18 +1593,18 @@ top:
       newPeepRule (match, replace, lines, restart);
     }
   else
-    {  
+    {
       if (*bp && strncmp (bp, "replace", 7))
         {
           /* not the start of a new peeprule, so "if" should be here */
-          
+
           char strbuff[1000];
           char *cp;
-          
+
           /* go to the start of the line following "{" of the "by" token */
           while (*rp && (*rp == '\n'))
             rp++;
-            
+
           /* copy text of rule starting with line after "by {" */
           cp = strbuff;
           while (*rp && (rp < bp) && ((cp - strbuff) < sizeof(strbuff)))
@@ -1587,7 +1619,7 @@ top:
           return;
         }
       newPeepRule (match, replace, NULL, restart);
-    }    
+    }
   goto top;
 
 }
@@ -2264,7 +2296,7 @@ peepHole (lineNode ** pls)
   lineNode *spl;
   peepRule *pr;
   lineNode *mtail = NULL;
-  bool restart;
+  bool restart, replaced;
 
 #if !OPT_DISABLE_PIC || !OPT_DISABLE_PIC16
   /* The PIC port uses a different peep hole optimizer based on "pCode" */
@@ -2281,8 +2313,10 @@ peepHole (lineNode ** pls)
       /* for all rules */
       for (pr = rootRules; pr; pr = pr->next)
         {
-          for (spl = *pls; spl; spl = spl->next)
+          for (spl = *pls; spl; spl = replaced ? spl : spl->next)
             {
+              replaced = FALSE;
+
               /* if inline assembler then no peep hole */
               if (spl->isInline)
                 continue;
@@ -2299,10 +2333,15 @@ peepHole (lineNode ** pls)
               /* if it matches */
               if (matchRule (spl, &mtail, pr, *pls))
                 {
+                  /* restart at the replaced line */
+                  replaced = TRUE;
 
                   /* then replace */
                   if (spl == *pls)
-                    replaceRule (pls, mtail, pr);
+                    {
+                      replaceRule (pls, mtail, pr);
+                      spl = *pls;
+                    }
                   else
                     replaceRule (&spl, mtail, pr);