Fix for multiplication optimization issue #367
This commit is contained in:
parent
ae261e91f2
commit
1530020a1f
2 changed files with 40 additions and 15 deletions
|
@ -6,7 +6,7 @@
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 2001-2013, Ullrich von Bassewitz */
|
/* (C) 2001-2019, Ullrich von Bassewitz */
|
||||||
/* Roemerstrasse 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
|
@ -122,7 +122,7 @@ struct StackOpData {
|
||||||
const OptFuncDesc* OptFunc;
|
const OptFuncDesc* OptFunc;
|
||||||
|
|
||||||
/* ZP register usage inside the sequence */
|
/* ZP register usage inside the sequence */
|
||||||
unsigned UsedRegs;
|
unsigned ZPUsage;
|
||||||
|
|
||||||
/* Register load information for lhs and rhs */
|
/* Register load information for lhs and rhs */
|
||||||
LoadInfo Lhs;
|
LoadInfo Lhs;
|
||||||
|
@ -1771,7 +1771,7 @@ static void ResetStackOpData (StackOpData* Data)
|
||||||
/* Reset the given data structure */
|
/* Reset the given data structure */
|
||||||
{
|
{
|
||||||
Data->OptFunc = 0;
|
Data->OptFunc = 0;
|
||||||
Data->UsedRegs = REG_NONE;
|
Data->ZPUsage = REG_NONE;
|
||||||
|
|
||||||
ClearLoadInfo (&Data->Lhs);
|
ClearLoadInfo (&Data->Lhs);
|
||||||
ClearLoadInfo (&Data->Rhs);
|
ClearLoadInfo (&Data->Rhs);
|
||||||
|
@ -1832,14 +1832,16 @@ static int PreCondOk (StackOpData* D)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine the zero page locations to use */
|
/* Determine the zero page locations to use. We've tracked the used
|
||||||
if ((D->UsedRegs & REG_PTR1) == REG_NONE) {
|
* ZP locations, so try to find some for us that are unused.
|
||||||
|
*/
|
||||||
|
if ((D->ZPUsage & REG_PTR1) == REG_NONE) {
|
||||||
D->ZPLo = "ptr1";
|
D->ZPLo = "ptr1";
|
||||||
D->ZPHi = "ptr1+1";
|
D->ZPHi = "ptr1+1";
|
||||||
} else if ((D->UsedRegs & REG_SREG) == REG_NONE) {
|
} else if ((D->ZPUsage & REG_SREG) == REG_NONE) {
|
||||||
D->ZPLo = "sreg";
|
D->ZPLo = "sreg";
|
||||||
D->ZPHi = "sreg+1";
|
D->ZPHi = "sreg+1";
|
||||||
} else if ((D->UsedRegs & REG_PTR2) == REG_NONE) {
|
} else if ((D->ZPUsage & REG_PTR2) == REG_NONE) {
|
||||||
D->ZPLo = "ptr2";
|
D->ZPLo = "ptr2";
|
||||||
D->ZPHi = "ptr2+1";
|
D->ZPHi = "ptr2+1";
|
||||||
} else {
|
} else {
|
||||||
|
@ -1959,7 +1961,7 @@ unsigned OptStackOps (CodeSeg* S)
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
/* Track register usage */
|
/* Track register usage */
|
||||||
Data.UsedRegs |= (E->Use | E->Chg);
|
Data.ZPUsage |= (E->Use | E->Chg);
|
||||||
TrackLoads (&Data.Rhs, E, I);
|
TrackLoads (&Data.Rhs, E, I);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1991,7 +1993,7 @@ unsigned OptStackOps (CodeSeg* S)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* Other stuff: Track register usage */
|
/* Other stuff: Track register usage */
|
||||||
Data.UsedRegs |= (E->Use | E->Chg);
|
Data.ZPUsage |= (E->Use | E->Chg);
|
||||||
TrackLoads (&Data.Rhs, E, I);
|
TrackLoads (&Data.Rhs, E, I);
|
||||||
}
|
}
|
||||||
/* If the registers from the push (A/X) are used before they're
|
/* If the registers from the push (A/X) are used before they're
|
||||||
|
@ -2009,21 +2011,32 @@ unsigned OptStackOps (CodeSeg* S)
|
||||||
|
|
||||||
case FoundOp:
|
case FoundOp:
|
||||||
/* Track zero page location usage beyond this point */
|
/* Track zero page location usage beyond this point */
|
||||||
Data.UsedRegs |= GetRegInfo (S, I, REG_SREG | REG_PTR1 | REG_PTR2);
|
Data.ZPUsage |= GetRegInfo (S, I, REG_SREG | REG_PTR1 | REG_PTR2);
|
||||||
|
|
||||||
/* Finalize the load info */
|
/* Finalize the load info */
|
||||||
FinalizeLoadInfo (&Data.Lhs, S);
|
FinalizeLoadInfo (&Data.Lhs, S);
|
||||||
FinalizeLoadInfo (&Data.Rhs, S);
|
FinalizeLoadInfo (&Data.Rhs, S);
|
||||||
|
|
||||||
/* If the Lhs loads do load from zeropage, we have to include
|
/* Check if the lhs loads from zeropage. If this is true, these
|
||||||
** them into UsedRegs registers used. The Rhs loads have already
|
* zero page locations have to be added to ZPUsage, because
|
||||||
** been tracked.
|
* they cannot be used for intermediate storage. In addition,
|
||||||
|
* if one of these zero page locations is destroyed between
|
||||||
|
* pushing the lhs and the actual operation, we cannot use the
|
||||||
|
* original zero page locations for the final op, but must
|
||||||
|
* use another ZP location to save them.
|
||||||
*/
|
*/
|
||||||
|
ChangedRegs &= REG_ZP;
|
||||||
if (Data.Lhs.A.LoadEntry && Data.Lhs.A.LoadEntry->AM == AM65_ZP) {
|
if (Data.Lhs.A.LoadEntry && Data.Lhs.A.LoadEntry->AM == AM65_ZP) {
|
||||||
Data.UsedRegs |= Data.Lhs.A.LoadEntry->Use;
|
Data.ZPUsage |= Data.Lhs.A.LoadEntry->Use;
|
||||||
|
if ((Data.Lhs.A.LoadEntry->Use & ChangedRegs) != 0) {
|
||||||
|
Data.Lhs.A.Flags &= ~(LI_DIRECT | LI_RELOAD_Y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (Data.Lhs.X.LoadEntry && Data.Lhs.X.LoadEntry->AM == AM65_ZP) {
|
if (Data.Lhs.X.LoadEntry && Data.Lhs.X.LoadEntry->AM == AM65_ZP) {
|
||||||
Data.UsedRegs |= Data.Lhs.X.LoadEntry->Use;
|
Data.ZPUsage |= Data.Lhs.X.LoadEntry->Use;
|
||||||
|
if ((Data.Lhs.X.LoadEntry->Use & ChangedRegs) != 0) {
|
||||||
|
Data.Lhs.X.Flags &= ~(LI_DIRECT | LI_RELOAD_Y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check the preconditions. If they aren't ok, reset the insn
|
/* Check the preconditions. If they aren't ok, reset the insn
|
||||||
|
|
12
test/val/bug367.c
Normal file
12
test/val/bug367.c
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#include "unittest.h"
|
||||||
|
|
||||||
|
TEST
|
||||||
|
{
|
||||||
|
unsigned int y=192;
|
||||||
|
unsigned int d=y&0xFFF8;
|
||||||
|
unsigned int e=d*32+d*8;
|
||||||
|
unsigned int f=d*40;
|
||||||
|
|
||||||
|
ASSERT_AreEqual(f, e, "%u", "Multiplication results differ (should be 7680)!");
|
||||||
|
}
|
||||||
|
ENDTEST
|
Loading…
Add table
Reference in a new issue