X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fz80%2Fralloc.c;h=59ee73c6d33657b3b599144f82e8bfc310bb74ed;hb=70fe73bde6188da1e58bc4b0f333fe3ef96c83a8;hp=7027e57b046406482c7ad96c5045357c91f12929;hpb=a8bd79f0b8619a3d1773c58c623888d2e2fe7c22;p=fw%2Fsdcc diff --git a/src/z80/ralloc.c b/src/z80/ralloc.c index 7027e57b..59ee73c6 100644 --- a/src/z80/ralloc.c +++ b/src/z80/ralloc.c @@ -45,21 +45,26 @@ #include "z80.h" +/* Flags to turn off optimisations. + */ enum { DISABLE_PACK_ACC = 0, DISABLE_PACK_ASSIGN = 0, - DISABLE_PACK_ONE_USE = 0, + /* Pack for one use is quite broken. */ + DISABLE_PACK_ONE_USE = 1, DISABLE_PACK_HL = 0, - LIMITED_PACK_ACC = 1, }; +/* Flags to turn on debugging code. + */ enum { D_ALLOC = 0, D_ALLOC2 = 0, D_ACCUSE2 = 0, - D_ACCUSE2_VERBOSE = 0 + D_ACCUSE2_VERBOSE = 0, + D_HLUSE = 0 }; #if 1 @@ -2013,32 +2018,84 @@ packRegsForHLUse (iCode * ic) { iCode *uic; - if (IS_GB) - return; + /* PENDING: Could do IFX */ + if (ic->op == IFX) + { + return; + } /* has only one definition */ if (bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) > 1) - return; + { + D (D_HLUSE, (" + Dropping as has more than one def\n")); + return; + } /* has only one use */ if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1) - return; + { + D (D_HLUSE, (" + Dropping as has more than one use\n")); + return; + } /* and the usage immediately follows this iCode */ if (!(uic = hTabItemWithKey (iCodehTab, bitVectFirstBit (OP_USES (IC_RESULT (ic)))))) - return; + { + D (D_HLUSE, (" + Dropping as usage isn't in this block\n")); + return; + } if (ic->next != uic) - return; + { + D (D_HLUSE, (" + Dropping as usage doesn't follow this\n")); + return; + } + + if (uic->op ==IFX) + { + return; + } + + if (getSize (operandType (IC_RESULT (ic))) != 2 || + (IC_LEFT(uic) && getSize (operandType (IC_LEFT (uic))) != 2) || + (IC_RIGHT(uic) && getSize (operandType (IC_RIGHT (uic))) != 2)) + { + D (D_HLUSE, (" + Dropping as the result size is not 2\n")); + return; + } - if (ic->op == ADDRESS_OF && uic->op == IPUSH) - goto hluse; - if (ic->op == CALL && ic->parmBytes == 0 && (uic->op == '-' || uic->op == '+')) - goto hluse; + if (IS_Z80) + { + if (ic->op == CAST && uic->op == IPUSH) + goto hluse; + if (ic->op == ADDRESS_OF && uic->op == IPUSH) + goto hluse; + if (ic->op == ADDRESS_OF && POINTER_GET (uic) && IS_ITEMP( IC_RESULT (uic))) + goto hluse; + if (ic->op == CALL && ic->parmBytes == 0 && (uic->op == '-' || uic->op == '+')) + goto hluse; + } + else if (IS_GB) + { + /* Case of assign a constant to offset in a static array. */ + if (ic->op == '+' && IS_VALOP (IC_RIGHT (ic))) + { + if (uic->op == '=' && POINTER_SET (uic)) + { + goto hluse; + } + else if (uic->op == IPUSH && getSize (operandType (IC_LEFT (uic))) == 2) + { + goto hluse; + } + } + } + + D (D_HLUSE, (" + Dropping as it's a bad op\n")); return; hluse: - OP_SYMBOL (IC_RESULT (ic))->accuse = ACCUSE_HL; + OP_SYMBOL (IC_RESULT (ic))->accuse = ACCUSE_SCRATCH; } static bool @@ -2046,16 +2103,10 @@ opPreservesA (iCode * ic, iCode * uic) { if (uic->op == IFX) { + /* If we've gotten this far then the thing to compare must be + small enough and must be in A. + */ return TRUE; - - if (getSize (operandType (IC_COND (uic))) == 1 && - IS_OP_LITERAL (IC_COND (uic))) - { - return TRUE; - } - - D (D_ACCUSE2, (" + Dropping as operation is an IFX\n")); - return FALSE; } if (uic->op == JUMPTABLE) @@ -2086,50 +2137,10 @@ opPreservesA (iCode * ic, iCode * uic) return FALSE; } - /* - Bad: - !IS_ARITHMETIC_OP(uic) (sub requires A) - */ - if ( - uic->op != '+' && - !IS_BITWISE_OP (uic) && - uic->op != '=' && - uic->op != EQ_OP && - !POINTER_GET (uic) && - /* - uic->op != LEFT_OP && - uic->op != RIGHT_OP && */ - 1 - ) - { - D (D_ACCUSE2, (" + Dropping as 'its a bad op'\n")); - return FALSE; - } - - /* PENDING */ - if (!IC_LEFT (uic) || !IC_RESULT (ic)) - { - D (D_ACCUSE2, (" + Dropping for some reason #1\n")); - 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; - } - - D (D_ACCUSE2, (" + Dropping as hit default case\n")); + /* Disabled all of the old rules as they weren't verified and have + caused at least one problem. + */ return FALSE; } @@ -2228,6 +2239,7 @@ packRegsForAccUse2 (iCode * ic) ic->op != '=' && ic->op != EQ_OP && ic->op != CAST && + ic->op != GETHBIT && 1) { D (D_ACCUSE2, (" + Dropping as not a 'good' source command\n")); @@ -2244,21 +2256,6 @@ packRegsForAccUse2 (iCode * ic) 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) { @@ -2541,14 +2538,6 @@ packRegisters (eBBlock * ebp) packRegsForSupport (ic, ebp); #endif -#if 0 - /* some cases the redundant moves can - can be eliminated for return statements */ - if ((ic->op == RETURN || ic->op == SEND) && - !isOperandInFarSpace (IC_LEFT (ic)) && - !options.model) - packRegsForOneuse (ic, IC_LEFT (ic), ebp); -#endif /* if pointer set & left has a size more than one and right is not in far space */ if (!DISABLE_PACK_ONE_USE && @@ -2575,6 +2564,7 @@ packRegisters (eBBlock * ebp) packRegsForOneuse (ic, IC_LEFT (ic), ebp); } + /* pack registers for accumulator use, when the result of an arithmetic or bit wise operation has only one use, that use is immediately following the defintion and the using iCode has @@ -2586,24 +2576,71 @@ packRegisters (eBBlock * ebp) { packRegsForHLUse (ic); } -#if 0 - if ((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))) <= 2) - packRegsForAccUse (ic); -#else + if (!DISABLE_PACK_ACC && IS_ITEMP (IC_RESULT (ic)) && getSize (operandType (IC_RESULT (ic))) == 1) { packRegsForAccUse2 (ic); } -#endif } } +/** Joins together two byte constant pushes into one word push. + */ +static iCode * +joinPushes (iCode *lic) +{ + iCode *ic, *uic; + + for (ic = lic; ic; ic = ic->next) + { + int first, second; + value *val; + + uic = ic->next; + + /* Anything past this? */ + if (uic == NULL) + { + continue; + } + /* This and the next pushes? */ + if (ic->op != IPUSH || uic->op != IPUSH) + { + continue; + } + /* Both literals? */ + if ( !IS_OP_LITERAL (IC_LEFT (ic)) || !IS_OP_LITERAL (IC_LEFT (uic))) + { + continue; + } + /* Both characters? */ + if ( getSize (operandType (IC_LEFT (ic))) != 1 || getSize (operandType (IC_LEFT (uic))) != 1) + { + continue; + } + /* Pull out the values, make a new type, and create the new iCode for it. + */ + first = (int)operandLitValue ( IC_LEFT (ic)); + second = (int)operandLitValue ( IC_LEFT (uic)); + + sprintf (buffer, "%u", ((first << 8) | (second & 0xFF)) & 0xFFFFU); + val = constVal (buffer); + SPEC_NOUN (val->type) = V_INT; + IC_LEFT (ic)->operand.valOperand = val; + + /* Now remove the second one from the list. */ + ic->next = uic->next; + if (uic->next) + { + /* Patch up the reverse link */ + uic->next->prev = ic; + } + } + + return lic; +} + /*-----------------------------------------------------------------*/ /* assignRegisters - assigns registers to each live range as need */ /*-----------------------------------------------------------------*/ @@ -2660,8 +2697,10 @@ z80_assignRegisters (eBBlock ** ebbs, int count) _G.dataExtend = 0; } - if (options.dump_rassgn) + if (options.dump_rassgn) { dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count); + dumpLiveRanges (DUMP_LRANGE, liveRanges); + } /* after that create the register mask for each of the instruction */ @@ -2670,6 +2709,8 @@ z80_assignRegisters (eBBlock ** ebbs, int count) /* now get back the chain */ ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count)); + ic = joinPushes (ic); + /* redo that offsets for stacked automatic variables */ redoStackOffsets ();