X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fz80%2Fralloc.c;h=02a2fc90cc64b471ee0c0f5aa97a211ceb802e08;hb=fc8ce1a538d4f56e80f3129db270426c840baf1b;hp=01add6516844f1c1f0cee30b6e84d91de5cc36e5;hpb=7d3377407877cd32f73a308d417eb1988449ac7f;p=fw%2Fsdcc diff --git a/src/z80/ralloc.c b/src/z80/ralloc.c index 01add651..02a2fc90 100644 --- a/src/z80/ralloc.c +++ b/src/z80/ralloc.c @@ -7,8 +7,9 @@ hardware. It allocates based on usage and how long the varible lives into registers or temporary memory on the stack. - On the Z80 hl, ix, iy, and a are reserved for the code generator, - leaving bc and de for allocation. The extra register pressure + On the Z80 hl and ix and a are reserved for the code generator, + leaving bc and de for allocation. iy is unusable due to currently + as it's only adressable as a pair. The extra register pressure from reserving hl is made up for by how much easier the sub operations become. You could swap hl for iy if the undocumented iyl/iyh instructions are available. @@ -44,6 +45,20 @@ #include "z80.h" +enum { + DISABLE_PACK_ACC = 0, + DISABLE_PACK_ASSIGN = 0, + LIMITED_PACK_ACC = 1 +}; + +#define D_ALLOC 1 + +#if 0 +#define D(_a, _s) if (_a) { printf _s; fflush(stdout); } +#else +#define D(_a, _s) +#endif + /*-----------------------------------------------------------------*/ /* At this point we start getting processor specific although */ /* some routines are non-processor specific & can be reused when */ @@ -59,7 +74,6 @@ bitVect *regAssigned = NULL; short blockSpil = 0; int slocNum = 0 ; extern void genZ80Code(iCode *); -int ptrRegReq = 0; /* one byte pointer register required */ bitVect *funcrUsed = NULL; /* registers used in a function */ int stackExtend = 0; int dataExtend = 0; @@ -119,9 +133,11 @@ static regs *allocReg (short type) if (currFunc) currFunc->regsUsed = bitVectSetBit(currFunc->regsUsed,i); + D(D_ALLOC, ("allocReg: alloced %zr\n", ®sZ80[i])); return ®sZ80[i]; } } + D(D_ALLOC, ("allocReg: No free.\n")); return NULL; } @@ -134,7 +150,7 @@ regs *regWithIdx (int idx) for (i=0;i < _nRegs;i++) if (regsZ80[i].rIdx == idx) return ®sZ80[i]; - + werror(E_INTERNAL_ERROR,__FILE__,__LINE__, "regWithIdx not found"); exit(1); @@ -144,8 +160,9 @@ regs *regWithIdx (int idx) */ static void freeReg (regs *reg) { - assert(!reg->isFree); + wassert(!reg->isFree); reg->isFree = 1; + D(D_ALLOC, ("freeReg: freed %zr\n", reg)); } @@ -334,14 +351,12 @@ static int noOverLap (set *itmpStack, symbol *fsym) { symbol *sym; - for (sym = setFirstItem(itmpStack); sym; sym = setNextItem(itmpStack)) { if (sym->liveTo > fsym->liveFrom ) return 0; } - return 1; } @@ -372,14 +387,6 @@ DEFSETFUNC(isFree) return 0; } -/*-----------------------------------------------------------------*/ -/* spillLRWithPtrReg :- will spil those live ranges which use PTR */ -/*-----------------------------------------------------------------*/ -static void spillLRWithPtrReg (symbol *forSym) -{ - /* Always just return */ -} - /*-----------------------------------------------------------------*/ /* createStackSpil - create a location on the stack to spil */ /*-----------------------------------------------------------------*/ @@ -387,6 +394,8 @@ symbol *createStackSpil (symbol *sym) { symbol *sloc= NULL; + D(D_ALLOC, ("createStackSpil: for sym %zs\n", sym)); + /* first go try and find a free one that is already existing on the stack */ if (applyToSet(stackSpil,isFree,&sloc, sym)) { @@ -395,6 +404,7 @@ symbol *createStackSpil (symbol *sym) sym->stackSpil= 1; sloc->isFree = 0; addSetHead(&sloc->usl.itmpStack,sym); + D(D_ALLOC, ("createStackSpil: found existing\n")); return sym; } @@ -436,6 +446,8 @@ symbol *createStackSpil (symbol *sym) /* add it to the set of itempStack set of the spill location */ addSetHead(&sloc->usl.itmpStack,sym); + + D(D_ALLOC, ("createStackSpil: created new\n")); return sym; } @@ -471,12 +483,14 @@ bool isSpiltOnStack (symbol *sym) static void spillThis (symbol *sym) { int i; + + D(D_ALLOC, ("spillThis: spilling %zs\n", sym)); + /* if this is rematerializable or has a spillLocation we are okay, else we need to create a spillLocation for it */ if (!(sym->remat || sym->usl.spillLoc)) createStackSpil (sym); - /* mark it has spilt & put it in the spilt set */ sym->isspilt = 1; @@ -484,21 +498,16 @@ static void spillThis (symbol *sym) bitVectUnSetBit(regAssigned,sym->key); - for (i = 0 ; i < sym->nRegs ; i++) - + for (i = 0 ; i < sym->nRegs ; i++) { if (sym->regs[i]) { freeReg(sym->regs[i]); sym->regs[i] = NULL; } + } /* if spilt on stack then free up r0 & r1 if they could have been assigned to some LIVE ranges */ - if (!ptrRegReq && isSpiltOnStack(sym)) { - ptrRegReq++ ; - spillLRWithPtrReg(sym); - } - if (sym->usl.spillLoc && !sym->remat) sym->usl.spillLoc->allocreq = 1; return; @@ -512,12 +521,13 @@ symbol *selectSpil (iCode *ic, eBBlock *ebp, symbol *forSym) set *selectS ; symbol *sym; + D(D_ALLOC, ("selectSpil: finding spill for ic %zi\n", ic)); /* get the spillable live ranges */ lrcs = computeSpillable (ic); /* get all live ranges that are rematerizable */ if ((selectS = liveRangesWith(lrcs,rematable,ebp,ic))) { - + D(D_ALLOC, ("selectSpil: using remat.\n")); /* return the least used of these */ return leastUsedLR(selectS); } @@ -573,7 +583,7 @@ symbol *selectSpil (iCode *ic, eBBlock *ebp, symbol *forSym) /* find live ranges with spillocation */ if ((selectS = liveRangesWith(lrcs,hasSpilLoc,ebp,ic))) { - + D(D_ALLOC, ("selectSpil: using with spill.\n")); sym = leastUsedLR(selectS); sym->usl.spillLoc->allocreq = 1; return sym; @@ -583,6 +593,7 @@ symbol *selectSpil (iCode *ic, eBBlock *ebp, symbol *forSym) location on the stack , for which one? the least used ofcourse */ if ((selectS = liveRangesWith(lrcs,noSpilLoc,ebp,ic))) { + D(D_ALLOC, ("selectSpil: creating new spill.\n")); /* return a created spil location */ sym = createStackSpil(leastUsedLR(selectS)); sym->usl.spillLoc->allocreq = 1; @@ -591,6 +602,7 @@ symbol *selectSpil (iCode *ic, eBBlock *ebp, symbol *forSym) /* this is an extreme situation we will spill this one : happens very rarely but it does happen */ + D(D_ALLOC, ("selectSpil: using spillThis.\n")); spillThis ( forSym ); return forSym; @@ -604,6 +616,8 @@ bool spilSomething (iCode *ic, eBBlock *ebp, symbol *forSym) symbol *ssym; int i ; + D(D_ALLOC, ("spilSomething: spilling on ic %zi\n", ic)); + /* get something we can spil */ ssym = selectSpil(ic,ebp,forSym); @@ -619,7 +633,6 @@ bool spilSomething (iCode *ic, eBBlock *ebp, symbol *forSym) for (i = 0 ; i < ssym->nRegs ;i++ ) if (ssym->regs[i]) freeReg(ssym->regs[i]); - #if 0 /* if spilt on stack then free up r0 & r1 if they could have been assigned to as gprs */ @@ -655,6 +668,8 @@ bool spilSomething (iCode *ic, eBBlock *ebp, symbol *forSym) } #endif + D(D_ALLOC, ("spilSomething: done.\n")); + if (ssym == forSym ) return FALSE ; else @@ -667,18 +682,19 @@ regs *getRegGpr (iCode *ic, eBBlock *ebp,symbol *sym) { regs *reg; + D(D_ALLOC, ("getRegGpr: on ic %zi\n")); tryAgain: /* try for gpr type */ - if ((reg = allocReg(REG_GPR))) + if ((reg = allocReg(REG_GPR))) { + D(D_ALLOC, ("getRegGpr: got a reg.\n")); return reg; - - if (!ptrRegReq) - if ((reg = allocReg(REG_PTR))) - return reg ; + } /* we have to spil */ - if (!spilSomething (ic,ebp,sym)) + if (!spilSomething (ic,ebp,sym)) { + D(D_ALLOC, ("getRegGpr: have to spill.\n")); return NULL ; + } /* this looks like an infinite loop but in really selectSpil will abort */ @@ -738,6 +754,8 @@ static void deassignLRs (iCode *ic, eBBlock *ebp) !OP_SYMBOL(IC_LEFT(ic->prev))->isspilt) psym = OP_SYMBOL(IC_LEFT(ic->prev)); + D(D_ALLOC, ("deassignLRs: in loop on sym %zs", sym)); + if (sym->nRegs) { int i = 0; @@ -766,15 +784,23 @@ static void deassignLRs (iCode *ic, eBBlock *ebp) ((nfreeRegsType(result->regType) + sym->nRegs) >= result->nRegs) ) { - - for (i = 0 ; i < max(sym->nRegs,result->nRegs) ; i++) + for (i = 0 ; i < max(sym->nRegs,result->nRegs) ; i++) { if (i < sym->nRegs ) result->regs[i] = sym->regs[i] ; else result->regs[i] = getRegGpr (ic,ebp,result); + + /* if the allocation falied which means + this was spilt then break */ + if (!result->regs[i]) { + wassert(0); + assert(0); + break; + } + } regAssigned = bitVectSetBit(regAssigned,result->key); - } + } /* free the remaining */ for (; i < sym->nRegs ; i++) { @@ -783,6 +809,7 @@ static void deassignLRs (iCode *ic, eBBlock *ebp) freeReg(sym->regs[i]); } else freeReg(sym->regs[i]); + // sym->regs[i] = NULL; } } } @@ -796,6 +823,8 @@ static void reassignLR (operand *op) symbol *sym = OP_SYMBOL(op); int i; + D(D_ALLOC, ("reassingLR: on sym %zs\n", sym)); + /* not spilt any more */ sym->isspilt = sym->blockSpil = sym->remainSpil = 0; bitVectUnSetBit(spiltSet,sym->key); @@ -827,30 +856,32 @@ static int willCauseSpill ( int nr, int rt) */ static void positionRegs (symbol *result, symbol *opsym, int lineno) { - int count = min(result->nRegs,opsym->nRegs); - int i , j = 0, shared = 0; + int count = min(result->nRegs,opsym->nRegs); + int i , j = 0, shared = 0; + + D(D_ALLOC, ("positionRegs: on result %zs opsum %zs line %u\n", result, opsym, lineno)); - /* if the result has been spilt then cannot share */ - if (opsym->isspilt) - return ; + /* if the result has been spilt then cannot share */ + if (opsym->isspilt) + return ; again: - shared = 0; - /* first make sure that they actually share */ - for ( i = 0 ; i < count; i++ ) { - for (j = 0 ; j < count ; j++ ) { - if (result->regs[i] == opsym->regs[j] && i !=j) { - shared = 1; - goto xchgPositions; - } - } + shared = 0; + /* first make sure that they actually share */ + for ( i = 0 ; i < count; i++ ) { + for (j = 0 ; j < count ; j++ ) { + if (result->regs[i] == opsym->regs[j] && i !=j) { + shared = 1; + goto xchgPositions; + } } + } xchgPositions: - if (shared) { - regs *tmp = result->regs[i]; - result->regs[i] = result->regs[j]; - result->regs[j] = tmp; - goto again; - } + if (shared) { + regs *tmp = result->regs[i]; + result->regs[i] = result->regs[j]; + result->regs[j] = tmp; + goto again; + } } /** Try to allocate a pair of registers to the symbol. @@ -858,7 +889,7 @@ static void positionRegs (symbol *result, symbol *opsym, int lineno) bool tryAllocatingRegPair(symbol *sym) { int i; - assert(sym->nRegs == 2); + wassert(sym->nRegs == 2); for ( i = 0 ; i < _nRegs ; i+=2 ) { if ((regsZ80[i].isFree)&&(regsZ80[i+1].isFree)) { regsZ80[i].isFree = 0; @@ -871,9 +902,11 @@ bool tryAllocatingRegPair(symbol *sym) currFunc->regsUsed = bitVectSetBit(currFunc->regsUsed,i+1); } + D(D_ALLOC, ("tryAllocRegPair: succeded for sym %zs\n", sym)); return TRUE; } } + D(D_ALLOC, ("tryAllocRegPair: failed on sym %zs\n", sym)); return FALSE; } @@ -900,8 +933,10 @@ static void serialRegAssign (eBBlock **ebbs, int count) /* if this is an ipop that means some live range will have to be assigned again */ - if (ic->op == IPOP) + if (ic->op == IPOP) { + wassert(0); reassignLR (IC_LEFT(ic)); + } /* if result is present && is a true symbol */ if (IC_RESULT(ic) && ic->op != IFX && @@ -928,19 +963,24 @@ static void serialRegAssign (eBBlock **ebbs, int count) int willCS ; int j; + D(D_ALLOC, ("serialRegAssign: in loop on result %zs\n", sym)); + /* if it does not need or is spilt or is already assigned to registers or will not live beyond this instructions */ if (!sym->nRegs || sym->isspilt || bitVectBitValue(regAssigned,sym->key) || - sym->liveTo <= ic->seq) + sym->liveTo <= ic->seq) { + D(D_ALLOC, ("serialRegAssign: wont live long enough.\n")); continue ; + } /* if some liverange has been spilt at the block level and this one live beyond this block then spil this to be safe */ if (blockSpil && sym->liveTo > ebbs[i]->lSeq) { + D(D_ALLOC, ("serialRegAssign: \"spilling to be safe.\"\n")); spillThis (sym); continue ; } @@ -953,6 +993,7 @@ static void serialRegAssign (eBBlock **ebbs, int count) if ( sym->remat || (willCS && bitVectIsZero(spillable) ) ) { + D(D_ALLOC, ("serialRegAssign: \"remat spill\"\n")); spillThis (sym) ; continue ; @@ -979,6 +1020,7 @@ static void serialRegAssign (eBBlock **ebbs, int count) /* Special case: Try to fit into a reg pair if available */ + D(D_ALLOC, ("serialRegAssign: actually allocing regs!\n")); if ((sym->nRegs == 2)&&tryAllocatingRegPair(sym)) { } else { @@ -1032,8 +1074,7 @@ bitVect *rUmaskForOp (operand *op) rumask = newBitVect(_nRegs); for (j = 0; j < sym->nRegs; j++) { - rumask = bitVectSetBit(rumask, - sym->regs[j]->rIdx); + rumask = bitVectSetBit(rumask, sym->regs[j]->rIdx); } return rumask; @@ -1169,7 +1210,7 @@ char *rematStr (symbol *sym) /*-----------------------------------------------------------------*/ /* regTypeNum - computes the type & number of registers required */ /*-----------------------------------------------------------------*/ -static void regTypeNum () +static void regTypeNum (void) { symbol *sym; int k; @@ -1182,6 +1223,8 @@ static void regTypeNum () if ((sym->liveTo - sym->liveFrom) == 0) continue ; + D(D_ALLOC, ("regTypeNum: loop on sym %zs\n", sym)); + /* if the live range is a temporary */ if (sym->isitmp) { @@ -1202,6 +1245,8 @@ static void regTypeNum () getSize(sym->type = aggrToPtr(sym->type,FALSE)) : getSize(sym->type)); + D(D_ALLOC, ("regTypeNum: setup to assign regs sym %zs\n", sym)); + if (sym->nRegs > 4) { fprintf(stderr,"allocated more than 4 or 0 registers for type "); printTypeChain(sym->type,stderr);fprintf(stderr,"\n"); @@ -1226,6 +1271,8 @@ static void freeAllRegs() { int i; + D(D_ALLOC, ("freeAllRegs: running.\n")); + for (i=0;i< _nRegs;i++ ) regsZ80[i].isFree = 1; } @@ -1246,6 +1293,8 @@ DEFSETFUNC(deallocStackSpil) static int packRegsForAssign (iCode *ic,eBBlock *ebp) { iCode *dic, *sic; + + D(D_ALLOC, ("packRegsForAssing: running on ic %zi\n", ic)); if ( /* !IS_TRUE_SYMOP(IC_RESULT(ic)) ||*/ @@ -1431,6 +1480,8 @@ static int packRegsForSupport (iCode *ic, eBBlock *ebp) /* for the left & right operand :- look to see if the left was assigned a true symbol in far space in that case replace them */ + D(D_ALLOC, ("packRegsForSupport: running on ic %zi\n", ic)); + if (IS_ITEMP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->liveTo <= ic->seq) { iCode *dic = findAssignToSym(IC_LEFT(ic),ic); @@ -1486,6 +1537,8 @@ static iCode *packRegsForOneuse (iCode *ic, operand *op , eBBlock *ebp) bitVect *uses ; iCode *dic, *sic; + D(D_ALLOC, ("packRegsForOneUse: running on ic %zi\n", ic)); + /* if returning a literal then do nothing */ if (!IS_SYMOP(op)) return NULL; @@ -1751,22 +1804,39 @@ static void packRegsForAccUse (iCode *ic) bool opPreservesA(iCode *ic, iCode *uic) { + /* if it is a conditional branch then we definitely can */ + if (uic->op == IFX ) + return FALSE; + + if ( uic->op == JUMPTABLE ) + return FALSE; + /* if the usage has only one operand then we can */ + /* PENDING: check */ if (IC_LEFT(uic) == NULL || IC_RIGHT(uic) == NULL) - return TRUE; + return FALSE; + /* PENDING: check this rule */ if (getSize(operandType(IC_RESULT(uic))) > 1) { return FALSE; } - if (uic->op != '=' && - !IS_ARITHMETIC_OP(uic) && + /* + Bad: + !IS_ARITHMETIC_OP(uic) (sub requires A) + */ + if ( + uic->op != '+' && !IS_BITWISE_OP(uic) && + uic->op != '=' && uic->op != EQ_OP && - uic->op != LEFT_OP && !POINTER_GET(uic) && - uic->op != RIGHT_OP ) { + /* + uic->op != LEFT_OP && + uic->op != RIGHT_OP &&*/ + 1 + ) { return FALSE; } @@ -1791,11 +1861,26 @@ bool opPreservesA(iCode *ic, iCode *uic) /** 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. + + Note that the 'A preserving' list is currently emperical :)e */ static void packRegsForAccUse2(iCode *ic) { iCode *uic; + D(D_ALLOC, ("packRegsForAccUse2: running on ic %zi\n", ic)); + + /* Filter out all but those 'good' commands */ + if ( + !POINTER_GET(ic) && + ic->op != '+' && + !IS_BITWISE_OP(ic) && + ic->op != '=' && + ic->op != EQ_OP && + ic->op != CAST && + 1) + return; + /* if + or - then it has to be one byte result. MLH: Ok. */ @@ -1970,8 +2055,10 @@ static void packRegisters (eBBlock *ebp) { iCode *ic ; int change = 0 ; + + D(D_ALLOC, ("packRegisters: entered.\n")); - while (1) { + while (1 && !DISABLE_PACK_ASSIGN) { change = 0; /* look for assignments of the form */ /* iTempNN = TRueSym (someoperation) SomeOperand */ @@ -1990,6 +2077,9 @@ static void packRegisters (eBBlock *ebp) /* Safe: address of a true sym is always constant. */ /* if this is an itemp & result of a address of a true sym then mark this as rematerialisable */ + + D(D_ALLOC, ("packRegisters: looping on ic %zi\n", ic)); + if (ic->op == ADDRESS_OF && IS_ITEMP(IC_RESULT(ic)) && IS_TRUE_SYMOP(IC_LEFT(ic)) && @@ -2079,7 +2169,7 @@ static void packRegisters (eBBlock *ebp) getSize(operandType(IC_RESULT(ic))) <= 2) packRegsForAccUse (ic); #else - if (IS_ITEMP(IC_RESULT(ic)) && + if (!DISABLE_PACK_ACC && IS_ITEMP(IC_RESULT(ic)) && getSize(operandType(IC_RESULT(ic))) == 1) packRegsForAccUse2(ic); #endif @@ -2094,8 +2184,10 @@ void z80_assignRegisters (eBBlock **ebbs, int count) iCode *ic; int i ; + D(D_ALLOC, ("\n-> z80_assignRegisters: entered.\n")); + setToNull((void *)&funcrUsed); - ptrRegReq = stackExtend = dataExtend = 0; + stackExtend = dataExtend = 0; if (IS_GB) { /* DE is required for the code gen. */