From 4c19a5b69938f653aa8718880cdc5e390a7f0ff8 Mon Sep 17 00:00:00 2001 From: cuz Date: Sun, 20 May 2001 20:42:00 +0000 Subject: [PATCH] Working git-svn-id: svn://svn.cc65.org/cc65/trunk@735 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/cc65/codeinfo.c | 69 ++++++++++++--- src/cc65/codeopt.c | 203 ++++++++++++++++++++++++++++++++++++++++++-- src/cc65/codeseg.c | 10 +++ src/cc65/funcdesc.c | 6 +- src/cc65/funcdesc.h | 2 +- 5 files changed, 268 insertions(+), 22 deletions(-) diff --git a/src/cc65/codeinfo.c b/src/cc65/codeinfo.c index 9d41d877a..0bbeffad1 100644 --- a/src/cc65/codeinfo.c +++ b/src/cc65/codeinfo.c @@ -42,7 +42,9 @@ /* cc65 */ #include "codeent.h" #include "codeseg.h" +#include "datatype.h" #include "error.h" +#include "symtab.h" #include "codeinfo.h" @@ -132,20 +134,63 @@ void GetFuncInfo (const char* Name, unsigned char* Use, unsigned char* Chg) * load all registers. */ { - /* Search for the function */ - const FuncInfo* Info = bsearch (Name, FuncInfoTable, FuncInfoCount, - sizeof(FuncInfo), CompareFuncInfo); - - /* Do we know the function? */ - if (Info) { - /* Use the information we have */ - *Use = Info->Use; - *Chg = Info->Chg; + /* If the function name starts with an underline, it is an external + * function. Search for it in the symbol table. If the function does + * not start with an underline, it may be a runtime support function. + * Search for it in the list of builtin functions. + */ + if (Name[0] == '_') { + + /* Search in the symbol table, skip the leading underscore */ + SymEntry* E = FindSym (Name+1); + + /* Did we find it in the top level table? */ + if (E && E->Owner->PrevTab == 0 && IsTypeFunc (E->Type)) { + + /* A function may use the A or A/X registers if it is a fastcall + * function. Otherwise it does not use any registers passed by + * the caller. However, we assume that any function will destroy + * all registers. + */ + FuncDesc* D = E->V.F.Func; + if ((D->Flags & FD_FASTCALL) != 0 && D->ParamCount > 0) { + /* Will use registers depending on the last param */ + SymEntry* LastParam = D->SymTab->SymTail; + if (SizeOf (LastParam->Type) == 1) { + *Use = REG_A; + } else { + *Use = REG_AX; + } + } else { + /* Will not use any registers */ + *Use = REG_NONE; + } + + /* Will destroy all registers */ + *Chg = REG_AXY; + + /* Done */ + return; + } + } else { - /* Assume all registers used */ - *Use = REG_AXY; - *Chg = REG_AXY; + + /* Search for the function in the list of builtin functions */ + const FuncInfo* Info = bsearch (Name, FuncInfoTable, FuncInfoCount, + sizeof(FuncInfo), CompareFuncInfo); + + /* Do we know the function? */ + if (Info) { + /* Use the information we have */ + *Use = Info->Use; + *Chg = Info->Chg; + return; + } } + + /* Function not found - assume all registers used */ + *Use = REG_AXY; + *Chg = REG_AXY; } diff --git a/src/cc65/codeopt.c b/src/cc65/codeopt.c index 208414526..4b9dfefa2 100644 --- a/src/cc65/codeopt.c +++ b/src/cc65/codeopt.c @@ -243,7 +243,7 @@ static int IsLocalLoad16 (CodeSeg* S, unsigned Index, L[3]->OPC == OPC_DEY && !CodeEntryHasLabel (L[3]) && IsSpLoad (L[4]) && - !CodeEntryHasLabel (L[4])); + !CodeEntryHasLabel (L[4])); } @@ -420,6 +420,196 @@ NextEntry: +/*****************************************************************************/ +/* Optimize subtractions */ +/*****************************************************************************/ + + + +static unsigned OptSub1 (CodeSeg* S) +/* Search for the sequence + * + * sbc ... + * bcs L + * dex + * L: + * + * and remove the handling of the high byte if X is not used later. + */ +{ + unsigned Changes = 0; + + /* Walk over the entries */ + unsigned I = 0; + while (I < GetCodeEntryCount (S)) { + + CodeEntry* L[3]; + + /* Get next entry */ + CodeEntry* E = GetCodeEntry (S, I); + + /* Check for the sequence */ + if (E->OPC == OPC_SBC && + GetCodeEntries (S, L, I+1, 3) && + (L[0]->OPC == OPC_BCS || L[0]->OPC == OPC_JCS) && + L[0]->JumpTo != 0 && + !CodeEntryHasLabel (L[0]) && + L[1]->OPC == OPC_DEX && + !CodeEntryHasLabel (L[1]) && + L[0]->JumpTo->Owner == L[2] && + !RegXUsed (S, I+3)) { + + /* Remove the bcs/dex */ + DelCodeEntries (S, I+1, 2); + + /* Remember, we had changes */ + ++Changes; + + } + + /* Next entry */ + ++I; + + } + + /* Return the number of changes made */ + return Changes; +} + + + +static unsigned OptSub2 (CodeSeg* S) +/* Search for the sequence + * + * lda xx + * sec + * sta tmp1 + * lda yy + * sbc tmp1 + * sta yy + * + * and replace it by + * + * sec + * lda yy + * sbc xx + * sta yy + */ +{ + unsigned Changes = 0; + + /* Walk over the entries */ + unsigned I = 0; + while (I < GetCodeEntryCount (S)) { + + CodeEntry* L[5]; + + /* Get next entry */ + CodeEntry* E = GetCodeEntry (S, I); + + /* Check for the sequence */ + if (E->OPC == OPC_LDA && + GetCodeEntries (S, L, I+1, 5) && + L[0]->OPC == OPC_SEC && + !CodeEntryHasLabel (L[0]) && + L[1]->OPC == OPC_STA && + strcmp (L[1]->Arg, "tmp1") == 0 && + !CodeEntryHasLabel (L[1]) && + L[2]->OPC == OPC_LDA && + !CodeEntryHasLabel (L[2]) && + L[3]->OPC == OPC_SBC && + strcmp (L[3]->Arg, "tmp1") == 0 && + !CodeEntryHasLabel (L[3]) && + L[4]->OPC == OPC_STA && + strcmp (L[4]->Arg, L[2]->Arg) == 0 && + !CodeEntryHasLabel (L[4])) { + + /* Remove the store to tmp1 */ + DelCodeEntry (S, I+2); + + /* Remove the subtraction */ + DelCodeEntry (S, I+3); + + /* Move the lda to the position of the subtraction and change the + * op to SBC. + */ + MoveCodeEntry (S, I, I+3); + ReplaceOPC (E, OPC_SBC); + + /* Remember, we had changes */ + ++Changes; + + } + + /* Next entry */ + ++I; + + } + + /* Return the number of changes made */ + return Changes; +} + + + +/*****************************************************************************/ +/* Optimize additions */ +/*****************************************************************************/ + + + +static unsigned OptAdd1 (CodeSeg* S) +/* Search for the sequence + * + * adc ... + * bcc L + * inx + * L: + * + * and remove the handling of the high byte if X is not used later. + */ +{ + unsigned Changes = 0; + + /* Walk over the entries */ + unsigned I = 0; + while (I < GetCodeEntryCount (S)) { + + CodeEntry* L[3]; + + /* Get next entry */ + CodeEntry* E = GetCodeEntry (S, I); + + /* Check for the sequence */ + if (E->OPC == OPC_ADC && + GetCodeEntries (S, L, I+1, 3) && + (L[0]->OPC == OPC_BCC || L[0]->OPC == OPC_JCC) && + L[0]->JumpTo != 0 && + !CodeEntryHasLabel (L[0]) && + L[1]->OPC == OPC_INX && + !CodeEntryHasLabel (L[1]) && + L[0]->JumpTo->Owner == L[2] && + !RegXUsed (S, I+3)) { + + /* Remove the bcs/dex */ + DelCodeEntries (S, I+1, 2); + + /* Remember, we had changes */ + ++Changes; + + } + + /* Next entry */ + ++I; + + } + + /* Return the number of changes made */ + return Changes; +} + + + /*****************************************************************************/ /* Optimizations for compares */ /*****************************************************************************/ @@ -1007,6 +1197,11 @@ struct OptFunc { /* Table with optimizer steps - are called in this order */ static OptFunc OptFuncs [] = { + /* Optimize subtractions */ + { OptSub1, "OptSub1", 0 }, + { OptSub2, "OptSub2", 0 }, + /* Optimize additions */ + { OptAdd1, "OptAdd1", 0 }, /* Optimize jump cascades */ { OptJumpCascades, "OptJumpCascades", 0 }, /* Remove dead jumps */ @@ -1025,21 +1220,15 @@ static OptFunc OptFuncs [] = { { OptBoolTransforms, "OptBoolTransforms", 0 }, /* Optimize calls to nega */ { OptNegA1, "OptNegA1", 0 }, - /* Optimize calls to nega */ { OptNegA2, "OptNegA2", 0 }, /* Optimize calls to negax */ { OptNegAX1, "OptNegAX1", 0 }, - /* Optimize calls to negax */ { OptNegAX2, "OptNegAX2", 0 }, - /* Optimize calls to negax */ { OptNegAX3, "OptNegAX3", 0 }, /* Optimize compares */ { OptCmp1, "OptCmp1", 0 }, - /* Optimize compares */ { OptCmp2, "OptCmp2", 0 }, - /* Optimize compares */ { OptCmp3, "OptCmp3", 0 }, - /* Optimize compares */ { OptCmp4, "OptCmp4", 0 }, /* Remove unused loads */ { OptUnusedLoads, "OptUnusedLoads", 0 }, diff --git a/src/cc65/codeseg.c b/src/cc65/codeseg.c index fb971183a..6565d2b8f 100644 --- a/src/cc65/codeseg.c +++ b/src/cc65/codeseg.c @@ -889,6 +889,16 @@ void DelCodeSegAfter (CodeSeg* S, unsigned Last) /* Check if this entry has a label reference */ if (E->JumpTo) { + /* If the label is a label in the label pool and this is the last + * reference to the label, remove the label from the pool. + */ + CodeLabel* L = E->JumpTo; + int Index = CollIndex (&S->Labels, L); + if (Index >= 0 && CollCount (&L->JumpFrom) == 1) { + /* Delete it from the pool */ + CollDelete (&S->Labels, Index); + } + /* Remove the reference to the label */ RemoveCodeLabelRef (S, E); } diff --git a/src/cc65/funcdesc.c b/src/cc65/funcdesc.c index f5517586b..cccff02c2 100644 --- a/src/cc65/funcdesc.c +++ b/src/cc65/funcdesc.c @@ -33,8 +33,10 @@ -#include "../common/xmalloc.h" - +/* common */ +#include "xmalloc.h" + +/* cc65 */ #include "funcdesc.h" diff --git a/src/cc65/funcdesc.h b/src/cc65/funcdesc.h index eb62d3d48..d2c2ed57e 100644 --- a/src/cc65/funcdesc.h +++ b/src/cc65/funcdesc.h @@ -79,7 +79,7 @@ struct FuncDesc { FuncDesc* NewFuncDesc (void); /* Create a new symbol table with the given name */ -void FreeFuncDesc (FuncDesc* E); +void FreeFuncDesc (FuncDesc* D); /* Free a function descriptor */ -- 2.39.5