From b2c1a77bb389bf20b5043f796f2dee496c07fdbd Mon Sep 17 00:00:00 2001 From: Greg King Date: Thu, 24 Dec 2020 12:27:09 -0500 Subject: [PATCH] Fixed the cc65 code that optimizes 16-bit compares when the high bytes are known to be equal. Only the low bytes are compared. Originally, signed 16-bit compares were optimized into signed 8-bit compares. But, the sign bits are in the high bytes; and, they're equal. Therefore, the low bytes always must be compared as unsigned numbers. Fixes #1348. --- src/cc65/coptstop.c | 78 +++++++++++------------------------- test/misc/Makefile | 8 ---- test/{misc => val}/bug1348.c | 28 ++++++------- 3 files changed, 37 insertions(+), 77 deletions(-) rename test/{misc => val}/bug1348.c (61%) diff --git a/src/cc65/coptstop.c b/src/cc65/coptstop.c index 59bbe6dc9..77b79281b 100644 --- a/src/cc65/coptstop.c +++ b/src/cc65/coptstop.c @@ -287,7 +287,7 @@ static unsigned Opt_tosshift (StackOpData* D, const char* Name) /* ldx */ X = NewCodeEntry (OP65_LDX, LoadX->AM, LoadX->Arg, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); - + /* Lhs load entries can be removed if not used later */ D->Lhs.X.Flags |= LI_REMOVE; D->Lhs.A.Flags |= LI_REMOVE; @@ -1100,7 +1100,7 @@ static unsigned Opt_tosxorax (StackOpData* D) static unsigned Opt_a_toscmpbool (StackOpData* D, const char* BoolTransformer) -/* Optimize the tos compare sequence with a bool transformer */ +/* Optimize the TOS compare sequence with a bool transformer */ { CodeEntry* X; cmp_t Cond; @@ -1119,9 +1119,8 @@ static unsigned Opt_a_toscmpbool (StackOpData* D, const char* BoolTransformer) D->Rhs.A.Flags |= LI_REMOVE; } else if ((D->Lhs.A.Flags & LI_DIRECT) != 0) { - - /* If the lhs is direct (but not stack relative), encode compares with lhs - ** effectively reverting the order (which doesn't matter for ==). + /* If the lhs is direct (but not stack relative), encode compares with lhs, + ** effectively reversing the order (which doesn't matter for == and !=). */ Cond = FindBoolCmpCond (BoolTransformer); Cond = GetRevertedCond (Cond); @@ -1138,7 +1137,6 @@ static unsigned Opt_a_toscmpbool (StackOpData* D, const char* BoolTransformer) D->Lhs.A.Flags |= LI_REMOVE; } else { - /* We'll do reverse-compare */ Cond = FindBoolCmpCond (BoolTransformer); Cond = GetRevertedCond (Cond); @@ -1162,7 +1160,7 @@ static unsigned Opt_a_toscmpbool (StackOpData* D, const char* BoolTransformer) X = NewCodeEntry (OP65_JSR, AM65_ABS, BoolTransformer, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); - /* Remove the push and the call to the tosgeax function */ + /* Remove the push and the call to the TOS function */ RemoveRemainders (D); /* We changed the sequence */ @@ -1179,22 +1177,6 @@ static unsigned Opt_a_toseq (StackOpData* D) -static unsigned Opt_a_tosge (StackOpData* D) -/* Optimize the tosgeax sequence */ -{ - return Opt_a_toscmpbool (D, "boolge"); -} - - - -static unsigned Opt_a_tosgt (StackOpData* D) -/* Optimize the tosgtax sequence */ -{ - return Opt_a_toscmpbool (D, "boolgt"); -} - - - static unsigned Opt_a_tosicmp (StackOpData* D) /* Replace tosicmp with CMP */ { @@ -1236,7 +1218,7 @@ static unsigned Opt_a_tosicmp (StackOpData* D) } InsertEntry (D, X, D->IP++); - /* cmp src,y OR cmp (sp),y*/ + /* cmp src,y OR cmp (sp),y */ if (D->Rhs.A.LoadEntry->OPC == OP65_JSR) { /* opc (sp),y */ X = NewCodeEntry (OP65_CMP, AM65_ZP_INDY, "sp", 0, D->OpEntry->LI); @@ -1268,18 +1250,18 @@ static unsigned Opt_a_tosicmp (StackOpData* D) InsertEntry (D, X, D->IP-3); } else { - /* Just clear A,Z,N and set C */ + /* Just clear A,Z,N; and set C */ + Arg = MakeHexArg (0); if ((RI = GetLastChangedRegInfo (D, &D->Lhs.A)) != 0 && RegValIsKnown (RI->Out.RegA) && (RI->Out.RegA & 0xFF) == 0) { - Arg = MakeHexArg (0); - X = NewCodeEntry (OP65_CMP, AM65_IMM, Arg, 0, D->OpEntry->LI); + + X = NewCodeEntry (OP65_CMP, AM65_IMM, Arg, 0, D->OpEntry->LI); InsertEntry (D, X, D->OpIndex + 1); } else { - Arg = MakeHexArg (0); - X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, D->OpEntry->LI); + X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, D->OpEntry->LI); InsertEntry (D, X, D->OpIndex + 1); - X = NewCodeEntry (OP65_CMP, AM65_IMM, Arg, 0, D->OpEntry->LI); + X = NewCodeEntry (OP65_CMP, AM65_IMM, Arg, 0, D->OpEntry->LI); InsertEntry (D, X, D->OpIndex + 2); } } @@ -1292,24 +1274,8 @@ static unsigned Opt_a_tosicmp (StackOpData* D) -static unsigned Opt_a_tosle (StackOpData* D) -/* Optimize the tosleax sequence */ -{ - return Opt_a_toscmpbool (D, "boolle"); -} - - - -static unsigned Opt_a_toslt (StackOpData* D) -/* Optimize the tosltax sequence */ -{ - return Opt_a_toscmpbool (D, "boollt"); -} - - - static unsigned Opt_a_tosne (StackOpData* D) -/* Optimize the toseqax sequence */ +/* Optimize the tosneax sequence */ { return Opt_a_toscmpbool (D, "boolne"); } @@ -1317,7 +1283,7 @@ static unsigned Opt_a_tosne (StackOpData* D) static unsigned Opt_a_tosuge (StackOpData* D) -/* Optimize the tosugeax sequence */ +/* Optimize the tosgeax and tosugeax sequences */ { return Opt_a_toscmpbool (D, "booluge"); } @@ -1325,7 +1291,7 @@ static unsigned Opt_a_tosuge (StackOpData* D) static unsigned Opt_a_tosugt (StackOpData* D) -/* Optimize the tosugtax sequence */ +/* Optimize the tosgtax and tosugtax sequences */ { return Opt_a_toscmpbool (D, "boolugt"); } @@ -1333,7 +1299,7 @@ static unsigned Opt_a_tosugt (StackOpData* D) static unsigned Opt_a_tosule (StackOpData* D) -/* Optimize the tosuleax sequence */ +/* Optimize the tosleax and tosuleax sequences */ { return Opt_a_toscmpbool (D, "boolule"); } @@ -1341,7 +1307,7 @@ static unsigned Opt_a_tosule (StackOpData* D) static unsigned Opt_a_tosult (StackOpData* D) -/* Optimize the tosultax sequence */ +/* Optimize the tosltax and tosultax sequences */ { return Opt_a_toscmpbool (D, "boolult"); } @@ -1354,6 +1320,8 @@ static unsigned Opt_a_tosult (StackOpData* D) +/* The first column of these two tables must be sorted in lexical order */ + static const OptFuncDesc FuncTable[] = { { "__bzero", Opt___bzero, REG_NONE, OP_X_ZERO | OP_A_KNOWN }, { "staspidx", Opt_staspidx, REG_NONE, OP_NONE }, @@ -1379,11 +1347,11 @@ static const OptFuncDesc FuncTable[] = { static const OptFuncDesc FuncRegATable[] = { { "toseqax", Opt_a_toseq, REG_NONE, OP_NONE }, - { "tosgeax", Opt_a_tosge, REG_NONE, OP_NONE }, - { "tosgtax", Opt_a_tosgt, REG_NONE, OP_NONE }, + { "tosgeax", Opt_a_tosuge, REG_NONE, OP_NONE }, + { "tosgtax", Opt_a_tosugt, REG_NONE, OP_NONE }, { "tosicmp", Opt_a_tosicmp, REG_NONE, OP_NONE }, - { "tosleax", Opt_a_tosle, REG_NONE, OP_NONE }, - { "tosltax", Opt_a_toslt, REG_NONE, OP_NONE }, + { "tosleax", Opt_a_tosule, REG_NONE, OP_NONE }, + { "tosltax", Opt_a_tosult, REG_NONE, OP_NONE }, { "tosneax", Opt_a_tosne, REG_NONE, OP_NONE }, { "tosugeax", Opt_a_tosuge, REG_NONE, OP_NONE }, { "tosugtax", Opt_a_tosugt, REG_NONE, OP_NONE }, diff --git a/test/misc/Makefile b/test/misc/Makefile index ad31e8554..81a09c693 100644 --- a/test/misc/Makefile +++ b/test/misc/Makefile @@ -117,14 +117,6 @@ $(WORKDIR)/endless.$1.$2.prg: endless.c | $(WORKDIR) $(LD65) -t sim$2 -o $$@ $$(@:.prg=.o) sim$2.lib $(NULLERR) $(NOT) $(SIM65) $(SIM65FLAGS) $$@ $(NULLOUT) $(NULLERR) -# this one fails when optimization are enabled -$(WORKDIR)/bug1348.$1.$2.prg: bug1348.c | $(WORKDIR) - $(if $(QUIET),echo misc/bug1348.$1.$2.prg) - $(CC65) -Osr -t sim$2 -$1 -o $$(@:.prg=.s) $$< $(NULLERR) - $(CA65) -t sim$2 -o $$(@:.prg=.o) $$(@:.prg=.s) $(NULLERR) - $(LD65) -t sim$2 -o $$@ $$(@:.prg=.o) sim$2.lib $(NULLERR) - $(NOT) $(SIM65) $(SIM65FLAGS) $$@ $(NULLOUT) $(NULLERR) - # these need reference data that can't be generated by a host-compiled program, # in a useful way $(WORKDIR)/limits.$1.$2.prg: limits.c $(ISEQUAL) | $(WORKDIR) diff --git a/test/misc/bug1348.c b/test/val/bug1348.c similarity index 61% rename from test/misc/bug1348.c rename to test/val/bug1348.c index 913849482..c40d9ac84 100644 --- a/test/misc/bug1348.c +++ b/test/val/bug1348.c @@ -1,27 +1,26 @@ - -/* bug#1348, wrongly optimized integer promotion in comparison */ +/* bug #1348, wrongly optimized integer promotion in comparison */ #include -int notrandtab[] = { +static const int notrandtab[] = { 0xffff, 0x7fff, 0x3fff, 0x1fff, 0x0fff, 0x07ff, 0x03ff, 0x01ff, 0x00ff, 0x007f, 0x003f, 0x001f, 0x000f, 0x0007, 0x0003, 0x0001 }; -unsigned char notrandcount = 0; +static unsigned char notrandcount = 0; -int notrand(void) +static int notrand(void) { return notrandtab[notrandcount & 0x0f]; } -unsigned char n1, n2; -unsigned char i, ii, s; -unsigned char err = 0; +static unsigned char n1, n2; +static unsigned char i, ii, s; +static unsigned char err = 0; -unsigned char cmptab[] = { +static const unsigned char cmptab[] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01, 0x80, 0x40, 0x20, 0x10, @@ -40,13 +39,14 @@ int main(void) if ((notrand() & 0xffu) > s) { n2 = 1; } - printf("%5d>%3d %d(%02x) %d(%02x) %s\n", - notrandtab[notrandcount & 0x0f], s, + printf("%5d > %3d %u(%02x) %u(%02x) %s\n", + notrandtab[i], s, n1, (notrand() & 0xff), n2, (notrand() & 0xffu), - n1 == n2 ? "=" : "!=" - ); - if (n1 != n2) err = 1; + n1 == n2 ? "=" : "!="); + if (n1 != n2) { + err = 1; + } notrandcount++; } }