From: michaelh Date: Sun, 13 Feb 2000 01:12:59 +0000 (+0000) Subject: * Now can use acc for short lived varibles. X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=b5a26cf0f6e3783a04a4b4250d84086ab220ba5c;p=fw%2Fsdcc * Now can use acc for short lived varibles. * Added a few peephole rules * At 98 d/s - so close to 100... :) git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@103 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- diff --git a/device/lib/z80/Makefile b/device/lib/z80/Makefile index 0ecb909e..e70eee38 100644 --- a/device/lib/z80/Makefile +++ b/device/lib/z80/Makefile @@ -5,7 +5,7 @@ TOPDIR = ../../.. SCC = $(TOPDIR)/bin/sdcc -mz80 -v SAS = as-z80 -OBJ = div.o mul.o putchar.o string.o printf.o asm_strings.o +OBJ = div.o mul.o putchar.o string.o printf.o # asm_strings.o LIB = z80.lib CC = $(SCC) AS = $(SAS) diff --git a/device/lib/z80/string.c b/device/lib/z80/string.c index 0ba6f753..53ee9b2c 100644 --- a/device/lib/z80/string.c +++ b/device/lib/z80/string.c @@ -1,7 +1,7 @@ /* Dumb strings stub. Wanted a quick hack for now - will use the libc version later. */ -char *_strcpy(char *dest, const char *source) +char *strcpy(char *dest, const char *source) { char *d = dest; const char *s = source; @@ -9,7 +9,7 @@ char *_strcpy(char *dest, const char *source) return dest; } -void *_memcpy(void *dest, const void *source, int count) +void *memcpy(void *dest, const void *source, int count) { char *d = dest; const char *s = source; @@ -19,7 +19,7 @@ void *_memcpy(void *dest, const void *source, int count) return dest; } -int _strcmp(const char *s1, const char *s2) +int strcmp(const char *s1, const char *s2) { char ret = 0; diff --git a/src/z80/Makefile b/src/z80/Makefile index a248555c..2f6ef6e3 100644 --- a/src/z80/Makefile +++ b/src/z80/Makefile @@ -18,4 +18,6 @@ $(LIB): peeph.rul $(OBJ) peeph.rul: peeph.def $(AWK) -f ../SDCCpeeph.awk peeph.def > peeph.rul +main.o: main.c peeph.rul + include clean.mk diff --git a/src/z80/gen.c b/src/z80/gen.c index 92601216..50154dd3 100644 --- a/src/z80/gen.c +++ b/src/z80/gen.c @@ -859,8 +859,10 @@ void toBoolean(operand *oper) emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE)); } else { - CLRC; - emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE)); + if (AOP(oper)->type != AOP_ACC) { + CLRC; + emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE)); + } } } @@ -1407,7 +1409,7 @@ static bool genPlusIncr (iCode *ic) if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) && isPair(AOP(IC_RESULT(ic)))) { while (icount--) { - emitcode("inc", "%s ; 1", getPairName(AOP(IC_RESULT(ic)))); + emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic)))); } return TRUE; } @@ -1596,6 +1598,25 @@ static bool genMinusDec (iCode *ic) return FALSE; size = getDataSize(IC_RESULT(ic)); + +#if 0 + /* if increment 16 bits in register */ + if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) && + (size > 1) && + (icount == 1)) { + symbol *tlbl = newiTempLabel(NULL); + emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE)); + emitcode("jp", "np," LABEL_STR ,tlbl->key+100); + + emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE)); + if(size == 4) { + assert(0); + } + emitcode("", LABEL_STR ":",tlbl->key+100); + return TRUE; + } +#endif + /* if decrement 16 bits in register */ if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) && (size > 1) && isPair(AOP(IC_RESULT(ic)))) { @@ -1804,7 +1825,7 @@ static void genCmp (operand *left,operand *right, emitcode("cp", "%s^0x80", aopGet(AOP(right), offset, FALSE)); } else - emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE)); + emitcode("cp", "%s ; 7", aopGet(AOP(right), offset, FALSE)); } else { if(AOP_TYPE(right) == AOP_LIT) { @@ -1972,8 +1993,11 @@ static void gencjneshort(operand *left, operand *right, symbol *lbl) if (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR ) { while (size--) { - emitcode("ld", "a,%s", aopGet(AOP(left),offset,FALSE)); - emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE)); + emitcode("ld", "a,%s ; 2", aopGet(AOP(left),offset,FALSE)); + if ((AOP_TYPE(right) == AOP_LIT) && lit == 0) + emitcode("or", "a,a"); + else + emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE)); emitcode("jp", "nz," LABEL_STR , lbl->key+100); offset++; } @@ -1990,7 +2014,7 @@ static void gencjneshort(operand *left, operand *right, symbol *lbl) /* PENDING */ emitcode("jp","nz," LABEL_STR ,lbl->key+100); else { - emitcode("cp", "%s", aopGet(AOP(right),offset,FALSE)); + emitcode("cp", "%s ; 4", aopGet(AOP(right),offset,FALSE)); emitcode("jp", "nz," LABEL_STR , lbl->key+100); } offset++; @@ -2001,7 +2025,7 @@ static void gencjneshort(operand *left, operand *right, symbol *lbl) while(size--) { char *l = aopGet(AOP(left),offset,FALSE); MOVA(aopGet(AOP(right),offset,FALSE)); - emitcode("cp", "%s", l); + emitcode("cp", "%s ; 5", l); emitcode("jr", "nz," LABEL_STR, lbl->key+100); offset++; } diff --git a/src/z80/peeph.def b/src/z80/peeph.def index 9fd073d6..63f57e35 100644 --- a/src/z80/peeph.def +++ b/src/z80/peeph.def @@ -3,3 +3,62 @@ replace restart { } by { ; Removed redundent load } +replace restart { + xor a,a + or a,%1 + or a,a + jp %2,%3 +} by { + ; Removed redundent or a,a + xor a,a + or a,%1 + jp %2,%3 +} +replace restart { + cp a,#0x00 + jp nz,%1 +} by { + ; Rule 3 + or a,a + jp nz,%1 +} +replace restart { + jp nz,%1 + jp %2 +%1: + jp %3 +%2: +} by { + ; Rule 4 + jp z,%2 +%1: + jp %3 +%2: +} +replace restart { + jp nz,%1 + jp %2 +%1: +} by { + ; Rule 5 + jp z,%2 +%1: +} +replace restart { + jp z,%1 + jp %2 +%1: +} by { + ; Rule 6 + jp nz,%2 +%1: +} +replace restart { +%1: + jp %2 + jp %3 +} by { + ; Weird Rule 7 +%1: + jp %2 +} diff --git a/src/z80/ralloc.c b/src/z80/ralloc.c index dd75f56b..1e651850 100644 --- a/src/z80/ralloc.c +++ b/src/z80/ralloc.c @@ -1755,6 +1755,216 @@ static void packRegsForAccUse (iCode *ic) OP_SYMBOL(IC_RESULT(ic))->accuse = 1; } +bool opPreservesA(iCode *ic, iCode *uic) +{ + /* if the usage has only one operand then we can */ + if (IC_LEFT(ic) == NULL || + IC_RIGHT(ic) == NULL) + return TRUE; + + if (uic->op != '=' && + !IS_ARITHMETIC_OP(uic) && + !IS_BITWISE_OP(uic) && + uic->op != EQ_OP && + uic->op != LEFT_OP && + uic->op != RIGHT_OP ) { + return FALSE; + } + + /* PENDING */ + if (!IC_LEFT(uic) || !IC_RESULT(ic)) + return FALSE; + + /** This is confusing :) Guess for now */ + if (IC_LEFT(uic)->key == IC_RESULT(ic)->key && + (IS_ITEMP(IC_RIGHT(uic)) || + (IS_TRUE_SYMOP(IC_RIGHT(uic))))) + return TRUE; + + if (IC_RIGHT(uic)->key == IC_RESULT(ic)->key && + (IS_ITEMP(IC_LEFT(uic)) || + (IS_TRUE_SYMOP(IC_LEFT(uic))))) + return TRUE; + + return FALSE; +} + +/** Pack registers for acc use. + When the result of this operation is small and short lived it may + be able to be stored in the accumelator. + */ +static void packRegsForAccUse2(iCode *ic) +{ + iCode *uic; + + /* if + or - then it has to be one byte result. + MLH: Ok. + */ + if ((ic->op == '+' || ic->op == '-') + && getSize(operandType(IC_RESULT(ic))) > 1) + return ; + + /* if shift operation make sure right side is not a literal. + MLH: depends. + */ +#if 0 + if (ic->op == RIGHT_OP && + (isOperandLiteral(IC_RIGHT(ic)) || + getSize(operandType(IC_RESULT(ic))) > 1)) + return ; + + if (ic->op == LEFT_OP && + ( isOperandLiteral(IC_RIGHT(ic)) || + getSize(operandType(IC_RESULT(ic))) > 1)) + return ; +#endif + + /* has only one definition */ + if (bitVectnBitsOn(OP_DEFS(IC_RESULT(ic))) > 1) { + return; + } + + /* Right. We may be able to propagate it through if: + For each in the chain of uses the intermediate is OK. + */ + /* Get next with 'uses result' bit on + If this->next == next + Validate use of next + If OK, increase count + */ + /* and the usage immediately follows this iCode */ + if (!(uic = hTabItemWithKey(iCodehTab, + bitVectFirstBit(OP_USES(IC_RESULT(ic)))))) { + return; + } + + { + /* Create a copy of the OP_USES bit vect */ + bitVect *uses = bitVectCopy(OP_USES(IC_RESULT(ic))); + int setBit; + iCode *scan = ic, *next; + + do { + setBit = bitVectFirstBit(uses); + next = hTabItemWithKey(iCodehTab, setBit); + if (scan->next == next) { + bitVectUnSetBit(uses, setBit); + /* Still contigous. */ + if (!opPreservesA(ic, next)) { + return; + } + scan = next; + } + else { + return; + } + } while (!bitVectIsZero(uses)); + OP_SYMBOL(IC_RESULT(ic))->accuse = 1; + return; + } + + /* OLD CODE FOLLOWS */ + /* if it is a conditional branch then we definitely can + MLH: Depends. + */ +#if 0 + if (uic->op == IFX ) + goto accuse; + + /* MLH: Depends. */ + if ( uic->op == JUMPTABLE ) + return ; +#endif + + /* if the usage is not is an assignment or an + arithmetic / bitwise / shift operation then not. + MLH: Pending: Invalid. Our pointer sets are always peechy. + */ +#if 0 + if (POINTER_SET(uic) && + getSize(aggrToPtr(operandType(IC_RESULT(uic)),FALSE)) > 1) { + printf("e5 %u\n", getSize(aggrToPtr(operandType(IC_RESULT(uic)),FALSE))); + return; + } +#endif + + printf("1\n"); + if (uic->op != '=' && + !IS_ARITHMETIC_OP(uic) && + !IS_BITWISE_OP(uic) && + uic->op != LEFT_OP && + uic->op != RIGHT_OP ) { + printf("e6\n"); + return; + } + + /* if used in ^ operation then make sure right is not a + literl */ + if (uic->op == '^' && isOperandLiteral(IC_RIGHT(uic))) + return ; + + /* if shift operation make sure right side is not a literal */ + if (uic->op == RIGHT_OP && + ( isOperandLiteral(IC_RIGHT(uic)) || + getSize(operandType(IC_RESULT(uic))) > 1)) + return ; + + if (uic->op == LEFT_OP && + ( isOperandLiteral(IC_RIGHT(uic)) || + getSize(operandType(IC_RESULT(uic))) > 1)) + return ; + +#if 0 + /* make sure that the result of this icode is not on the + stack, since acc is used to compute stack offset */ + if (IS_TRUE_SYMOP(IC_RESULT(uic)) && + OP_SYMBOL(IC_RESULT(uic))->onStack) + return ; +#endif + +#if 0 + /* if either one of them in far space then we cannot */ + if ((IS_TRUE_SYMOP(IC_LEFT(uic)) && + isOperandInFarSpace(IC_LEFT(uic))) || + (IS_TRUE_SYMOP(IC_RIGHT(uic)) && + isOperandInFarSpace(IC_RIGHT(uic)))) + return ; +#endif + + /* if the usage has only one operand then we can */ + if (IC_LEFT(uic) == NULL || + IC_RIGHT(uic) == NULL) + goto accuse; + + /* make sure this is on the left side if not + a '+' since '+' is commutative */ + if (ic->op != '+' && + IC_LEFT(uic)->key != IC_RESULT(ic)->key) + return; + + /* if one of them is a literal then we can */ + if ((IC_LEFT(uic) && IS_OP_LITERAL(IC_LEFT(uic))) || + (IC_RIGHT(uic) && IS_OP_LITERAL(IC_RIGHT(uic)))) { + OP_SYMBOL(IC_RESULT(ic))->accuse = 1; + return ; + } + + /** This is confusing :) Guess for now */ + if (IC_LEFT(uic)->key == IC_RESULT(ic)->key && + (IS_ITEMP(IC_RIGHT(uic)) || + (IS_TRUE_SYMOP(IC_RIGHT(uic))))) + goto accuse; + + if (IC_RIGHT(uic)->key == IC_RESULT(ic)->key && + (IS_ITEMP(IC_LEFT(uic)) || + (IS_TRUE_SYMOP(IC_LEFT(uic))))) + goto accuse ; + return ; + accuse: + printf("acc ok!\n"); + OP_SYMBOL(IC_RESULT(ic))->accuse = 1; +} + /** Does some transformations to reduce register pressure. */ static void packRegisters (eBBlock *ebp) @@ -1863,6 +2073,7 @@ static void packRegisters (eBBlock *ebp) only one operand or has two operands but one is literal & the result of that operation is not on stack then we can leave the result of this operation in acc:b combination */ +#if 0 if ((IS_ARITHMETIC_OP(ic) || IS_BITWISE_OP(ic) || ic->op == LEFT_OP || ic->op == RIGHT_OP @@ -1870,6 +2081,17 @@ static void packRegisters (eBBlock *ebp) IS_ITEMP(IC_RESULT(ic)) && getSize(operandType(IC_RESULT(ic))) <= 2) packRegsForAccUse (ic); +#else + if ((POINTER_GET(ic) || + IS_ARITHMETIC_OP(ic) || + IS_BITWISE_OP(ic) || + ic->op == LEFT_OP || + ic->op == RIGHT_OP + ) && + IS_ITEMP(IC_RESULT(ic)) && + getSize(operandType(IC_RESULT(ic))) == 1) + packRegsForAccUse2(ic); +#endif } }