From 084dd312234f8d66846225c1ec5c49f32a61fb91 Mon Sep 17 00:00:00 2001 From: bernhardheld Date: Sat, 30 Dec 2006 22:02:12 +0000 Subject: [PATCH] * 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' git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@4540 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- ChangeLog | 15 +++++ src/SDCCpeeph.c | 4 +- src/mcs51/peep.c | 159 ++++++++++++++++++++++++++++++++++++++------ src/mcs51/peep.h | 2 +- src/mcs51/peeph.def | 8 +++ src/port.h | 2 +- 6 files changed, 166 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index 526ee483..37f1e1f0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2006-12-30 Bernhard Held + + * 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 * support/cpp2/options_vc_in.h, support/cpp2/options_vc_in.c, diff --git a/src/SDCCpeeph.c b/src/SDCCpeeph.c index a831e9f4..ef221546 100644 --- a/src/SDCCpeeph.c +++ b/src/SDCCpeeph.c @@ -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; diff --git a/src/mcs51/peep.c b/src/mcs51/peep.c index 5453f421..872dded4 100644 --- a/src/mcs51/peep.c +++ b/src/mcs51/peep.c @@ -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; + } +} diff --git a/src/mcs51/peep.h b/src/mcs51/peep.h index 4958dea8..fec1dd8d 100644 --- a/src/mcs51/peep.h +++ b/src/mcs51/peep.h @@ -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); diff --git a/src/mcs51/peeph.def b/src/mcs51/peeph.def index 8369811d..e0ea0195 100644 --- a/src/mcs51/peeph.def +++ b/src/mcs51/peeph.def @@ -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: diff --git a/src/port.h b/src/port.h index af16bfcf..93e03b41 100644 --- a/src/port.h +++ b/src/port.h @@ -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; -- 2.47.2