mirror of
https://github.com/cc65/cc65.git
synced 2025-02-05 20:31:53 +00:00
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:
parent
e5bbdfa995
commit
79c52e742f
@ -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);
|
||||
|
@ -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 */
|
||||
/*****************************************************************************/
|
||||
|
@ -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 */
|
||||
/*****************************************************************************/
|
||||
|
Loading…
x
Reference in New Issue
Block a user