mirror of
https://github.com/cc65/cc65.git
synced 2024-12-23 19:29:37 +00:00
Allow enabling/disabline optimizer steps by file
git-svn-id: svn://svn.cc65.org/cc65/trunk@831 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
750cf445f7
commit
d341565ddc
@ -1662,67 +1662,78 @@ static unsigned OptPtrLoad2 (CodeSeg* S)
|
||||
|
||||
|
||||
|
||||
/* Types of optimization steps */
|
||||
enum {
|
||||
optPre, /* Repeated once */
|
||||
optPreMain, /* Repeated more than once */
|
||||
optMain, /* dito */
|
||||
optPostMain, /* dito */
|
||||
optPost /* Repeated once */
|
||||
};
|
||||
|
||||
/* Table with all the optimization functions */
|
||||
typedef struct OptFunc OptFunc;
|
||||
struct OptFunc {
|
||||
unsigned (*Func) (CodeSeg*);/* Optimizer function */
|
||||
const char* Name; /* Name of optimizer step */
|
||||
char Disabled; /* True if pass disabled */
|
||||
unsigned (*Func) (CodeSeg*); /* Optimizer function */
|
||||
const char* Name; /* Name of optimizer step */
|
||||
unsigned char Type; /* Type of this step */
|
||||
char Disabled; /* True if pass disabled */
|
||||
};
|
||||
|
||||
/* Macro that builds a table entry */
|
||||
#define OptEntry(func,type) { func, #func, type, 0 }
|
||||
|
||||
|
||||
/* Table with optimizer steps - are called in this order */
|
||||
/* Table with optimizer steps */
|
||||
static OptFunc OptFuncs [] = {
|
||||
/* Optimizes stores through pointers */
|
||||
{ OptPtrStore1, "OptPtrStore1", 0 },
|
||||
OptEntry (OptPtrStore1, optPre),
|
||||
/* Optimize loads through pointers */
|
||||
{ OptPtrLoad1, "OptPtrLoad1", 0 },
|
||||
{ OptPtrLoad2, "OptPtrLoad2", 0 },
|
||||
/* Optimize subtractions */
|
||||
{ OptSub1, "OptSub1", 0 },
|
||||
{ OptSub2, "OptSub2", 0 },
|
||||
/* Optimize additions */
|
||||
{ OptAdd1, "OptAdd1", 0 },
|
||||
/* Optimize jump cascades */
|
||||
{ OptJumpCascades, "OptJumpCascades", 0 },
|
||||
/* Remove dead jumps */
|
||||
{ OptDeadJumps, "OptDeadJumps", 0 },
|
||||
/* Change jsr/rts to jmp */
|
||||
{ OptRTS, "OptRTS", 0 },
|
||||
/* Remove dead code */
|
||||
{ OptDeadCode, "OptDeadCode", 0 },
|
||||
/* Optimize jump targets */
|
||||
{ OptJumpTarget, "OptJumpTarget", 0 },
|
||||
/* Optimize conditional branches */
|
||||
{ OptCondBranches, "OptCondBranches", 0 },
|
||||
/* Replace jumps to RTS by RTS */
|
||||
{ OptRTSJumps, "OptRTSJumps", 0 },
|
||||
/* Remove calls to the bool transformer subroutines */
|
||||
{ OptBoolTransforms, "OptBoolTransforms", 0 },
|
||||
OptEntry (OptPtrLoad1, optMain),
|
||||
OptEntry (OptPtrLoad2, optMain),
|
||||
/* Optimize calls to nega */
|
||||
{ OptNegA1, "OptNegA1", 0 },
|
||||
{ OptNegA2, "OptNegA2", 0 },
|
||||
OptEntry (OptNegA1, optPre),
|
||||
OptEntry (OptNegA2, optPre),
|
||||
/* Optimize calls to negax */
|
||||
{ OptNegAX1, "OptNegAX1", 0 },
|
||||
{ OptNegAX2, "OptNegAX2", 0 },
|
||||
{ OptNegAX3, "OptNegAX3", 0 },
|
||||
{ OptNegAX4, "OptNegAX4", 0 },
|
||||
OptEntry (OptNegAX1, optPre),
|
||||
OptEntry (OptNegAX2, optPre),
|
||||
OptEntry (OptNegAX3, optPre),
|
||||
OptEntry (OptNegAX4, optPre),
|
||||
/* Optimize subtractions */
|
||||
OptEntry (OptSub1, optMain),
|
||||
OptEntry (OptSub2, optMain),
|
||||
/* Optimize additions */
|
||||
OptEntry (OptAdd1, optMain),
|
||||
/* Optimize jump cascades */
|
||||
OptEntry (OptJumpCascades, optMain),
|
||||
/* Remove dead jumps */
|
||||
OptEntry (OptDeadJumps, optMain),
|
||||
/* Change jsr/rts to jmp */
|
||||
OptEntry (OptRTS, optMain),
|
||||
/* Remove dead code */
|
||||
OptEntry (OptDeadCode, optMain),
|
||||
/* Optimize jump targets */
|
||||
OptEntry (OptJumpTarget, optMain),
|
||||
/* Optimize conditional branches */
|
||||
OptEntry (OptCondBranches, optMain),
|
||||
/* Replace jumps to RTS by RTS */
|
||||
OptEntry (OptRTSJumps, optMain),
|
||||
/* Remove calls to the bool transformer subroutines */
|
||||
OptEntry (OptBoolTransforms, optMain),
|
||||
/* Optimize compares */
|
||||
{ OptCmp1, "OptCmp1", 0 },
|
||||
{ OptCmp2, "OptCmp2", 0 },
|
||||
{ OptCmp3, "OptCmp3", 0 },
|
||||
{ OptCmp4, "OptCmp4", 0 },
|
||||
{ OptCmp5, "OptCmp5", 0 },
|
||||
{ OptCmp6, "OptCmp6", 0 },
|
||||
OptEntry (OptCmp1, optMain),
|
||||
OptEntry (OptCmp2, optMain),
|
||||
OptEntry (OptCmp3, optMain),
|
||||
OptEntry (OptCmp4, optMain),
|
||||
OptEntry (OptCmp5, optMain),
|
||||
OptEntry (OptCmp6, optMain),
|
||||
/* Optimize tests */
|
||||
{ OptTest1, "OptTest1", 0 },
|
||||
OptEntry (OptTest1, optMain),
|
||||
/* Remove unused loads */
|
||||
{ OptUnusedLoads, "OptUnusedLoads", 0 },
|
||||
{ OptDuplicateLoads, "OptDuplicateLoads", 0 },
|
||||
{ OptStoreLoad, "OptStoreLoad", 0 },
|
||||
OptEntry (OptUnusedLoads, optMain),
|
||||
OptEntry (OptDuplicateLoads, optMain),
|
||||
OptEntry (OptStoreLoad, optMain),
|
||||
/* Optimize branch distance */
|
||||
{ OptBranchDist, "OptBranchDist", 0 },
|
||||
OptEntry (OptBranchDist, optMain),
|
||||
};
|
||||
|
||||
|
||||
@ -1756,7 +1767,7 @@ void DisableOpt (const char* Name)
|
||||
unsigned I;
|
||||
for (I = 0; I < sizeof(OptFuncs)/sizeof(OptFuncs[0]); ++I) {
|
||||
OptFuncs[I].Disabled = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
OptFunc* F = FindOptStep (Name);
|
||||
F->Disabled = 1;
|
||||
@ -1781,13 +1792,66 @@ void EnableOpt (const char* Name)
|
||||
|
||||
|
||||
|
||||
void RunOpt (CodeSeg* S)
|
||||
/* Run the optimizer */
|
||||
void ListOptSteps (FILE* F)
|
||||
/* List all optimization steps */
|
||||
{
|
||||
unsigned I;
|
||||
for (I = 0; I < sizeof(OptFuncs)/sizeof(OptFuncs[0]); ++I) {
|
||||
fprintf (F, "%s\n", OptFuncs[I].Name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void RepeatOptStep (CodeSeg* S, unsigned char Type, unsigned Max)
|
||||
/* Repeat the optimizer step of type Type at may Max times */
|
||||
{
|
||||
unsigned I;
|
||||
unsigned Pass = 0;
|
||||
unsigned OptChanges;
|
||||
|
||||
/* Repeat max times of until there are no more changes */
|
||||
do {
|
||||
/* Reset the number of changes */
|
||||
OptChanges = 0;
|
||||
|
||||
/* Keep the user hapy */
|
||||
Print (stdout, 1, " Optimizer pass %u:\n", ++Pass);
|
||||
|
||||
/* Run all optimization steps */
|
||||
for (I = 0; I < sizeof(OptFuncs)/sizeof(OptFuncs[0]); ++I) {
|
||||
|
||||
/* Get the table entry */
|
||||
const OptFunc* F = OptFuncs + I;
|
||||
|
||||
/* Check if the type matches */
|
||||
if (F->Type != Type) {
|
||||
/* Skip it */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Print the name of the following optimizer step */
|
||||
Print (stdout, 1, " %s:%*s", F->Name, (int) (30-strlen(F->Name)), "");
|
||||
|
||||
/* Check if the step is disabled */
|
||||
if (F->Disabled) {
|
||||
Print (stdout, 1, "Disabled\n");
|
||||
} else {
|
||||
unsigned Changes = F->Func (S);
|
||||
OptChanges += Changes;
|
||||
Print (stdout, 1, "%u Changes\n", Changes);
|
||||
}
|
||||
}
|
||||
|
||||
} while (--Max > 0 && OptChanges > 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void RunOpt (CodeSeg* S)
|
||||
/* Run the optimizer */
|
||||
{
|
||||
|
||||
/* If we shouldn't run the optimizer, bail out */
|
||||
if (!Optimize) {
|
||||
return;
|
||||
@ -1801,31 +1865,11 @@ void RunOpt (CodeSeg* S)
|
||||
}
|
||||
|
||||
/* Repeat all steps until there are no more changes */
|
||||
do {
|
||||
/* Reset the number of changes */
|
||||
OptChanges = 0;
|
||||
|
||||
/* Keep the user hapy */
|
||||
Print (stdout, 1, " Optimizer pass %u:\n", ++Pass);
|
||||
|
||||
/* Run all optimization steps */
|
||||
for (I = 0; I < sizeof(OptFuncs)/sizeof(OptFuncs[0]); ++I) {
|
||||
|
||||
/* Print the name of the following optimizer step */
|
||||
Print (stdout, 1, " %s:%*s", OptFuncs[I].Name,
|
||||
(int) (30-strlen(OptFuncs[I].Name)), "");
|
||||
|
||||
/* Check if the step is disabled */
|
||||
if (OptFuncs[I].Disabled) {
|
||||
Print (stdout, 1, "Disabled\n");
|
||||
} else {
|
||||
unsigned Changes = OptFuncs[I].Func (S);
|
||||
OptChanges += Changes;
|
||||
Print (stdout, 1, "%u Changes\n", Changes);
|
||||
}
|
||||
}
|
||||
|
||||
} while (OptChanges > 0);
|
||||
RepeatOptStep (S, optPre, 1);
|
||||
RepeatOptStep (S, optPreMain, 0xFFFF);
|
||||
RepeatOptStep (S, optMain, 0xFFFF);
|
||||
RepeatOptStep (S, optPostMain, 0xFFFF);
|
||||
RepeatOptStep (S, optPost, 1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -43,12 +43,6 @@
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
@ -61,6 +55,9 @@ void DisableOpt (const char* Name);
|
||||
void EnableOpt (const char* Name);
|
||||
/* Enable the optimization with the given name */
|
||||
|
||||
void ListOptSteps (FILE* F);
|
||||
/* List all optimization steps */
|
||||
|
||||
void RunOpt (CodeSeg* S);
|
||||
/* Run the optimizer */
|
||||
|
||||
|
@ -104,10 +104,12 @@ static void Usage (void)
|
||||
" --data-name seg\tSet the name of the DATA segment\n"
|
||||
" --debug\t\tDebug mode\n"
|
||||
" --debug-info\t\tAdd debug info to object file\n"
|
||||
" --debug-opt name\tDebug optimization steps\n"
|
||||
" --disable-opt name\tDisable an optimization step\n"
|
||||
" --enable-opt name\tEnable an optimization step\n"
|
||||
" --help\t\tHelp (this text)\n"
|
||||
" --include-dir dir\tSet an include directory search path\n"
|
||||
" --list-opt-steps\tList all optimizer steps\n"
|
||||
" --rodata-name seg\tSet the name of the RODATA segment\n"
|
||||
" --signed-chars\tDefault characters are signed\n"
|
||||
" --static-locals\tMake local variables static\n"
|
||||
@ -380,6 +382,73 @@ static void OptDebugInfo (const char* Opt, const char* Arg)
|
||||
|
||||
|
||||
|
||||
static void OptDebugOpt (const char* Opt, const char* Arg)
|
||||
/* Debug optimization steps */
|
||||
{
|
||||
char Buf [128];
|
||||
char* Line;
|
||||
|
||||
/* Open the file */
|
||||
FILE* F = fopen (Arg, "r");
|
||||
if (F == 0) {
|
||||
AbEnd ("Cannot open `%s': %s", Arg, strerror (errno));
|
||||
}
|
||||
|
||||
/* Read line by line, ignore empty lines and switch optimization
|
||||
* steps on/off.
|
||||
*/
|
||||
while (fgets (Buf, sizeof (Buf), F) != 0) {
|
||||
|
||||
/* Remove trailing control chars. This will also remove the
|
||||
* trailing newline.
|
||||
*/
|
||||
unsigned Len = strlen (Buf);
|
||||
while (Len > 0 && IsControl (Buf[Len-1])) {
|
||||
--Len;
|
||||
}
|
||||
Buf[Len] = '\0';
|
||||
|
||||
/* Get a pointer to the buffer and remove leading white space */
|
||||
Line = Buf;
|
||||
while (IsBlank (*Line)) {
|
||||
++Line;
|
||||
}
|
||||
|
||||
/* Check the first character and enable/disable the step or
|
||||
* ignore the line
|
||||
*/
|
||||
switch (*Line) {
|
||||
|
||||
case '\0':
|
||||
case '#':
|
||||
case ';':
|
||||
/* Empty or comment line */
|
||||
continue;
|
||||
|
||||
case '-':
|
||||
DisableOpt (Line+1);
|
||||
break;
|
||||
|
||||
case '+':
|
||||
++Line;
|
||||
/* FALLTHROUGH */
|
||||
|
||||
default:
|
||||
EnableOpt (Line);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Close the file, no error check here since we were just reading and
|
||||
* this is only a debug function.
|
||||
*/
|
||||
(void) fclose (F);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void OptDisableOpt (const char* Opt, const char* Arg)
|
||||
/* Disable an optimization step */
|
||||
{
|
||||
@ -413,6 +482,14 @@ static void OptIncludeDir (const char* Opt, const char* Arg)
|
||||
|
||||
|
||||
|
||||
static void OptListOptSteps (const char* Opt, const char* Arg)
|
||||
/* List all optimizer steps */
|
||||
{
|
||||
ListOptSteps (stdout);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void OptRodataName (const char* Opt, const char* Arg)
|
||||
/* Handle the --rodata-name option */
|
||||
{
|
||||
@ -482,10 +559,12 @@ int main (int argc, char* argv[])
|
||||
{ "--data-name", 1, OptDataName },
|
||||
{ "--debug", 0, OptDebug },
|
||||
{ "--debug-info", 0, OptDebugInfo },
|
||||
{ "--debug-opt", 1, OptDebugOpt },
|
||||
{ "--disable-opt", 1, OptDisableOpt },
|
||||
{ "--enable-opt", 1, OptEnableOpt, },
|
||||
{ "--help", 0, OptHelp },
|
||||
{ "--include-dir", 1, OptIncludeDir },
|
||||
{ "--list-opt-steps", 0, OptListOptSteps },
|
||||
{ "--rodata-name", 1, OptRodataName },
|
||||
{ "--signed-chars", 0, OptSignedChars },
|
||||
{ "--static-locals", 0, OptStaticLocals },
|
||||
|
Loading…
Reference in New Issue
Block a user