From 3c3375d0477d692290f05334d4cb858ee1205369 Mon Sep 17 00:00:00 2001 From: michaelh Date: Thu, 6 Dec 2001 03:07:04 +0000 Subject: [PATCH] * src/diff.1 (Index): Many, many optmisiations. Dhrystone up to 201. git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@1663 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- ChangeLog | 10 ++ doc/choices.txt | 23 ++++- src/z80/gen.c | 218 ++++++++++++++++++++++++++++++++++++------ src/z80/peeph-z80.def | 12 +++ src/z80/peeph.def | 11 ++- src/z80/ralloc.c | 106 +++++++++++--------- 6 files changed, 305 insertions(+), 75 deletions(-) diff --git a/ChangeLog b/ChangeLog index 45902791..164cf777 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2001-12-05 Michael Hope + + * src/diff.1 (Index): Many, many optmisiations. Dhrystone up to 201. + +1904-01-06 Michael Hope + + * src/z80/ralloc.c (packRegsForIYUse): Fixed the case where an operand is in direct space. + + * src/z80/gen.c (makeFreePairId): Optimised IY load by using a spare pair. + 2001-12-02 Bernhard Held * src/mcs51/gen.c (genFunction): avoid excess "inc sp" diff --git a/doc/choices.txt b/doc/choices.txt index d6fbe90c..1442eca4 100644 --- a/doc/choices.txt +++ b/doc/choices.txt @@ -218,4 +218,25 @@ Cleaning up the arguments to a call: pop af ; 5/byte -So for 8 bytes and above use the first form. \ No newline at end of file +So for 8 bytes and above use the first form. + +Pointer assign: + ld hl,bc ; 4+4 + ld e,(hl) ; 7 + inc hl ; 6 + ld d,(hl) ; 7 + +vs: + ld a,(bc) ; 7 + ld e,a ; 4 + inc bc ; 6 + ld a,(bc) ; 7 + ld d,a ; 4 + +Same cost. Not worth it, although is does free up HL. + +Shift left signed on HL + sla l + rl h ; 8+8 = 16 + + add hl,hl ; 11 diff --git a/src/z80/gen.c b/src/z80/gen.c index 76345de7..1ac58abf 100644 --- a/src/z80/gen.c +++ b/src/z80/gen.c @@ -60,7 +60,9 @@ 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 @@ -252,6 +254,30 @@ static const char *aopNames[] = { "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) { @@ -271,14 +297,50 @@ _getTempPairName(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; } @@ -1175,8 +1237,36 @@ fetchLitPair (PAIR_ID pairId, asmop * left, int offset) 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)) { @@ -1228,19 +1318,24 @@ fetchPairLong (PAIR_ID pairId, asmop * aop, int offset) } 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); @@ -1250,7 +1345,7 @@ fetchPairLong (PAIR_ID pairId, asmop * aop, int offset) static void fetchPair (PAIR_ID pairId, asmop * aop) { - fetchPairLong (pairId, aop, 0); + fetchPairLong (pairId, aop, NULL, 0); } static void @@ -2044,7 +2139,7 @@ _gbz80_emitAddSubLongLong (iCode *ic, asmop *left, asmop *right, bool isAdd) 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); @@ -2333,11 +2428,11 @@ genIpush (iCode * ic) } 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; @@ -2952,7 +3047,7 @@ genRet (iCode * ic) 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 { @@ -3690,8 +3785,9 @@ genMult (iCode * ic) // 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))))) @@ -3735,9 +3831,10 @@ genMult (iCode * 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); @@ -5273,9 +5370,13 @@ shiftL2Left2Result (operand * left, int offl, 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; @@ -5897,7 +5998,7 @@ genGenPointerGet (operand * left, goto release; } - if ( getPairId( AOP (left)) == PAIR_IY) + if (getPairId (AOP (left)) == PAIR_IY) { /* Just do it */ offset = 0; @@ -5917,14 +6018,12 @@ genGenPointerGet (operand * left, /* 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"); @@ -5932,6 +6031,35 @@ genGenPointerGet (operand * left, 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); @@ -5940,7 +6068,8 @@ genGenPointerGet (operand * left, 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++); } @@ -5957,6 +6086,8 @@ genGenPointerGet (operand * left, } } + freeAsmop (left, NULL, ic); + release: freeAsmop (result, NULL, ic); } @@ -6047,6 +6178,37 @@ genGenPointerSet (operand * right, } 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 */ @@ -6242,12 +6404,12 @@ genAssign (iCode * ic) 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) && diff --git a/src/z80/peeph-z80.def b/src/z80/peeph-z80.def index 2bba1260..63c89a44 100644 --- a/src/z80/peeph-z80.def +++ b/src/z80/peeph-z80.def @@ -31,3 +31,15 @@ replace { rlca and a,#0x01 } +replace { + ld %3,a + ld l,%1) + ld h,%2) + ld l,(hl) + ld a,%3 +} by { + ld %3,a + ld l,%1) + ld h,%2) + ld l,(hl) +} diff --git a/src/z80/peeph.def b/src/z80/peeph.def index d865c3a9..ee359787 100644 --- a/src/z80/peeph.def +++ b/src/z80/peeph.def @@ -3,7 +3,7 @@ replace { } by { ERROR - peephole - caught (hl),(hl) } -replace { +replace restart { ld %1,%1 } by { ; Removed redundent load @@ -192,3 +192,12 @@ replace { cp a,#%4 jp p,%5 } +replace { + ld e,l + ld d,h + ld l,e + ld h,d +} by { + ld e,l + ld d,h +} diff --git a/src/z80/ralloc.c b/src/z80/ralloc.c index e8d338fa..9d58ded2 100644 --- a/src/z80/ralloc.c +++ b/src/z80/ralloc.c @@ -54,6 +54,7 @@ enum DISABLE_PACK_ASSIGN = 0, DISABLE_PACK_ONE_USE = 0, DISABLE_PACK_HL = 0, + DISABLE_PACK_IY = 0 }; /* Flags to turn on debugging code. @@ -67,7 +68,9 @@ enum 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 @@ -2232,10 +2235,9 @@ packRegsForHLUse3 (iCode * lic, operand * op, eBBlock * ebp) 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) { @@ -2282,12 +2284,12 @@ packRegsForHLUse3 (iCode * lic, operand * op, eBBlock * ebp) 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; @@ -2295,6 +2297,8 @@ packRegsForHLUse3 (iCode * lic, operand * op, eBBlock * ebp) continue; if (POINTER_GET (ic)) continue; + if (ic->op == '=' && !POINTER_SET(ic)) + continue; } if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) @@ -2330,13 +2334,25 @@ packRegsForHLUse3 (iCode * lic, operand * op, eBBlock * ebp) 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; @@ -2351,11 +2367,9 @@ packRegsForHLUse3 (iCode * lic, operand * op, eBBlock * ebp) 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; } @@ -2367,10 +2381,9 @@ packRegsForIYUse (iCode * lic, operand * op, eBBlock * ebp) 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) { @@ -2423,10 +2436,8 @@ packRegsForIYUse (iCode * lic, operand * op, eBBlock * ebp) 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 || @@ -2437,13 +2448,32 @@ packRegsForIYUse (iCode * lic, operand * op, eBBlock * ebp) 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; @@ -2470,23 +2500,8 @@ packRegsForIYUse (iCode * lic, operand * op, eBBlock * ebp) } 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; } @@ -2494,11 +2509,9 @@ packRegsForIYUse (iCode * lic, operand * op, eBBlock * ebp) 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; } @@ -2647,11 +2660,14 @@ packRegsForAccUse2 (iCode * ic) 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 && @@ -2902,7 +2918,7 @@ packRegisters (eBBlock * ebp) 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); } -- 2.30.2