From cbdc651884f0733a7374febdda562e7973862427 Mon Sep 17 00:00:00 2001 From: cuz Date: Tue, 17 Jul 2001 20:13:33 +0000 Subject: [PATCH] Added more optimizations git-svn-id: svn://svn.cc65.org/cc65/trunk@804 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/cc65/codeinfo.c | 16 ++++++++++++ src/cc65/codeopt.c | 1 + src/cc65/coptind.c | 62 ++++++++++++++++++++++++++++++++++++++++----- src/cc65/coptind.h | 3 +++ src/cc65/opcodes.c | 6 ++--- src/cc65/opcodes.h | 5 ++-- 6 files changed, 82 insertions(+), 11 deletions(-) diff --git a/src/cc65/codeinfo.c b/src/cc65/codeinfo.c index 1885306de..7702a37ec 100644 --- a/src/cc65/codeinfo.c +++ b/src/cc65/codeinfo.c @@ -67,6 +67,9 @@ struct FuncInfo { static const FuncInfo FuncInfoTable[] = { { "addysp", REG_Y, REG_NONE }, + { "bnega", REG_A, REG_AX }, + { "bnegax", REG_AX, REG_AX }, + { "bnegeax", REG_AX, REG_AX }, { "booleq", REG_NONE, REG_AX }, { "boolge", REG_NONE, REG_AX }, { "boolgt", REG_NONE, REG_AX }, @@ -77,6 +80,7 @@ static const FuncInfo FuncInfoTable[] = { { "boolugt", REG_NONE, REG_AX }, { "boolule", REG_NONE, REG_AX }, { "boolult", REG_NONE, REG_AX }, + { "complax", REG_AX, REG_AX }, { "decax1", REG_AX, REG_AX }, { "decax2", REG_AX, REG_AX }, { "decax3", REG_AX, REG_AX }, @@ -94,6 +98,8 @@ static const FuncInfo FuncInfoTable[] = { { "decsp6", REG_NONE, REG_A }, { "decsp7", REG_NONE, REG_A }, { "decsp8", REG_NONE, REG_A }, + { "incax1", REG_AX, REG_AX }, + { "incax2", REG_AX, REG_AX }, { "incsp1", REG_NONE, REG_NONE }, { "incsp2", REG_NONE, REG_Y }, { "incsp3", REG_NONE, REG_Y }, @@ -109,12 +115,22 @@ static const FuncInfo FuncInfoTable[] = { { "ldaxidx", REG_AXY, REG_AX }, { "ldaxysp", REG_Y, REG_AX }, { "leaasp", REG_A, REG_AX }, + { "negax", REG_AX, REG_AX }, { "pusha", REG_A, REG_Y }, { "pusha0", REG_A, REG_XY }, { "pushax", REG_AX, REG_Y }, + { "pusheax", REG_AX, REG_Y }, { "pushw0sp", REG_NONE, REG_AXY }, { "pushwysp", REG_Y, REG_AXY }, + { "shrax1", REG_AX, REG_AX }, + { "shrax2", REG_AX, REG_AX }, + { "shrax3", REG_AX, REG_AX }, + { "shreax1", REG_AX, REG_AX }, + { "shreax2", REG_AX, REG_AX }, + { "shreax3", REG_AX, REG_AX }, + { "staspidx", REG_A | REG_Y, REG_Y }, { "tosicmp", REG_AX, REG_AXY }, + { "tosshreax", REG_AX, REG_AXY }, }; #define FuncInfoCount (sizeof(FuncInfoTable) / sizeof(FuncInfoTable[0])) diff --git a/src/cc65/codeopt.c b/src/cc65/codeopt.c index 470836942..c596068be 100644 --- a/src/cc65/codeopt.c +++ b/src/cc65/codeopt.c @@ -1297,6 +1297,7 @@ static OptFunc OptFuncs [] = { /* Remove unused loads */ { OptUnusedLoads, "OptUnusedLoads", 0 }, { OptDuplicateLoads, "OptDuplicateLoads", 0 }, + { OptStoreLoad, "OptStoreLoad", 0 }, /* Optimize branch distance */ { OptBranchDist, "OptBranchDist", 0 }, }; diff --git a/src/cc65/coptind.c b/src/cc65/coptind.c index 0987d37db..ba1ffdc7f 100644 --- a/src/cc65/coptind.c +++ b/src/cc65/coptind.c @@ -682,7 +682,7 @@ unsigned OptDuplicateLoads (CodeSeg* S) unsigned char Use, Chg; CodeEntry* N; - + /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); @@ -797,7 +797,7 @@ unsigned OptDuplicateLoads (CodeSeg* S) RegA ^= (int) E->Num; } else { RegA = -1; - } + } } break; @@ -994,10 +994,16 @@ unsigned OptDuplicateLoads (CodeSeg* S) /* If the value in the Y register is known and the same as * that in the A register, replace the store by a STA. The * optimizer will then remove the load instruction for Y - * later. + * later. If replacement by A is not possible try a + * replacement by X, but check for invalid addressing modes + * in this case. */ - if (RegY >= 0 && RegY == RegA) { - CE_ReplaceOPC (E, OP65_STA); + if (RegY >= 0) { + if (RegY == RegA) { + CE_ReplaceOPC (E, OP65_STA); + } else if (RegY == RegX && E->AM != AM65_ABSX && E->AM != AM65_ZPX) { + CE_ReplaceOPC (E, OP65_STX); + } } break; @@ -1012,7 +1018,7 @@ unsigned OptDuplicateLoads (CodeSeg* S) break; case OP65_TAY: - N = CS_GetNextEntry (S, I); + N = CS_GetNextEntry (S, I); if (RegA >= 0 && RegA == RegY && N && (N->Info & OF_FBRA) == 0) { /* Value is identical and not followed by a branch */ Delete = 1; @@ -1083,6 +1089,50 @@ unsigned OptDuplicateLoads (CodeSeg* S) +unsigned OptStoreLoad (CodeSeg* S) +/* Remove a store followed by a load from the same location. */ +{ + unsigned Changes = 0; + + /* Walk over the entries */ + unsigned I = 0; + while (I < CS_GetEntryCount (S)) { + + CodeEntry* N; + CodeEntry* X; + + /* Get next entry */ + CodeEntry* E = CS_GetEntry (S, I); + + /* Check if it is a store instruction followed by a load from the + * same address which is itself not followed by a conditional branch. + */ + if ((E->Info & OF_STORE) != 0 && + (N = CS_GetNextEntry (S, I)) != 0 && + (N->Info & OF_LOAD) != 0 && + strcmp (E->Arg, N->Arg) == 0 && + (X = CS_GetNextEntry (S, I+1)) != 0 && + (X->Info & OF_FBRA) == 0) { + + /* Register value is not used, remove the load */ + CS_DelEntry (S, I+1); + + /* Remember, we had changes */ + ++Changes; + + } + + /* Next entry */ + ++I; + + } + + /* Return the number of changes made */ + return Changes; +} + + + /*****************************************************************************/ /* Optimize branch types */ /*****************************************************************************/ diff --git a/src/cc65/coptind.h b/src/cc65/coptind.h index a5bb5635b..30d9d1577 100644 --- a/src/cc65/coptind.h +++ b/src/cc65/coptind.h @@ -92,6 +92,9 @@ unsigned OptUnusedLoads (CodeSeg* S); unsigned OptDuplicateLoads (CodeSeg* S); /* Remove loads of registers where the value loaded is already in the register. */ +unsigned OptStoreLoad (CodeSeg* S); +/* Remove a store followed by a load from the same location. */ + unsigned OptBranchDist (CodeSeg* S); /* Change branches for the distance needed. */ diff --git a/src/cc65/opcodes.c b/src/cc65/opcodes.c index 167e1f19c..f70207871 100644 --- a/src/cc65/opcodes.c +++ b/src/cc65/opcodes.c @@ -611,21 +611,21 @@ const OPCDesc OPCTable[OPCODE_COUNT] = { 0, /* size */ REG_A, /* use */ REG_NONE, /* chg */ - OF_NONE /* flags */ + OF_STORE /* flags */ }, { OP65_STX, /* opcode */ "stx", /* mnemonic */ 0, /* size */ REG_X, /* use */ REG_NONE, /* chg */ - OF_NONE /* flags */ + OF_STORE /* flags */ }, { OP65_STY, /* opcode */ "sty", /* mnemonic */ 0, /* size */ REG_Y, /* use */ REG_NONE, /* chg */ - OF_NONE /* flags */ + OF_STORE /* flags */ }, { OP65_TAX, /* opcode */ "tax", /* mnemonic */ diff --git a/src/cc65/opcodes.h b/src/cc65/opcodes.h index e2369aa19..990a878e5 100644 --- a/src/cc65/opcodes.h +++ b/src/cc65/opcodes.h @@ -203,8 +203,9 @@ typedef enum { #define OF_LBRA 0x0100U /* Jump/branch is long */ #define OF_RET 0x0200U /* Return from function */ #define OF_LOAD 0x0400U /* Register load */ -#define OF_XFR 0x0800U /* Transfer instruction */ -#define OF_CALL 0x1000U /* A subroutine call */ +#define OF_STORE 0x0800U /* Register store */ +#define OF_XFR 0x1000U /* Transfer instruction */ +#define OF_CALL 0x2000U /* A subroutine call */ /* Combined infos */ #define OF_BRA (OF_UBRA | OF_CBRA) /* Operation is a jump/branch */ -- 2.39.5