1
0
mirror of https://github.com/cc65/cc65.git synced 2025-04-04 06:29:41 +00:00
git-svn-id: svn://svn.cc65.org/cc65/trunk@735 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2001-05-20 20:42:00 +00:00
parent 3c04d5777f
commit 4c19a5b699
5 changed files with 267 additions and 21 deletions

View File

@ -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);
/* 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;
}
/* Do we know the function? */
if (Info) {
/* Use the information we have */
*Use = Info->Use;
*Chg = Info->Chg;
} 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;
}

View File

@ -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 },

View File

@ -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);
}

View File

@ -33,8 +33,10 @@
#include "../common/xmalloc.h"
/* common */
#include "xmalloc.h"
/* cc65 */
#include "funcdesc.h"

View File

@ -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 */