1
0
mirror of https://github.com/cc65/cc65.git synced 2025-01-14 16:33:00 +00:00

More shift optimizations.

git-svn-id: svn://svn.cc65.org/cc65/trunk@5770 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
uz 2012-07-07 19:24:17 +00:00
parent ae42e3b491
commit 49905d74bd
2 changed files with 66 additions and 23 deletions

View File

@ -1086,6 +1086,7 @@ static unsigned RunOptGroup3 (CodeSeg* S)
C += RunOptFunc (S, &DOptNegAX1, 1); C += RunOptFunc (S, &DOptNegAX1, 1);
C += RunOptFunc (S, &DOptNegAX2, 1); C += RunOptFunc (S, &DOptNegAX2, 1);
C += RunOptFunc (S, &DOptStackOps, 3); C += RunOptFunc (S, &DOptStackOps, 3);
C += RunOptFunc (S, &DOptShift1, 1);
C += RunOptFunc (S, &DOptShift4, 1); C += RunOptFunc (S, &DOptShift4, 1);
C += RunOptFunc (S, &DOptSub1, 1); C += RunOptFunc (S, &DOptSub1, 1);
C += RunOptFunc (S, &DOptSub2, 1); C += RunOptFunc (S, &DOptSub2, 1);

View File

@ -128,10 +128,10 @@ enum {
/* Macros to extract values from a shift type */ /* Macros to extract values from a shift type */
#define SHIFT_COUNT(S) ((S) & SHIFT_MASK_COUNT) #define SHIFT_COUNT(S) ((S) & SHIFT_MASK_COUNT)
#define SHIFT_DIR(S) ((S) & SHIFT_MASK_DIR) #define SHIFT_DIR(S) ((S) & SHIFT_MASK_DIR)
#define SHIFT_MODE(S) ((S) & SHIFT_MASK_MODE) #define SHIFT_MODE(S) ((S) & SHIFT_MASK_MODE)
#define SHIFT_TYPE(S) ((S) & SHIFT_MASK_TYPE) #define SHIFT_TYPE(S) ((S) & SHIFT_MASK_TYPE)
@ -208,7 +208,6 @@ unsigned OptShift1 (CodeSeg* S)
while (I < CS_GetEntryCount (S)) { while (I < CS_GetEntryCount (S)) {
unsigned Shift; unsigned Shift;
unsigned Count;
CodeEntry* N; CodeEntry* N;
CodeEntry* X; CodeEntry* X;
CodeLabel* L; CodeLabel* L;
@ -219,23 +218,53 @@ unsigned OptShift1 (CodeSeg* S)
/* Check for the sequence */ /* Check for the sequence */
if (E->OPC == OP65_JSR && if (E->OPC == OP65_JSR &&
(Shift = GetShift (E->Arg)) != SHIFT_NONE && (Shift = GetShift (E->Arg)) != SHIFT_NONE &&
SHIFT_DIR (Shift) == SHIFT_DIR_LEFT && SHIFT_DIR (Shift) == SHIFT_DIR_LEFT) {
(Count = SHIFT_COUNT (Shift)) > 0) {
unsigned Count = SHIFT_COUNT (Shift);
if (!RegXUsed (S, I+1)) { if (!RegXUsed (S, I+1)) {
/* Insert shift insns */ if (Count == SHIFT_COUNT_Y) {
while (Count--) {
CodeLabel* L;
if (S->CodeSizeFactor < 200) {
goto NextEntry;
}
/* Change into
*
* L1: asl a
* dey
* bpl L1
* ror a
*/
/* asl a */
X = NewCodeEntry (OP65_ASL, AM65_ACC, "a", 0, E->LI); X = NewCodeEntry (OP65_ASL, AM65_ACC, "a", 0, E->LI);
CS_InsertEntry (S, X, I+1); CS_InsertEntry (S, X, I+1);
L = CS_GenLabel (S, X);
/* dey */
X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, E->LI);
CS_InsertEntry (S, X, I+2);
/* bpl L1 */
X = NewCodeEntry (OP65_BPL, AM65_BRA, L->Name, L, E->LI);
CS_InsertEntry (S, X, I+3);
/* ror a */
X = NewCodeEntry (OP65_ROR, AM65_ACC, "a", 0, E->LI);
CS_InsertEntry (S, X, I+4);
} else {
/* Insert shift insns */
while (Count--) {
X = NewCodeEntry (OP65_ASL, AM65_ACC, "a", 0, E->LI);
CS_InsertEntry (S, X, I+1);
}
} }
/* Delete the call to shlax */
CS_DelEntry (S, I);
/* Remember, we had changes */
++Changes;
} else if (E->RI->In.RegX == 0 && } else if (E->RI->In.RegX == 0 &&
Count == 1 && Count == 1 &&
(N = CS_GetNextEntry (S, I)) != 0) { (N = CS_GetNextEntry (S, I)) != 0) {
@ -253,15 +282,21 @@ unsigned OptShift1 (CodeSeg* S)
X = NewCodeEntry (OP65_INX, AM65_IMP, 0, 0, E->LI); X = NewCodeEntry (OP65_INX, AM65_IMP, 0, 0, E->LI);
CS_InsertEntry (S, X, I+3); CS_InsertEntry (S, X, I+3);
/* Delete the call to shlax */ } else {
CS_DelEntry (S, I);
/* We won't handle this one */
goto NextEntry;
/* Remember, we had changes */
++Changes;
} }
/* Delete the call to shlax */
CS_DelEntry (S, I);
/* Remember, we had changes */
++Changes;
} }
NextEntry:
/* Next entry */ /* Next entry */
++I; ++I;
@ -438,19 +473,25 @@ unsigned OptShift4 (CodeSeg* S)
Count = SHIFT_COUNT (Shift); Count = SHIFT_COUNT (Shift);
if (Count == SHIFT_COUNT_Y) { if (Count == SHIFT_COUNT_Y) {
CodeLabel* L;
if (S->CodeSizeFactor < 200) {
/* Not acceptable */
goto NextEntry;
}
/* Generate: /* Generate:
* *
* L1: lsr a * L1: lsr a
* dey * dey
* bpl L1 * bpl L1
* rol a * rol a
* *
* A negative shift count or one that is greater or equal than * A negative shift count or one that is greater or equal than
* the bit width of the left operand (which is promoted to * the bit width of the left operand (which is promoted to
* integer before the operation) causes undefined behaviour, so * integer before the operation) causes undefined behaviour, so
* above transformation is safe. * above transformation is safe.
*/ */
CodeLabel* L;
/* lsr a */ /* lsr a */
X = NewCodeEntry (OP65_LSR, AM65_ACC, "a", 0, E->LI); X = NewCodeEntry (OP65_LSR, AM65_ACC, "a", 0, E->LI);
@ -486,6 +527,7 @@ unsigned OptShift4 (CodeSeg* S)
} }
NextEntry:
/* Next entry */ /* Next entry */
++I; ++I;