Added new opts OptBoolUnary1/OptBoolUnary2 to remove unnecessary cmp + bcastax/bnegax,

as well as OptBoolUnary3 to "strength-reduce" certain bcastax/bnegax to boolne/booleq.
This commit is contained in:
acqn 2023-10-21 23:56:04 +08:00
parent e5bbdfa995
commit 79c52e742f
3 changed files with 263 additions and 2 deletions

View File

@ -118,6 +118,9 @@ static OptFunc DOptBNegAX3 = { OptBNegAX3, "OptBNegAX3", 100, 0,
static OptFunc DOptBNegAX4 = { OptBNegAX4, "OptBNegAX4", 100, 0, 0, 0, 0, 0 };
static OptFunc DOptBoolCmp = { OptBoolCmp, "OptBoolCmp", 100, 0, 0, 0, 0, 0 };
static OptFunc DOptBoolTrans = { OptBoolTrans, "OptBoolTrans", 100, 0, 0, 0, 0, 0 };
static OptFunc DOptBoolUnary1 = { OptBoolUnary1, "OptBoolUnary1", 40, 0, 0, 0, 0, 0 };
static OptFunc DOptBoolUnary2 = { OptBoolUnary2, "OptBoolUnary2", 40, 0, 0, 0, 0, 0 };
static OptFunc DOptBoolUnary3 = { OptBoolUnary3, "OptBoolUnary3", 40, 0, 0, 0, 0, 0 };
static OptFunc DOptBranchDist = { OptBranchDist, "OptBranchDist", 0, 0, 0, 0, 0, 0 };
static OptFunc DOptBranchDist2 = { OptBranchDist2, "OptBranchDist2", 0, 0, 0, 0, 0, 0 };
static OptFunc DOptCmp1 = { OptCmp1, "OptCmp1", 42, 0, 0, 0, 0, 0 };
@ -224,6 +227,9 @@ static OptFunc* OptFuncs[] = {
&DOptBNegAX4,
&DOptBoolCmp,
&DOptBoolTrans,
&DOptBoolUnary1,
&DOptBoolUnary2,
&DOptBoolUnary3,
&DOptBranchDist,
&DOptBranchDist2,
&DOptCmp1,
@ -613,7 +619,6 @@ static unsigned RunOptGroup1 (CodeSeg* S)
Changes += RunOptFunc (S, &DOptPtrLoad15, 1);
Changes += RunOptFunc (S, &DOptPtrLoad16, 1);
Changes += RunOptFunc (S, &DOptPtrLoad17, 1);
Changes += RunOptFunc (S, &DOptBNegAX1, 1);
Changes += RunOptFunc (S, &DOptBNegAX2, 1);
Changes += RunOptFunc (S, &DOptBNegAX3, 1);
Changes += RunOptFunc (S, &DOptBNegAX4, 1);
@ -673,7 +678,12 @@ static unsigned RunOptGroup3 (CodeSeg* S)
C += RunOptFunc (S, &DOptBNegA2, 1);
C += RunOptFunc (S, &DOptNegAX1, 1);
C += RunOptFunc (S, &DOptNegAX2, 1);
C += RunOptFunc (S, &DOptStackOps, 3);
C += RunOptFunc (S, &DOptStackOps, 3); /* Before OptBoolUnary1 */
C += RunOptFunc (S, &DOptCmp8, 1); /* Before OptBoolUnary1 */
C += RunOptFunc (S, &DOptBoolUnary1, 3);
C += RunOptFunc (S, &DOptBoolUnary2, 3);
C += RunOptFunc (S, &DOptBoolUnary3, 1);
C += RunOptFunc (S, &DOptBNegAX1, 1); /* After OptBoolUnary2 */
C += RunOptFunc (S, &DOptShift1, 1);
C += RunOptFunc (S, &DOptShift4, 1);
C += RunOptFunc (S, &DOptComplAX1, 1);

View File

@ -290,6 +290,227 @@ unsigned OptBoolTrans (CodeSeg* S)
/*****************************************************************************/
/* Remove calls to the boolean cast/negation subroutines */
/*****************************************************************************/
unsigned OptBoolUnary1 (CodeSeg* S)
/* Search for and remove cmp #0/bcastax/boolne following a bcastax/bnegax.
** Or search for and remove cmp #1/bnegax/booleq following a bcastax/bnegax
** and invert the bcastax/bnegax.
*/
{
unsigned Changes = 0;
int Neg = 0;
/* Walk over the entries */
unsigned I = 0;
while (I < CS_GetEntryCount (S)) {
CodeEntry* L[2];
/* Get next entry */
L[0] = CS_GetEntry (S, I);
/* Check for the sequence.
** We allow the first entry to have labels.
*/
if (L[0]->OPC == OP65_JSR &&
(L[1] = CS_GetNextEntry (S, I)) != 0 &&
!CE_HasLabel (L[1])) {
if (strcmp (L[0]->Arg, "bnegax") == 0) {
Neg = 1;
} else if (strcmp (L[0]->Arg, "bcastax") == 0) {
Neg = 0;
} else {
/* Next entry */
++I;
continue;
}
if ((L[1]->OPC == OP65_CMP && CE_IsKnownImm (L[1], 0x0)) ||
CE_IsCallTo (L[1], "boolne") ||
CE_IsCallTo (L[1], "bcastax")) {
/* Delete the entry no longer needed. */
CS_DelEntry (S, I + 1);
/* Remember, we had changes */
++Changes;
/* We are still at this index */
continue;
} else if ((L[1]->OPC == OP65_CMP && CE_IsKnownImm (L[1], 0x1)) ||
CE_IsCallTo (L[1], "booleq") ||
CE_IsCallTo (L[1], "bnegax")) {
/* Invert the previous bool conversion */
CE_SetArg (L[0], Neg ? "bcastax" : "bnegax");
/* Delete the entry no longer needed */
CS_DelEntry (S, I + 1);
/* Remember, we had changes */
++Changes;
/* We are still at this index */
continue;
}
}
/* Next entry */
++I;
}
/* Return the number of changes made */
return Changes;
}
unsigned OptBoolUnary2 (CodeSeg* S)
/* Search for and remove cmp #0/bcastax/boolne following a boolean transformer.
** Or search for and remove cmp #1/bnegax/booleq following a boolean transformer
** and invert the boolean transformer.
*/
{
unsigned Changes = 0;
cmp_t Cond;
char Buf[16];
/* Walk over the entries */
unsigned I = 0;
while (I < CS_GetEntryCount (S)) {
CodeEntry* L[2];
/* Get next entry */
L[0] = CS_GetEntry (S, I);
/* Check for the sequence.
** We allow the first entry to have labels.
*/
if (L[0]->OPC == OP65_JSR &&
(L[1] = CS_GetNextEntry (S, I)) != 0 &&
!CE_HasLabel (L[1]) &&
(Cond = FindBoolCmpCond (L[0]->Arg)) != CMP_INV) {
if ((L[1]->OPC == OP65_CMP && CE_IsKnownImm (L[1], 0x0)) ||
CE_IsCallTo (L[1], "boolne") ||
CE_IsCallTo (L[1], "bcastax")) {
/* Delete the entry no longer needed */
CS_DelEntry (S, I + 1);
/* Remember, we had changes */
++Changes;
/* We are still at this index */
continue;
} else if ((L[1]->OPC == OP65_CMP && CE_IsKnownImm (L[1], 0x1)) ||
CE_IsCallTo (L[1], "booleq") ||
CE_IsCallTo (L[1], "bnegax")) {
/* Invert the bool conversion */
if (GetBoolCmpSuffix (Buf, GetNegatedCond (Cond)) == 0) {
Internal ("No inverted boolean transformer for: %s", L[0]->Arg);
}
CE_SetArg (L[0], Buf);
/* Delete the entry no longer needed */
CS_DelEntry (S, I + 1);
/* Remember, we had changes */
++Changes;
/* We are still at this index */
continue;
}
}
/* Next entry */
++I;
}
/* Return the number of changes made */
return Changes;
}
unsigned OptBoolUnary3 (CodeSeg* S)
/* If A == 0, replace bcastax/bnegax with
**
** cpx #0
** jsr boolne/booleq
**
** Or if X == 0, replace bcastax/bnegax with
**
** cmp #0
** jsr boolne/booleq
**
*/
{
unsigned Changes = 0;
opc_t Op = OP65_COUNT;
const char* Sub = 0;
/* Walk over the entries */
unsigned I = 0;
while (I < CS_GetEntryCount (S)) {
CodeEntry* E;
CodeEntry* X;
/* Get next entry */
E = CS_GetEntry (S, I);
/* Check for the sequence */
if (!CE_HasLabel (E)) {
/* Choose the right subroutine */
if (CE_IsCallTo (E, "bnegax")) {
Sub = "booleq";
} else if (CE_IsCallTo (E, "bcastax")) {
Sub = "boolne";
}
/* Choose the right opcode */
if (RegValIsKnown (E->RI->In.RegA) && E->RI->In.RegA == 0) {
Op = OP65_CPX;
} else if (RegValIsKnown (E->RI->In.RegX) && E->RI->In.RegX == 0) {
Op = OP65_CMP;
}
/* Replace the sequence if all requirements are met*/
if (Op != OP65_COUNT && Sub != 0) {
/* Replace bcastax/bnegax with boolne/booleq */
CE_SetArg (E, Sub);
/* Insert the compare */
X = NewCodeEntry (Op, AM65_IMM, "$00", 0, E->LI);
CS_InsertEntry (S, X, I);
/* Remember, we had changes */
++Changes;
/* Correct the index */
++I;
}
/* Reset the choices */
Op = OP65_COUNT;
Sub = 0;
}
/* Next entry */
++I;
}
/* Return the number of changes made */
return Changes;
}
/*****************************************************************************/
/* bnega optimizations */
/*****************************************************************************/

View File

@ -63,6 +63,36 @@ unsigned OptBoolTrans (CodeSeg* S);
/*****************************************************************************/
/* Remove calls to the boolean cast/negation subroutines */
/*****************************************************************************/
unsigned OptBoolUnary1 (CodeSeg* S);
/* Search for and remove bcastax adjacent to bnegax */
unsigned OptBoolUnary2 (CodeSeg* S);
/* Search for and remove bcastax/bnegax following a boolean transformer.
** Invert the boolean transformer if it is bnegax to be removed.
*/
unsigned OptBoolUnary3 (CodeSeg* S);
/* Replace bcastax/bnegax with
**
** cpx #0
** jsr boolne/booleq
**
** if A == 0, or replace bcastax/bnegax with
**
** cmp #0
** jsr boolne/booleq
**
** if X == 0.
*/
/*****************************************************************************/
/* bnega optimizations */
/*****************************************************************************/