1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-24 11:31:31 +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)
int ED_IsLocPrimaryOrExpr (const ExprDesc* 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)
/* Return true if the given expression is a NULL pointer constant */
{

View File

@ -369,6 +369,9 @@ int ED_IsLocQuasiConst (const ExprDesc* Expr);
*/
#endif
int ED_IsLocZP (const ExprDesc* Expr);
/* Return true if the expression is in a location on a zeropage */
#if defined(HAVE_INLINE)
INLINE int ED_IsLocPrimaryOrExpr (const ExprDesc* 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.
*/
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);
/* 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.
*/
if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) ||
(ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
(ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)))) {
(ED_IsConstAddr (&Arg2.Expr) || ED_IsZPInd (&Arg2.Expr)) &&
(ED_IsConstAddr (&Arg1.Expr) || ED_IsZPInd (&Arg1.Expr))) {
int Reg1 = ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr);
int Reg2 = ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr);
int Reg1 = ED_IsZPInd (&Arg1.Expr);
int Reg2 = ED_IsZPInd (&Arg2.Expr);
/* Drop the generated code */
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 &&
ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr) &&
ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) &&
(Arg1.Expr.IVal - StackPtr) + Arg3.Expr.IVal < 256) {
ED_IsConstAddr (&Arg2.Expr) &&
ED_IsStackAddr (&Arg1.Expr) &&
ED_GetStackOffs (&Arg1.Expr, Arg3.Expr.IVal) < 256) {
/* It is possible to just use one index register even if the stack
** 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
** 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);
/* 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 &&
ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr) &&
(Arg2.Expr.IVal - StackPtr) + Arg3.Expr.IVal < 256 &&
ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) {
ED_IsStackAddr (&Arg2.Expr) &&
ED_GetStackOffs (&Arg2.Expr, Arg3.Expr.IVal) < 256 &&
ED_IsConstAddr (&Arg1.Expr)) {
/* It is possible to just use one index register even if the stack
** 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
** 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);
/* Calculate the real stack offset */
@ -498,7 +496,7 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
}
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) {
/* 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 &&
ED_IsConstAbsInt (&Arg2.Expr) &&
((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
(ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)))) {
(ED_IsConstAddr (&Arg1.Expr) || ED_IsZPInd (&Arg1.Expr))) {
int Reg = ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr);
int Reg = ED_IsZPInd (&Arg1.Expr);
/* Drop the generated code */
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 &&
ED_IsConstAbsInt (&Arg2.Expr) &&
ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) &&
(Arg1.Expr.IVal - StackPtr) + Arg3.Expr.IVal < 256) {
ED_IsStackAddr (&Arg1.Expr) &&
ED_GetStackOffs (&Arg1.Expr, Arg3.Expr.IVal) < 256) {
/* Calculate the real stack offset */
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
** 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) &&
(Offs = ED_GetStackOffs (&Arg1.Expr, 0) < 256)) {
/* Drop the generated code */
@ -878,22 +875,20 @@ static void StdFunc_strcmp (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
}
} else if ((IS_Get (&CodeSizeFactor) >= 165) &&
((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) ||
(ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
(ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr))) &&
(ED_IsConstAddr (&Arg2.Expr) || ED_IsZPInd (&Arg2.Expr)) &&
(ED_IsConstAddr (&Arg1.Expr) || ED_IsZPInd (&Arg1.Expr)) &&
(IS_Get (&EagerlyInlineFuncs) || (ECount1 > 0 && ECount1 < 256))) {
unsigned Entry, Loop, Fin; /* Labels */
const char* Load;
const char* Compare;
if (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)) {
if (ED_IsZPInd (&Arg1.Expr)) {
Load = "lda (%s),y";
} else {
Load = "lda %s,y";
}
if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) {
if (ED_IsZPInd (&Arg2.Expr)) {
Compare = "cmp (%s),y";
} else {
Compare = "cmp %s,y";
@ -924,14 +919,13 @@ static void StdFunc_strcmp (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
g_defcodelabel (Fin);
} else if ((IS_Get (&CodeSizeFactor) > 190) &&
((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) ||
(ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
(ED_IsConstAddr (&Arg2.Expr) || ED_IsZPInd (&Arg2.Expr)) &&
(IS_Get (&EagerlyInlineFuncs) || (ECount1 > 0 && ECount1 < 256))) {
unsigned Entry, Loop, Fin; /* Labels */
const char* Compare;
if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) {
if (ED_IsZPInd (&Arg2.Expr)) {
Compare = "cmp (%s),y";
} else {
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
** generated, and emit better code.
*/
if (((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) ||
(ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
(ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr))) &&
if ((ED_IsConstAddr (&Arg2.Expr) || ED_IsZPInd (&Arg2.Expr)) &&
(ED_IsConstAddr (&Arg1.Expr) || ED_IsZPInd (&Arg1.Expr)) &&
(IS_Get (&EagerlyInlineFuncs) ||
(ECount != UNSPECIFIED && ECount < 256))) {
const char* Load;
const char* Store;
if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) {
if (ED_IsZPInd (&Arg2.Expr)) {
Load = "lda (%s),y";
} else {
Load = "lda %s,y";
}
if (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)) {
if (ED_IsZPInd (&Arg1.Expr)) {
Store = "sta (%s),y";
} else {
Store = "sta %s,y";
@ -1069,9 +1061,9 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
goto ExitPoint;
}
if (ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr) &&
if (ED_IsStackAddr (&Arg2.Expr) &&
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
** 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
** 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);
/* Calculate the real stack offset */
@ -1116,8 +1108,8 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
goto ExitPoint;
}
if (ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr) &&
ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) &&
if (ED_IsConstAddr (&Arg2.Expr) &&
ED_IsStackAddr (&Arg1.Expr) &&
StackPtr >= -255) {
/* 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
** 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);
/* 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.
*/
if (ED_IsLocStack (&Arg) && IsArray && IsByteIndex &&
(Arg.IVal - StackPtr) + ECount < 256) {
ED_GetStackOffs (&Arg, ECount) < 256) {
/* Calculate the true stack offset */
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
** 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)) {
/* Generate the strlen code */