9. With asm optimised strings 17030 192 2223
10 and below are with asm strings off.
-
+
+ 10 Mucho optimisations 13562 201 1FCC
+
Apparent advantage of turning on regparams:
1. Cost of push
Decent case is push of a constant
"AOP_PAIRPT"
};
+static bool
+isLastUse (iCode *ic, operand *op)
+{
+ bitVect *uses = bitVectCopy (OP_USES (op));
+
+ while (!bitVectIsZero (uses))
+ {
+ if (bitVectFirstBit (uses) == ic->key)
+ {
+ if (bitVectnBitsOn (uses) == 1)
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+ bitVectUnSetBit (uses, bitVectFirstBit (uses));
+ }
+
+ return FALSE;
+}
+
static PAIR_ID
_getTempPairId(void)
{
return _pairs[_getTempPairId()].name;
}
+static bool
+isPairInUse (PAIR_ID id, iCode *ic)
+{
+ if (id == PAIR_DE)
+ {
+ return bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX);
+ }
+ else if (id == PAIR_BC)
+ {
+ return bitVectBitValue (ic->rMask, B_IDX) || bitVectBitValue(ic->rMask, C_IDX);
+ }
+ else
+ {
+ wassertl (0, "Only implemented for DE and BC");
+ return TRUE;
+ }
+}
+
+static bool
+isPairInUseNotInRet(PAIR_ID id, iCode *ic)
+{
+ bitVect *rInUse;
+
+ rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
+
+ if (id == PAIR_DE)
+ {
+ return bitVectBitValue (rInUse, D_IDX) || bitVectBitValue(rInUse, E_IDX);
+ }
+ else
+ {
+ wassertl (0, "Only implemented for DE");
+ return TRUE;
+ }
+}
+
static PAIR_ID
getFreePairId (iCode *ic)
{
- if (!(bitVectBitValue (ic->rMask, B_IDX) || bitVectBitValue(ic->rMask, C_IDX)))
+ if (!isPairInUse (PAIR_BC, ic))
{
return PAIR_BC;
}
- else if (IS_Z80 && !(bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX)))
+ else if (IS_Z80 && !isPairInUse (PAIR_DE, ic))
{
return PAIR_DE;
}
emit2 ("ld %s,!hashedstr", pair, l);
}
+static PAIR_ID
+makeFreePairId (iCode *ic, bool *pisUsed)
+{
+ *pisUsed = FALSE;
+
+ if (ic != NULL)
+ {
+ if (!bitVectBitValue (ic->rMask, B_IDX) && !bitVectBitValue(ic->rMask, C_IDX))
+ {
+ return PAIR_BC;
+ }
+ else if (IS_Z80 && !bitVectBitValue (ic->rMask, D_IDX) && !bitVectBitValue(ic->rMask, E_IDX))
+ {
+ return PAIR_DE;
+ }
+ else
+ {
+ *pisUsed = TRUE;
+ return PAIR_HL;
+ }
+ }
+ else
+ {
+ *pisUsed = TRUE;
+ return PAIR_HL;
+ }
+}
+
static void
-fetchPairLong (PAIR_ID pairId, asmop * aop, int offset)
+fetchPairLong (PAIR_ID pairId, asmop * aop, iCode *ic, int offset)
{
/* if this is remateriazable */
if (isLitWord (aop)) {
}
else
{
- _push (PAIR_HL);
+ bool isUsed;
+ PAIR_ID id = makeFreePairId (ic, &isUsed);
+ if (isUsed)
+ _push (id);
/* Can't load into parts, so load into HL then exchange. */
- emit2 ("ld %s,%s", _pairs[PAIR_HL].l, aopGet (aop, offset, FALSE));
- emit2 ("ld %s,%s", _pairs[PAIR_HL].h, aopGet (aop, offset + 1, FALSE));
- emit2 ("push hl");
+ emit2 ("ld %s,%s", _pairs[id].l, aopGet (aop, offset, FALSE));
+ emit2 ("ld %s,%s", _pairs[id].h, aopGet (aop, offset + 1, FALSE));
+ emit2 ("push %s", _pairs[id].name);
emit2 ("pop iy");
- _pop (PAIR_HL);
+ if (isUsed)
+ _pop (id);
}
}
- else {
+ else
+ {
emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
emit2 ("ld %s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
- }
+ }
/* PENDING: check? */
if (pairId == PAIR_HL)
spillPair (PAIR_HL);
static void
fetchPair (PAIR_ID pairId, asmop * aop)
{
- fetchPairLong (pairId, aop, 0);
+ fetchPairLong (pairId, aop, NULL, 0);
}
static void
aopPut ( AOP (IC_RESULT (ic)), "a", MSB16);
aopPut ( AOP (IC_RESULT (ic)), "e", LSB);
- fetchPairLong (PAIR_DE, left, MSB24);
+ fetchPairLong (PAIR_DE, left, NULL, MSB24);
aopGet (right, MSB24, FALSE);
_pop (PAIR_AF);
}
if (size == 4)
{
- fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
+ fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 2);
emit2 ("push hl");
spillPair (PAIR_HL);
_G.stack.pushed += 2;
- fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 0);
+ fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 0);
emit2 ("push hl");
spillPair (PAIR_HL);
_G.stack.pushed += 2;
if (IS_GB && size == 4 && requiresHL (AOP (IC_LEFT (ic))))
{
fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
- fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
+ fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 2);
}
else
{
// wassertl (val > 0, "Multiply must be positive");
wassertl (val != 1, "Can't multiply by 1");
- if (IS_Z80) {
+ if (IS_Z80 && isPairInUseNotInRet (PAIR_DE, ic)) {
_push (PAIR_DE);
+ _G.stack.pushedDE = TRUE;
}
if ( AOP_SIZE (IC_LEFT (ic)) == 1 && !SPEC_USIGN (getSpec (operandType ( IC_LEFT (ic)))))
spillCached();
- if (IS_Z80)
+ if (IS_Z80 && _G.stack.pushedDE)
{
_pop (PAIR_DE);
+ _G.stack.pushedDE = FALSE;
}
commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
movLeft2Result (left, offl, result, offr, 0);
movLeft2Result (left, offl + 1, result, offr + 1, 0);
}
- /* PENDING: for now just see if it'll work. */
- /*if (AOP(result)->type == AOP_REG) { */
- {
+
+ if (shCount == 1 && getPairId (AOP (result)) == PAIR_HL)
+ {
+ emit2 ("add hl,hl");
+ }
+ else
+ {
int size = 2;
int offset = 0;
symbol *tlbl, *tlbl1;
goto release;
}
- if ( getPairId( AOP (left)) == PAIR_IY)
+ if (getPairId (AOP (left)) == PAIR_IY)
{
/* Just do it */
offset = 0;
/* if this is remateriazable */
fetchPair (pair, AOP (left));
- freeAsmop (left, NULL, ic);
-
/* if bit then unpack */
if (IS_BITVAR (retype))
{
wassert (0);
}
- else if ( getPairId( AOP (result)) == PAIR_HL)
+ else if (getPairId (AOP (result)) == PAIR_HL)
{
wassertl (size == 2, "HL must be of size 2");
emit2 ("ld a,!*hl");
emit2 ("ld h,!*hl");
emit2 ("ld l,a");
}
+ else if (getPairId (AOP (left)) == PAIR_HL && !isLastUse (ic, left))
+ {
+ size = AOP_SIZE (result);
+ offset = 0;
+
+ while (size--)
+ {
+ /* PENDING: make this better */
+ if (!IS_GB && AOP_TYPE (result) == AOP_REG)
+ {
+ aopPut (AOP (result), "!*hl", offset++);
+ }
+ else
+ {
+ emit2 ("ld a,!*pair", _pairs[pair].name);
+ aopPut (AOP (result), "a", offset++);
+ }
+ if (size)
+ {
+ emit2 ("inc %s", _pairs[pair].name);
+ _G.pairs[pair].offset++;
+ }
+ }
+ /* Fixup HL back down */
+ for (size = AOP_SIZE (result)-1; size; size--)
+ {
+ emit2 ("dec %s", _pairs[pair].name);
+ }
+ }
else
{
size = AOP_SIZE (result);
while (size--)
{
/* PENDING: make this better */
- if (!IS_GB && AOP (result)->type == AOP_REG)
+ if (!IS_GB &&
+ (AOP_TYPE (result) == AOP_REG || AOP_TYPE (result) == AOP_HLREG))
{
aopPut (AOP (result), "!*hl", offset++);
}
}
}
+ freeAsmop (left, NULL, ic);
+
release:
freeAsmop (result, NULL, ic);
}
}
goto release;
}
+ else if (getPairId (AOP (result)) == PAIR_HL && !isLastUse (ic, result))
+ {
+ offset = 0;
+
+ while (size--)
+ {
+ const char *l = aopGet (AOP (right), offset, FALSE);
+ if (isRegOrLit (AOP (right)) && !IS_GB)
+ {
+ emit2 ("ld !*pair,%s", _pairs[PAIR_HL].name, l);
+ }
+ else
+ {
+ _moveA (l);
+ emit2 ("ld !*pair,a", _pairs[PAIR_HL].name);
+ }
+ if (size)
+ {
+ emit2 ("inc %s", _pairs[PAIR_HL].name);
+ _G.pairs[PAIR_HL].offset++;
+ }
+ offset++;
+ }
+
+ /* Fixup HL back down */
+ for (size = AOP_SIZE (right)-1; size; size--)
+ {
+ emit2 ("dec %s", _pairs[PAIR_HL].name);
+ }
+ goto release;
+ }
/* if the operand is already in dptr
then we do nothing else we move the value to dptr */
if (AOP_TYPE (right) == AOP_LIT)
{
- lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+ lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
}
if (isPair (AOP (result)))
{
- fetchPair (getPairId (AOP (result)), AOP (right));
+ fetchPairLong (getPairId (AOP (result)), AOP (right), ic, LSB);
}
else if ((size > 1) &&
(AOP_TYPE (result) != AOP_REG) &&
DISABLE_PACK_ASSIGN = 0,
DISABLE_PACK_ONE_USE = 0,
DISABLE_PACK_HL = 0,
+ DISABLE_PACK_IY = 0
};
/* Flags to turn on debugging code.
D_HLUSE = 0,
D_HLUSE2 = 0,
D_HLUSE2_VERBOSE = 0,
- D_FILL_GAPS = 0
+ D_FILL_GAPS = 0,
+ D_PACK_IY = 0,
+ D_PACK_HLUSE3 = 0
};
#if 1
iCode *ic, *dic;
bool isFirst = TRUE;
-#if 0
- printf("Checking:\n");
- piCode(lic, NULL);
-#endif
+ D (D_PACK_HLUSE3, ("Checking HL on %p lic key %u first def %u line %u:\n", OP_SYMBOL(op), lic->key, bitVectFirstBit(OP_DEFS(op)), lic->lineno));
+ if (D_PACK_HLUSE3)
+ piCode(lic, NULL);
if ( OP_SYMBOL(op)->accuse)
{
dic = ic = hTabFirstItemWK(iCodeSeqhTab,OP_SYMBOL(op)->liveFrom);
for (; ic && ic->seq <= OP_SYMBOL(op)->liveTo;
- ic = hTabNextItem(iCodeSeqhTab,&key))
+ ic = hTabNextItem(iCodeSeqhTab, &key))
{
-#if 0
- piCode(ic, NULL);
- printf("(op: %u)\n", ic->op);
-#endif
+ if (D_PACK_HLUSE3)
+ piCode(ic, NULL);
+ D (D_PACK_HLUSE3, ("(On %p: op: %u next: %p)\n", ic, ic->op, ic->next));
+
if (isFirst)
{
isFirst = FALSE;
continue;
if (POINTER_GET (ic))
continue;
+ if (ic->op == '=' && !POINTER_SET(ic))
+ continue;
}
if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic))
if (ic->op == CALL && isOperandEqual (op, IC_RESULT (ic)))
continue;
+ if (ic->op == LEFT_OP && isOperandLiteral (IC_RIGHT (ic)))
+ continue;
+
if ((ic->op == '=' && !POINTER_SET(ic)) ||
ic->op == UNARYMINUS ||
ic->op == '+' ||
ic->op == '-' ||
+ ic->op == '>' ||
+ ic->op == '<' ||
+ ic->op == EQ_OP ||
0)
continue;
+ if (ic->op == '*' && isOperandEqual (op, IC_LEFT (ic)))
+ continue;
+
+ if (POINTER_SET (ic) && isOperandEqual (op, IC_RESULT (ic)))
+ continue;
+
if (POINTER_GET (ic) && isOperandEqual (op, IC_LEFT (ic)))
continue;
return NULL;
}
-#if 0
- printf("Succeeded!\n");
-#endif
- OP_SYMBOL (op)->accuse = ACCUSE_SCRATCH;
+ D (D_PACK_HLUSE3, ("Succeeded!\n"))
+ OP_SYMBOL (op)->accuse = ACCUSE_SCRATCH;
return dic;
}
iCode *ic, *dic;
bitVect *uses;
-#if 0
- printf("Checking IY on %p lic key %u first def %u:\n", OP_SYMBOL(op), lic->key, bitVectFirstBit(OP_DEFS(op)));
- piCode(lic, NULL);
-#endif
+ D (D_PACK_IY, ("Checking IY on %p lic key %u first def %u line %u:\n", OP_SYMBOL(op), lic->key, bitVectFirstBit(OP_DEFS(op)), lic->lineno));
+ if (D_PACK_IY)
+ piCode(lic, NULL);
if ( OP_SYMBOL(op)->accuse)
{
for (; ic && ic->seq <= OP_SYMBOL(op)->liveTo;
ic = hTabNextItem(iCodeSeqhTab,&key))
{
-#if 0
- piCode(ic, NULL);
- printf("(op: %u uses %u)\n", ic->op, bitVectBitValue(uses, ic->key));
-#endif
+ if (D_PACK_IY)
+ piCode(ic, NULL);
if (ic->op == PCALL ||
ic->op == CALL ||
if (SKIP_IC2(ic))
continue;
+ /* Be pessamistic. */
+ if (ic->op == IFX)
+ return NULL;
+
+ D (D_PACK_IY, (" op: %u uses %u result: %d left: %d right: %d\n", ic->op, bitVectBitValue(uses, ic->key),
+ IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) ? isOperandInDirSpace(IC_RESULT(ic)) : -1,
+ IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) ? isOperandInDirSpace(IC_LEFT(ic)) : -1,
+ IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) ? isOperandInDirSpace(IC_RIGHT(ic)) : -1
+ ));
+
+ if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) &&
+ isOperandInDirSpace(IC_RESULT(ic)))
+ return NULL;
+
+ if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) &&
+ isOperandInDirSpace(IC_RIGHT(ic)))
+ return NULL;
+
+ if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) &&
+ isOperandInDirSpace(IC_LEFT(ic)))
+ return NULL;
+
/* Only certain rules will work against IY. Check if this iCode uses
this symbol. */
if (bitVectBitValue(uses, ic->key) != 0)
{
- if (ic->op == IFX)
- return NULL;
-
if (ic->op == '=' &&
isOperandEqual(IC_RESULT(ic), op))
continue;
}
else
{
- if (ic->op == IFX)
- continue;
-
/* This iCode doesn't use the sym. See if this iCode preserves IY.
*/
- if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) &&
- isOperandInDirSpace(IC_RESULT(ic)))
- return NULL;
-
- if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) &&
- isOperandInFarSpace(IC_RIGHT(ic)))
- return NULL;
-
- if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) &&
- isOperandInFarSpace(IC_LEFT(ic)))
- return NULL;
-
continue;
}
return NULL;
}
-#if 0
- printf("Succeeded IY!\n");
-#endif
- OP_SYMBOL (op)->accuse = ACCUSE_IY;
+ D (D_PACK_IY, ("Succeeded IY!\n"));
+ OP_SYMBOL (op)->accuse = ACCUSE_IY;
return dic;
}
iCode *uic;
D (D_ACCUSE2, ("packRegsForAccUse2: running on ic %p line %u\n", ic, ic->lineno));
+ if (D_ACCUSE2)
+ piCode (ic, NULL);
/* Filter out all but those 'good' commands */
if (
!POINTER_GET (ic) &&
ic->op != '+' &&
+ ic->op != '-' &&
!IS_BITWISE_OP (ic) &&
ic->op != '=' &&
ic->op != EQ_OP &&
packRegsForHLUse3 (ic, IC_RESULT (ic), ebp);
}
- if (!DISABLE_PACK_HL && IS_ITEMP (IC_RESULT (ic)) && IS_Z80)
+ if (!DISABLE_PACK_IY && IS_ITEMP (IC_RESULT (ic)) && IS_Z80)
{
packRegsForIYUse (ic, IC_RESULT (ic), ebp);
}