Fix for multiplication optimization issue #367

This commit is contained in:
IrgendwerA8 2019-04-01 21:47:00 +02:00 committed by Oliver Schmidt
parent ae261e91f2
commit 1530020a1f
2 changed files with 40 additions and 15 deletions

View file

@ -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
View 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