1
0
mirror of https://github.com/cc65/cc65.git synced 2025-01-11 11:30:13 +00:00

General fixes for prerequisites for optimization on certain std functions.

Added utility functions for extracting expression info.
This commit is contained in:
acqn 2023-10-11 22:29:15 +08:00
parent bb1b5c363e
commit 7b6f8249a0
3 changed files with 74 additions and 45 deletions

View File

@ -167,6 +167,17 @@ int ED_IsLocQuasiConst (const ExprDesc* Expr)
int ED_IsLocZP (const ExprDesc* Expr)
/* Return true if the expression is in a location on a zeropage */
{
return ED_IsLocRegister (Expr) ||
(ED_IsLocConst (Expr) &&
Expr->Sym != 0 &&
(Expr->Sym->Flags & SC_ZEROPAGE) != 0);
}
#if !defined(HAVE_INLINE) #if !defined(HAVE_INLINE)
int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr) int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr)
/* Return true if the expression is E_LOC_PRIMARY or E_LOC_EXPR */ /* Return true if the expression is E_LOC_PRIMARY or E_LOC_EXPR */
@ -302,6 +313,23 @@ int ED_IsQuasiConstAddr (const ExprDesc* Expr)
int ED_IsStackAddr (const ExprDesc* Expr)
/* Return true if the expression denotes a fixed address on stack */
{
return ED_IsAddrExpr (Expr) && ED_IsLocStack (Expr);
}
int ED_IsZPInd (const ExprDesc* Expr)
/* Return true if the expression is located on the zeropage */
{
return ED_IsIndExpr (Expr) && ED_IsLocZP (Expr);
}
int ED_IsNullPtr (const ExprDesc* Expr) int ED_IsNullPtr (const ExprDesc* Expr)
/* Return true if the given expression is a NULL pointer constant */ /* Return true if the given expression is a NULL pointer constant */
{ {

View File

@ -369,6 +369,9 @@ int ED_IsLocQuasiConst (const ExprDesc* Expr);
*/ */
#endif #endif
int ED_IsLocZP (const ExprDesc* Expr);
/* Return true if the expression is in a location on a zeropage */
#if defined(HAVE_INLINE) #if defined(HAVE_INLINE)
INLINE int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr) INLINE int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr)
/* Return true if the expression is E_LOC_PRIMARY or E_LOC_EXPR */ /* Return true if the expression is E_LOC_PRIMARY or E_LOC_EXPR */
@ -572,6 +575,12 @@ int ED_IsQuasiConstAddr (const ExprDesc* Expr);
** This can be a constant address or a stack variable address. ** This can be a constant address or a stack variable address.
*/ */
int ED_IsStackAddr (const ExprDesc* Expr);
/* Return true if the expression denotes a fixed address on stack */
int ED_IsZPInd (const ExprDesc* Expr);
/* Return true if the expression is located on the zeropage */
int ED_IsNullPtr (const ExprDesc* Expr); int ED_IsNullPtr (const ExprDesc* Expr);
/* Return true if the given expression is a NULL pointer constant */ /* Return true if the given expression is a NULL pointer constant */

View File

@ -280,13 +280,11 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
** generated, and emit better code. ** generated, and emit better code.
*/ */
if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 && if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) || (ED_IsConstAddr (&Arg2.Expr) || ED_IsZPInd (&Arg2.Expr)) &&
(ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) && (ED_IsConstAddr (&Arg1.Expr) || ED_IsZPInd (&Arg1.Expr))) {
((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
(ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)))) {
int Reg1 = ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr); int Reg1 = ED_IsZPInd (&Arg1.Expr);
int Reg2 = ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr); int Reg2 = ED_IsZPInd (&Arg2.Expr);
/* Drop the generated code */ /* Drop the generated code */
RemoveCode (&Arg1.Expr.Start); RemoveCode (&Arg1.Expr.Start);
@ -342,9 +340,9 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
} }
if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 && if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr) && ED_IsConstAddr (&Arg2.Expr) &&
ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) && ED_IsStackAddr (&Arg1.Expr) &&
(Arg1.Expr.IVal - StackPtr) + Arg3.Expr.IVal < 256) { ED_GetStackOffs (&Arg1.Expr, Arg3.Expr.IVal) < 256) {
/* It is possible to just use one index register even if the stack /* It is possible to just use one index register even if the stack
** offset is not zero, by adjusting the offset to the constant ** offset is not zero, by adjusting the offset to the constant
@ -353,7 +351,7 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
** than 256. Register space is zero page, which means that the ** than 256. Register space is zero page, which means that the
** address calculation could overflow in the linker. ** address calculation could overflow in the linker.
*/ */
int AllowOneIndex = !ED_IsLocRegister (&Arg2.Expr) && int AllowOneIndex = !ED_IsLocZP (&Arg2.Expr) &&
!(ED_IsLocNone (&Arg2.Expr) && Arg2.Expr.IVal < 256); !(ED_IsLocNone (&Arg2.Expr) && Arg2.Expr.IVal < 256);
/* Calculate the real stack offset */ /* Calculate the real stack offset */
@ -420,9 +418,9 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
} }
if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 && if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr) && ED_IsStackAddr (&Arg2.Expr) &&
(Arg2.Expr.IVal - StackPtr) + Arg3.Expr.IVal < 256 && ED_GetStackOffs (&Arg2.Expr, Arg3.Expr.IVal) < 256 &&
ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) { ED_IsConstAddr (&Arg1.Expr)) {
/* It is possible to just use one index register even if the stack /* It is possible to just use one index register even if the stack
** offset is not zero, by adjusting the offset to the constant ** offset is not zero, by adjusting the offset to the constant
@ -431,7 +429,7 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
** than 256. Register space is zero page, which means that the ** than 256. Register space is zero page, which means that the
** address calculation could overflow in the linker. ** address calculation could overflow in the linker.
*/ */
int AllowOneIndex = !ED_IsLocRegister (&Arg1.Expr) && int AllowOneIndex = !ED_IsLocZP (&Arg1.Expr) &&
!(ED_IsLocNone (&Arg1.Expr) && Arg1.Expr.IVal < 256); !(ED_IsLocNone (&Arg1.Expr) && Arg1.Expr.IVal < 256);
/* Calculate the real stack offset */ /* Calculate the real stack offset */
@ -497,8 +495,8 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
goto ExitPoint; goto ExitPoint;
} }
if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 && if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr) && ED_IsStackAddr (&Arg2.Expr) &&
(Offs = ED_GetStackOffs (&Arg2.Expr, 0)) == 0) { (Offs = ED_GetStackOffs (&Arg2.Expr, 0)) == 0) {
/* Drop the generated code but leave the load of the first argument*/ /* Drop the generated code but leave the load of the first argument*/
@ -637,10 +635,9 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
*/ */
if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 && if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
ED_IsConstAbsInt (&Arg2.Expr) && ED_IsConstAbsInt (&Arg2.Expr) &&
((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) || (ED_IsConstAddr (&Arg1.Expr) || ED_IsZPInd (&Arg1.Expr))) {
(ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)))) {
int Reg = ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr); int Reg = ED_IsZPInd (&Arg1.Expr);
/* Drop the generated code */ /* Drop the generated code */
RemoveCode (&Arg1.Expr.Start); RemoveCode (&Arg1.Expr.Start);
@ -689,8 +686,8 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 && if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
ED_IsConstAbsInt (&Arg2.Expr) && ED_IsConstAbsInt (&Arg2.Expr) &&
ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) && ED_IsStackAddr (&Arg1.Expr) &&
(Arg1.Expr.IVal - StackPtr) + Arg3.Expr.IVal < 256) { ED_GetStackOffs (&Arg1.Expr, Arg3.Expr.IVal) < 256) {
/* Calculate the real stack offset */ /* Calculate the real stack offset */
int Offs = ED_GetStackOffs (&Arg1.Expr, 0); int Offs = ED_GetStackOffs (&Arg1.Expr, 0);
@ -850,7 +847,7 @@ static void StdFunc_strcmp (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
/* We do now have Arg1 in the primary. Load the first character from /* We do now have Arg1 in the primary. Load the first character from
** this string and cast to int. This is the function result. ** this string and cast to int. This is the function result.
*/ */
IsArray = IsTypeArray (Arg1.Type) && ED_IsRVal (&Arg1.Expr); IsArray = IsTypeArray (Arg1.Type) && ED_IsAddrExpr (&Arg1.Expr);
if (IsArray && ED_IsLocStack (&Arg1.Expr) && if (IsArray && ED_IsLocStack (&Arg1.Expr) &&
(Offs = ED_GetStackOffs (&Arg1.Expr, 0) < 256)) { (Offs = ED_GetStackOffs (&Arg1.Expr, 0) < 256)) {
/* Drop the generated code */ /* Drop the generated code */
@ -878,22 +875,20 @@ static void StdFunc_strcmp (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
} }
} else if ((IS_Get (&CodeSizeFactor) >= 165) && } else if ((IS_Get (&CodeSizeFactor) >= 165) &&
((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) || (ED_IsConstAddr (&Arg2.Expr) || ED_IsZPInd (&Arg2.Expr)) &&
(ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) && (ED_IsConstAddr (&Arg1.Expr) || ED_IsZPInd (&Arg1.Expr)) &&
((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
(ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr))) &&
(IS_Get (&EagerlyInlineFuncs) || (ECount1 > 0 && ECount1 < 256))) { (IS_Get (&EagerlyInlineFuncs) || (ECount1 > 0 && ECount1 < 256))) {
unsigned Entry, Loop, Fin; /* Labels */ unsigned Entry, Loop, Fin; /* Labels */
const char* Load; const char* Load;
const char* Compare; const char* Compare;
if (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)) { if (ED_IsZPInd (&Arg1.Expr)) {
Load = "lda (%s),y"; Load = "lda (%s),y";
} else { } else {
Load = "lda %s,y"; Load = "lda %s,y";
} }
if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) { if (ED_IsZPInd (&Arg2.Expr)) {
Compare = "cmp (%s),y"; Compare = "cmp (%s),y";
} else { } else {
Compare = "cmp %s,y"; Compare = "cmp %s,y";
@ -924,14 +919,13 @@ static void StdFunc_strcmp (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
g_defcodelabel (Fin); g_defcodelabel (Fin);
} else if ((IS_Get (&CodeSizeFactor) > 190) && } else if ((IS_Get (&CodeSizeFactor) > 190) &&
((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) || (ED_IsConstAddr (&Arg2.Expr) || ED_IsZPInd (&Arg2.Expr)) &&
(ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
(IS_Get (&EagerlyInlineFuncs) || (ECount1 > 0 && ECount1 < 256))) { (IS_Get (&EagerlyInlineFuncs) || (ECount1 > 0 && ECount1 < 256))) {
unsigned Entry, Loop, Fin; /* Labels */ unsigned Entry, Loop, Fin; /* Labels */
const char* Compare; const char* Compare;
if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) { if (ED_IsZPInd (&Arg2.Expr)) {
Compare = "cmp (%s),y"; Compare = "cmp (%s),y";
} else { } else {
Compare = "cmp %s,y"; Compare = "cmp %s,y";
@ -1028,21 +1022,19 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
** be generated. If such a situation is detected, throw away the ** be generated. If such a situation is detected, throw away the
** generated, and emit better code. ** generated, and emit better code.
*/ */
if (((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) || if ((ED_IsConstAddr (&Arg2.Expr) || ED_IsZPInd (&Arg2.Expr)) &&
(ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) && (ED_IsConstAddr (&Arg1.Expr) || ED_IsZPInd (&Arg1.Expr)) &&
((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
(ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr))) &&
(IS_Get (&EagerlyInlineFuncs) || (IS_Get (&EagerlyInlineFuncs) ||
(ECount != UNSPECIFIED && ECount < 256))) { (ECount != UNSPECIFIED && ECount < 256))) {
const char* Load; const char* Load;
const char* Store; const char* Store;
if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) { if (ED_IsZPInd (&Arg2.Expr)) {
Load = "lda (%s),y"; Load = "lda (%s),y";
} else { } else {
Load = "lda %s,y"; Load = "lda %s,y";
} }
if (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)) { if (ED_IsZPInd (&Arg1.Expr)) {
Store = "sta (%s),y"; Store = "sta (%s),y";
} else { } else {
Store = "sta %s,y"; Store = "sta %s,y";
@ -1069,9 +1061,9 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
goto ExitPoint; goto ExitPoint;
} }
if (ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr) && if (ED_IsStackAddr (&Arg2.Expr) &&
StackPtr >= -255 && StackPtr >= -255 &&
ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) { ED_IsConstAddr (&Arg1.Expr)) {
/* It is possible to just use one index register even if the stack /* It is possible to just use one index register even if the stack
** offset is not zero, by adjusting the offset to the constant ** offset is not zero, by adjusting the offset to the constant
@ -1080,7 +1072,7 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
** than 256. Register space is zero page, which means that the ** than 256. Register space is zero page, which means that the
** address calculation could overflow in the linker. ** address calculation could overflow in the linker.
*/ */
int AllowOneIndex = !ED_IsLocRegister (&Arg1.Expr) && int AllowOneIndex = !ED_IsLocZP (&Arg1.Expr) &&
!(ED_IsLocNone (&Arg1.Expr) && Arg1.Expr.IVal < 256); !(ED_IsLocNone (&Arg1.Expr) && Arg1.Expr.IVal < 256);
/* Calculate the real stack offset */ /* Calculate the real stack offset */
@ -1116,8 +1108,8 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
goto ExitPoint; goto ExitPoint;
} }
if (ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr) && if (ED_IsConstAddr (&Arg2.Expr) &&
ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) && ED_IsStackAddr (&Arg1.Expr) &&
StackPtr >= -255) { StackPtr >= -255) {
/* It is possible to just use one index register even if the stack /* It is possible to just use one index register even if the stack
@ -1127,7 +1119,7 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
** than 256. Register space is zero page, which means that the ** than 256. Register space is zero page, which means that the
** address calculation could overflow in the linker. ** address calculation could overflow in the linker.
*/ */
int AllowOneIndex = !ED_IsLocRegister (&Arg2.Expr) && int AllowOneIndex = !ED_IsLocZP (&Arg2.Expr) &&
!(ED_IsLocNone (&Arg2.Expr) && Arg2.Expr.IVal < 256); !(ED_IsLocNone (&Arg2.Expr) && Arg2.Expr.IVal < 256);
/* Calculate the real stack offset */ /* Calculate the real stack offset */
@ -1276,7 +1268,7 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
** completely within the reach of a byte sized index register. ** completely within the reach of a byte sized index register.
*/ */
if (ED_IsLocStack (&Arg) && IsArray && IsByteIndex && if (ED_IsLocStack (&Arg) && IsArray && IsByteIndex &&
(Arg.IVal - StackPtr) + ECount < 256) { ED_GetStackOffs (&Arg, ECount) < 256) {
/* Calculate the true stack offset */ /* Calculate the true stack offset */
int Offs = ED_GetStackOffs (&Arg, 0); int Offs = ED_GetStackOffs (&Arg, 0);
@ -1305,7 +1297,7 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
** get inlined if requested on the command line, since we cannot know how ** get inlined if requested on the command line, since we cannot know how
** big the buffer actually is, so inlining is not always safe. ** big the buffer actually is, so inlining is not always safe.
*/ */
if (ED_IsLocRegister (&Arg) && ED_IsLVal (&Arg) && IsPtr && if (ED_IsZPInd (&Arg) && IsPtr &&
IS_Get (&EagerlyInlineFuncs)) { IS_Get (&EagerlyInlineFuncs)) {
/* Generate the strlen code */ /* Generate the strlen code */