* src/SDCCpeeph.c (deadMove),
authorbernhardheld <bernhardheld@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Sat, 30 Dec 2006 22:02:12 +0000 (22:02 +0000)
committerbernhardheld <bernhardheld@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Sat, 30 Dec 2006 22:02:12 +0000 (22:02 +0000)
* src/port.h,
* src/mcs51/peep.h: renamed 'op' by 'reg'
* src/mcs51/peep.c (isFunc, isCallerSaveFunc): added,
(scan4op): small change for removeDeadMove(), added support for 'callee saves' and/or PACLL function calls,
(removeDeadMove): added, removes superflous 'mov r%1,%2',
(removeDeadPopPush): renamed from mcs51DeadMove(), common parts left in new dispatcher mcs51DeadMove()
(mcs51DeadMove): dispatcher for removeDeadPopPush() and new removeDeadMove()
* src/mcs51/peeph.def: added rule 301 removing superflous 'mov r%1,%2'

git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@4540 4a8a32a2-be11-0410-ad9d-d568d2c75423

ChangeLog
src/SDCCpeeph.c
src/mcs51/peep.c
src/mcs51/peep.h
src/mcs51/peeph.def
src/port.h

index 526ee483e792458888a72a0507770fdd8f608125..37f1e1f016096fece2a416b3abe6f2d5c79ef38a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2006-12-30 Bernhard Held <bernhard AT bernhardheld.de>
+
+       * src/SDCCpeeph.c (deadMove),
+       * src/port.h,
+       * src/mcs51/peep.h: renamed 'op' by 'reg'
+       * src/mcs51/peep.c (isFunc, isCallerSaveFunc): added,
+       (scan4op): small change for removeDeadMove(), added support for
+       'callee saves' and/or PACLL function calls,
+       (removeDeadMove): added, removes superflous 'mov r%1,%2',
+       (removeDeadPopPush): renamed from mcs51DeadMove(), common parts
+       left in new dispatcher mcs51DeadMove()
+       (mcs51DeadMove): dispatcher for removeDeadPopPush() and new
+       removeDeadMove()
+       * src/mcs51/peeph.def: added rule 301 removing superflous 'mov r%1,%2'
+
 2006-12-30 Jesus Calvino-Fraga <jesusc at ece.ubc.ca>
 
        * support/cpp2/options_vc_in.h, support/cpp2/options_vc_in.c,
index a831e9f404a386a60de61962a89605bf0b0aa424..ef221546b5af215215c0157863fbc0d436873df6 100644 (file)
@@ -308,10 +308,10 @@ FBYNAME (okToRemoveSLOC)
 /*-----------------------------------------------------------------*/
 FBYNAME (deadMove)
 {
-  char *op = hTabItemWithKey (vars, 1);
+  const char *reg = hTabItemWithKey (vars, 1);
 
   if (port->peep.deadMove)
-    return port->peep.deadMove (op, currPl, head);
+    return port->peep.deadMove (reg, currPl, head);
 
   fprintf (stderr, "Function deadMove not initialized in port structure\n"); 
   return FALSE;
index 5453f42185e287ad220f0a5f3e1a51204ff0c811..872dded4c587274b8ad5e31274e45c073aaad6cb 100644 (file)
@@ -26,7 +26,7 @@
 #include "ralloc.h"
 
 #define D(x) x
-#define DEADMOVEERROR "Internal error: deadmove\n"
+#define DEADMOVEERROR "SDCC internal error: deadmove in " __FILE__" line %d\n", __LINE__
 
 typedef enum
 {
@@ -199,6 +199,35 @@ findLabel (const lineNode *pl)
   return NULL;
 }
 
+/*-----------------------------------------------------------------*/
+/* isFunc - returns TRUE if it's a CALL or PCALL (not _gptrget())  */
+/*-----------------------------------------------------------------*/
+static bool
+isFunc (const lineNode *pl)
+{
+  if (pl && pl->ic)
+    {
+      if (   pl->ic->op == CALL
+          || pl->ic->op == PCALL)
+        return TRUE;
+    }
+  return FALSE;
+}
+
+/*-----------------------------------------------------------------*/
+/* isCallerSaveFunc - returns TRUE if it's a 'normal' function     */
+/* call and it's a 'caller save' (not 'callee save')               */
+/*-----------------------------------------------------------------*/
+static bool
+isCallerSaveFunc (const lineNode *pl)
+{
+  if (!isFunc (pl))
+    return FALSE;
+  if (FUNC_CALLEESAVES(OP_SYM_TYPE(IC_LEFT(pl->ic))))
+    return FALSE;
+  return TRUE;
+}
+
 /*-----------------------------------------------------------------*/
 /* scan4op - "executes" and examines the assembler opcodes,        */
 /* follows conditional and un-conditional jumps.                   */
@@ -308,9 +337,8 @@ scan4op (lineNode **pl, const char *pReg, const char *untilOp,
               if (bitVectBitValue (port->peep.getRegsWritten ((*pl)), rIdx))
                 return S4O_WR_OP;
 
-              /* should never reach here */
-              D(fprintf (stderr, DEADMOVEERROR);)
-              return S4O_ABORT;
+              /* we can get here, if the register name is
+                 part of a variable name: ignore it */
             }
         }
 
@@ -340,7 +368,12 @@ scan4op (lineNode **pl, const char *pReg, const char *untilOp,
         {
           case 'a':
             if (strncmp ("acall", (*pl)->line, 5) == 0)
-              return S4O_TERM;
+              {
+                /* for comments see 'lcall' */
+                if (isCallerSaveFunc (*pl))
+                  return S4O_TERM;
+                break;
+              }
             if (strncmp ("ajmp", (*pl)->line, 4) == 0)
               {
                 *pl = findLabel (*pl);
@@ -384,7 +417,23 @@ scan4op (lineNode **pl, const char *pReg, const char *untilOp,
             break;
           case 'l':
             if (strncmp ("lcall", (*pl)->line, 5) == 0)
-              return S4O_TERM;
+              {
+                if (isCallerSaveFunc (*pl))
+                  {
+                    /* If it's a 'normal' 'caller save' function call, all
+                       registers have been saved until the 'lcall'. The
+                       'life range' of all registers end at the lcall,
+                       and we can terminate our search.
+                    */
+                    return S4O_TERM;
+                  }
+                /* If it's a 'callee save' function call, registers are saved
+                   by the callee. We've got no information, if the register
+                   might live beyond the lcall. Therefore we've to continue
+                   the search.
+                */
+                break;
+              }
             if (strncmp ("ljmp", (*pl)->line, 4) == 0)
               {
                 *pl = findLabel (*pl);
@@ -398,9 +447,23 @@ scan4op (lineNode **pl, const char *pReg, const char *untilOp,
               return S4O_PUSHPOP;
             break;
           case 'r':
-            /* pcall uses ret */
-            if (strncmp ("ret", (*pl)->line, 3) == 0) /* catches "reti" too */
+            if (strncmp ("reti", (*pl)->line, 4) == 0)
               return S4O_TERM;
+
+            if (strncmp ("ret", (*pl)->line, 3) == 0)
+              {
+                /* pcall uses 'ret' */
+                if (isFunc (*pl))
+                  {
+                    /* for comments see 'lcall' */
+                    if (isCallerSaveFunc (*pl))
+                      return S4O_TERM;
+                    break;
+                  }
+
+                /* it's a normal function return */
+                return S4O_TERM;
+              }
             break;
           case 's':
             if (strncmp ("sjmp", (*pl)->line, 4) == 0)
@@ -507,12 +570,11 @@ doTermScan (lineNode **pl, const char *pReg)
 }
 
 /*-----------------------------------------------------------------*/
-/* -                                                               */
+/* removeDeadPopPush - remove pop/push pair if possible            */
 /*-----------------------------------------------------------------*/
-bool
-mcs51DeadMove (const char *op1, lineNode *currPl, lineNode *head)
+static bool
+removeDeadPopPush (const char *pReg, lineNode *currPl, lineNode *head)
 {
-  char pReg[5] = "ar";
   lineNode *pushPl, *pl;
 
   /* A pop/push pair can be removed, if these criteria are met
@@ -543,16 +605,11 @@ mcs51DeadMove (const char *op1, lineNode *currPl, lineNode *head)
       ;    - inline assembly
       ;    - a jump in or out of area 2 (see checkLabelRef())
 
-      ; An "acall", "lcall", "ret", "reti" or write access of ar0 terminate
-      ; the search, and the pop/push pair can safely be removed.
+      ; An "acall", "lcall" (not callee save), "ret" (not PCALL with
+      ; callee save), "reti" or write access of r0 terminate
+      ; the search, and the "mov r0,a" can safely be removed.
   */
 
-  _G.head = head;
-  strcat (pReg, op1);
-
-  unvisitLines (_G.head);
-  cleanLabelRef();
-
   /* area 1 */
   pushPl = currPl->next;
   if (!doPushScan (&pushPl, pReg))
@@ -589,3 +646,65 @@ mcs51DeadMove (const char *op1, lineNode *currPl, lineNode *head)
   /* 'pop ar0' will be removed by peephole framework after returning TRUE */
   return TRUE;
 }
+
+/*-----------------------------------------------------------------*/
+/* removeDeadMove - remove superflous 'mov r%1,%2'                 */
+/*-----------------------------------------------------------------*/
+static bool
+removeDeadMove (const char *pReg, lineNode *currPl, lineNode *head)
+{
+  lineNode *pl;
+
+  /* "mov r0,a" can be removed, if these criteria are met
+     (r0 is just an example here, r0...r7 are possible):
+
+      ; There must not be:
+      ;    - read access of r0
+      ;    - "jmp @a+dptr" opcode
+      ;    - inline assembly
+      ;    - a jump in or out of this area (see checkLabelRef())
+
+      ; An "acall", "lcall" (not callee save), "ret" (not PCALL with
+      ; callee save), "reti" or write access of r0 terminate
+      ; the search, and the "mov r0,a" can safely be removed.
+  */
+  pl = currPl->next;
+  if (!doTermScan (&pl, pReg))
+    return FALSE;
+
+  if (!checkLabelRef())
+    return FALSE;
+
+  return TRUE;
+}
+
+/*-----------------------------------------------------------------*/
+/* mcs51DeadMove - dispatch condition deadmove between             */
+/* - remove pop/push                                               */
+/* - remove mov r%1,%2                                             */
+/*-----------------------------------------------------------------*/
+bool
+mcs51DeadMove (const char *reg, lineNode *currPl, lineNode *head)
+{
+  char pReg[5] = "ar";
+
+  _G.head = head;
+  strcat (pReg, reg);
+
+  unvisitLines (_G.head);
+  cleanLabelRef();
+
+  if (strncmp (currPl->line, "pop", 3) == 0)
+    return removeDeadPopPush (pReg, currPl, head);
+  else if (   strncmp (currPl->line, "mov", 3) == 0
+           && (currPl->line[3] == ' ' || currPl->line[3] == '\t'))
+    return removeDeadMove (pReg, currPl, head);
+  else
+    {
+      fprintf (stderr, "Error: "
+                       "peephole rule with condition deadMove "
+                       "used with unknown opocde:\n"
+                       "\t%s\n", currPl->line);
+      return FALSE;
+    }
+}
index 4958dea8c716a7fd3939917910a30765de87b5a1..fec1dd8dacd17f7fd7f0564130d16cba61db257b 100644 (file)
@@ -22,4 +22,4 @@
   what you give them.   Help stamp out software-hoarding!
 -------------------------------------------------------------------------*/
 
-bool mcs51DeadMove (const char *op, lineNode *currPl, lineNode *head);
+bool mcs51DeadMove (const char *reg, lineNode *currPl, lineNode *head);
index 8369811dd5f9a9e481bfc4543e798ea09de5020a..e0ea01950bc2b68fd0e8b3ddf6cbae2cc6453525 100644 (file)
@@ -4591,12 +4591,20 @@ replace {
 %3:
 } if labelRefCount(%3 1), labelRefCountChange(%3 -1)
 
+
 replace restart {
        pop     ar%1
 } by {
        ;       Peephole 300    pop ar%1 removed
 } if deadMove %1
 
+replace {
+       mov     r%1,%2
+} by {
+       ;       Peephole 301    mov r%1,%2 removed
+} if notVolatile(%2), deadMove(%1)
+
+
 // should be one of the last peepholes
 replace{
 %1:
index af16bfcf2698fa9218fb8ea7cc806edeecc89a3b..93e03b4141bdcfe952ee780549e8a06a593eb88d 100644 (file)
@@ -132,7 +132,7 @@ typedef struct
         int (*getSize)(lineNode *line);
         bitVect * (*getRegsRead)(lineNode *line);
         bitVect * (*getRegsWritten)(lineNode *line);
-        bool (*deadMove) (const char *op, lineNode *currPl, lineNode *head);
+        bool (*deadMove) (const char *reg, lineNode *currPl, lineNode *head);
       }
     peep;