X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fds390%2Fralloc.c;h=3743e964dcf776f0369cdb7aa3971d007aa844e4;hb=353ff1ac97be2a4c6fb07f88607dffaebe20590e;hp=14b254dbd880a3993bbc552bb4e374f931f81356;hpb=3c9e14cbfc4a5438052fa94f16842286188557fa;p=fw%2Fsdcc diff --git a/src/ds390/ralloc.c b/src/ds390/ralloc.c index 14b254db..3743e964 100644 --- a/src/ds390/ralloc.c +++ b/src/ds390/ralloc.c @@ -77,12 +77,19 @@ regs regs390[] = {REG_GPR, X10_IDX, REG_GPR, "x10", "x10", "xreg", 2, 0, 0}, {REG_GPR, X11_IDX, REG_GPR, "x11", "x11", "xreg", 3, 0, 0}, {REG_GPR, X12_IDX, REG_GPR, "x12", "x12", "xreg", 4, 0, 0}, - {REG_CND, CND_IDX, REG_GPR, "C", "C", "xreg", 0, 0, 0}, + {REG_CND, CND_IDX, REG_GPR, "C", "psw", "xreg", 0, 0, 0}, + {0, DPL1_IDX, 0, "dpl1", "dpl1", "dpl1", 0, 0, 0}, + {0, DPH1_IDX, 0, "dph1", "dph1", "dph1", 0, 0, 0}, + {0, DPX1_IDX, 0, "dpx1", "dpx1", "dpx1", 0, 0, 0}, + {0, DPS_IDX, 0, "dps", "dps", "dps", 0, 0, 0}, + {0, A_IDX, 0, "a", "acc", "acc", 0, 0, 0}, + {0, AP_IDX, 0, "ap", "ap", "ap", 0, 0, 0}, }; int ds390_nRegs = 13; static void spillThis (symbol *); static void freeAllRegs (); static iCode * packRegsDPTRuse (operand *); +static int packRegsDPTRnuse (operand *,int); /*-----------------------------------------------------------------*/ /* allocReg - allocates register of given type */ @@ -129,7 +136,7 @@ ds390_regWithIdx (int idx) { int i; - for (i = 0; i < ds390_nRegs; i++) + for (i = 0; i < sizeof(regs390)/sizeof(regs); i++) if (regs390[i].rIdx == idx) return ®s390[i]; @@ -189,31 +196,6 @@ nfreeRegsType (int type) } -/*-----------------------------------------------------------------*/ -/* allDefsOutOfRange - all definitions are out of a range */ -/*-----------------------------------------------------------------*/ -static bool -allDefsOutOfRange (bitVect * defs, int fseq, int toseq) -{ - int i; - - if (!defs) - return TRUE; - - for (i = 0; i < defs->size; i++) - { - iCode *ic; - - if (bitVectBitValue (defs, i) && - (ic = hTabItemWithKey (iCodehTab, i)) && - (ic->seq >= fseq && ic->seq <= toseq)) - - return FALSE; - - } - - return TRUE; -} /*-----------------------------------------------------------------*/ /* isOperandInReg - returns true if operand is currently in regs */ @@ -221,7 +203,9 @@ allDefsOutOfRange (bitVect * defs, int fseq, int toseq) static int isOperandInReg(operand *op) { if (!IS_SYMOP(op)) return 0; - + if (OP_SYMBOL(op)->ruonly) return 1; + if (OP_SYMBOL(op)->accuse) return 1; + if (OP_SYMBOL(op)->dptr) return 1; return bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(op)->key); } @@ -301,17 +285,6 @@ rematable (symbol * sym, eBBlock * ebp, iCode * ic) return sym->remat; } -/*-----------------------------------------------------------------*/ -/* notUsedInBlock - not used in this block */ -/*-----------------------------------------------------------------*/ -static int -notUsedInBlock (symbol * sym, eBBlock * ebp, iCode * ic) -{ - return (!bitVectBitsInCommon (sym->defs, ebp->usesDefs) && - allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq)); -/* return (!bitVectBitsInCommon(sym->defs,ebp->usesDefs)); */ -} - /*-----------------------------------------------------------------*/ /* notUsedInRemaining - not used or defined in remain of the block */ /*-----------------------------------------------------------------*/ @@ -395,7 +368,7 @@ leastUsedLR (set * sset) } - setToNull ((void **) &sset); + setToNull ((void *) &sset); sym->blockSpil = 0; return sym; } @@ -517,7 +490,8 @@ createStackSpil (symbol * sym) we need to allocate this on the stack : this is really a hack!! but cannot think of anything better at this time */ - if (sprintf (slocBuffer, "sloc%d", _G.slocNum++) >= sizeof (slocBuffer)) + if (SNPRINTF (slocBuffer, sizeof(slocBuffer), + "sloc%d", _G.slocNum++) >= sizeof (slocBuffer)) { fprintf (stderr, "***Internal error: slocBuffer overflowed: %s:%d\n", __FILE__, __LINE__); @@ -537,6 +511,7 @@ createStackSpil (symbol * sym) SPEC_EXTR (sloc->etype) = 0; SPEC_STAT (sloc->etype) = 0; SPEC_VOLATILE(sloc->etype) = 0; + SPEC_ABSA(sloc->etype) = 0; /* we don't allow it to be allocated` onto the external stack since : so we @@ -636,12 +611,12 @@ spillThis (symbol * sym) sym->regs[i] = NULL; } - /* if spilt on stack then free up r0 & r1 + /* if spilt on stack then free up r0 & r1 if they could have been assigned to some LIVE ranges */ - if (!ds390_ptrRegReq && isSpiltOnStack (sym)) + if (!ds390_ptrRegReq && isSpiltOnStack (sym) && !options.stack10bit) { - ds390_ptrRegReq += !options.stack10bit; + ds390_ptrRegReq ++; spillLRWithPtrReg (sym); } @@ -675,9 +650,10 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym) if ((selectS = liveRangesWith (lrcs, directSpilLoc, ebp, ic))) { sym = leastUsedLR (selectS); - strcpy (sym->rname, (sym->usl.spillLoc->rname[0] ? - sym->usl.spillLoc->rname : - sym->usl.spillLoc->name)); + strncpyz (sym->rname, + sym->usl.spillLoc->rname[0] ? + sym->usl.spillLoc->rname : sym->usl.spillLoc->name, + sizeof(sym->rname)); sym->spildir = 1; /* mark it as allocation required */ sym->usl.spillLoc->allocreq++; @@ -832,6 +808,7 @@ static regs * getRegPtr (iCode * ic, eBBlock * ebp, symbol * sym) { regs *reg; + int j; tryAgain: /* try for a ptr type */ @@ -846,6 +823,11 @@ tryAgain: if (!spilSomething (ic, ebp, sym)) return NULL; + /* make sure partially assigned registers aren't reused */ + for (j=0; j<=sym->nRegs; j++) + if (sym->regs[j]) + sym->regs[j]->isFree = 0; + /* this looks like an infinite loop but in really selectSpil will abort */ goto tryAgain; @@ -858,6 +840,7 @@ static regs * getRegGpr (iCode * ic, eBBlock * ebp, symbol * sym) { regs *reg; + int j; tryAgain: /* try for gpr type */ @@ -872,6 +855,11 @@ tryAgain: if (!spilSomething (ic, ebp, sym)) return NULL; + /* make sure partially assigned registers aren't reused */ + for (j=0; j<=sym->nRegs; j++) + if (sym->regs[j]) + sym->regs[j]->isFree = 0; + /* this looks like an infinite loop but in really selectSpil will abort */ goto tryAgain; @@ -893,6 +881,9 @@ static regs *getRegPtrNoSpil() return reg; assert(0); + + /* just to make the compiler happy */ + return 0; } /*-----------------------------------------------------------------*/ @@ -910,6 +901,9 @@ static regs *getRegGprNoSpil() return reg; assert(0); + + /* just to make the compiler happy */ + return 0; } /*-----------------------------------------------------------------*/ @@ -1131,6 +1125,122 @@ xchgPositions: return change ; } +/*-----------------------------------------------------------------*/ +/* unusedLRS - returns a bitVector of liveranges not used in 'ebp' */ +/*-----------------------------------------------------------------*/ +bitVect *unusedLRs (eBBlock *ebp) +{ + bitVect *ret = NULL; + symbol *sym; + int key; + + if (!ebp) return NULL; + for (sym = hTabFirstItem(liveRanges,&key); sym ; + sym = hTabNextItem(liveRanges,&key)) { + + if (notUsedInBlock(sym,ebp,NULL)) { + ret = bitVectSetBit(ret,sym->key); + } + } + + return ret; +} + +/*-----------------------------------------------------------------*/ +/* deassignUnsedLRs - if this baisc block ends in a return then */ +/* deassign symbols not used in this block */ +/*-----------------------------------------------------------------*/ +bitVect *deassignUnsedLRs(eBBlock *ebp) +{ + bitVect *unused = NULL; + int i; + + switch (returnAtEnd(ebp)) { + case 2: /* successor block ends in a return */ + unused = unusedLRs((eBBlock *) setFirstItem(ebp->succList)); + /* fall thru */ + case 1: /* this block ends in a return */ + unused = bitVectIntersect(unused,unusedLRs(ebp)); + break; + } + + if (unused) { + for (i = 0 ; i < unused->size ; i++ ) { + + /* if unused */ + if (bitVectBitValue(unused,i)) { + + /* if assigned to registers */ + if (bitVectBitValue(_G.regAssigned,i)) { + symbol *sym; + int j; + + sym = hTabItemWithKey(liveRanges,i); + /* remove it from regassigned & mark the + register free */ + bitVectUnSetBit(_G.regAssigned,i); + for (j = 0 ; j < sym->nRegs; j++) + freeReg(sym->regs[j]); + } else { + /* not assigned to registers : remove from set*/ + bitVectUnSetBit(unused,i); + } + } + } + } + return unused; +} + +/*-----------------------------------------------------------------*/ +/* reassignUnusedLRs - put registers to unused Live ranges */ +/*-----------------------------------------------------------------*/ +void reassignUnusedLRs (bitVect *unused) +{ + int i; + if (!unused) return ; + + for (i = 0 ; i < unused->size ; i++ ) { + /* if unused : means it was assigned to registers before */ + if (bitVectBitValue(unused,i)) { + symbol *sym; + int j; + + /* put it back into reg set*/ + bitVectSetBit(_G.regAssigned,i) ; + + sym = hTabItemWithKey(liveRanges,i); + /* makr registers busy */ + for (j = 0 ; j < sym->nRegs; j++) + sym->regs[j]->isFree = 0; + } + } +} + +/*------------------------------------------------------------------*/ +/* verifyRegsAssigned - make sure an iTemp is properly initialized; */ +/* it should either have registers or have beed spilled. Otherwise, */ +/* there was an uninitialized variable, so just spill this to get */ +/* the operand in a valid state. */ +/*------------------------------------------------------------------*/ +static void +verifyRegsAssigned (operand *op, iCode * ic) +{ + symbol * sym; + + if (!op) return; + if (!IS_ITEMP (op)) return; + + sym = OP_SYMBOL (op); + if (sym->isspilt) return; + if (!sym->nRegs) return; + if (sym->regs[0]) return; + + werrorfl (ic->filename, ic->lineno, W_LOCAL_NOINIT, + sym->prereqv ? sym->prereqv->name : sym->name); + spillThis (sym); +} + + /*-----------------------------------------------------------------*/ /* serialRegAssign - serially allocate registers to the variables */ /*-----------------------------------------------------------------*/ @@ -1141,15 +1251,18 @@ serialRegAssign (eBBlock ** ebbs, int count) /* for all blocks */ for (i = 0; i < count; i++) - { + { /* ebbs */ iCode *ic; + bitVect *unusedLRs = NULL; if (ebbs[i]->noPath && (ebbs[i]->entryLabel != entryLabel && ebbs[i]->entryLabel != returnLabel)) continue; - + + unusedLRs = deassignUnsedLRs(ebbs[i]); + /* of all instructions do */ for (ic = ebbs[i]->sch; ic; ic = ic->next) { @@ -1267,17 +1380,25 @@ serialRegAssign (eBBlock ** ebbs, int count) if (!sym->regs[j]) break; } - /* if it shares registers with operands make sure + + /* if it shares registers with operands make sure that they are in the same position */ - if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) && - OP_SYMBOL (IC_LEFT (ic))->nRegs && ic->op != '=') - positionRegs (OP_SYMBOL (IC_RESULT (ic)), - OP_SYMBOL (IC_LEFT (ic))); - /* do the same for the right operand */ - if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) && - OP_SYMBOL (IC_RIGHT (ic))->nRegs) - positionRegs (OP_SYMBOL (IC_RESULT (ic)), - OP_SYMBOL (IC_RIGHT (ic))); + if (!POINTER_SET(ic) && !POINTER_GET(ic)) + { + if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) && + OP_SYMBOL (IC_LEFT (ic))->nRegs) + { + positionRegs (OP_SYMBOL (IC_RESULT (ic)), + OP_SYMBOL (IC_LEFT (ic))); + } + /* do the same for the right operand */ + if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) && + OP_SYMBOL (IC_RIGHT (ic))->nRegs) + { + positionRegs (OP_SYMBOL (IC_RESULT (ic)), + OP_SYMBOL (IC_RIGHT (ic))); + } + } if (ptrRegSet) { @@ -1287,7 +1408,42 @@ serialRegAssign (eBBlock ** ebbs, int count) } } + reassignUnusedLRs(unusedLRs); } + + /* Check for and fix any problems with uninitialized operands */ + for (i = 0; i < count; i++) + { + iCode *ic; + + if (ebbs[i]->noPath && + (ebbs[i]->entryLabel != entryLabel && + ebbs[i]->entryLabel != returnLabel)) + continue; + + for (ic = ebbs[i]->sch; ic; ic = ic->next) + { + if (SKIP_IC2 (ic)) + continue; + + if (ic->op == IFX) + { + verifyRegsAssigned (IC_COND (ic), ic); + continue; + } + + if (ic->op == JUMPTABLE) + { + verifyRegsAssigned (IC_JTCOND (ic), ic); + continue; + } + + verifyRegsAssigned (IC_RESULT (ic), ic); + verifyRegsAssigned (IC_LEFT (ic), ic); + verifyRegsAssigned (IC_RIGHT (ic), ic); + } + } + } /*-----------------------------------------------------------------*/ @@ -1297,131 +1453,169 @@ static void fillGaps() { symbol *sym =NULL; int key =0; - + int loop = 0, change; + int pass; + if (getenv("DISABLE_FILL_GAPS")) return; /* First try to do DPTRuse once more since now we know what got into - registers */ - - for (sym = hTabFirstItem(liveRanges,&key) ; sym ; - sym = hTabNextItem(liveRanges,&key)) { - - if (sym->uptr && !sym->ruonly && getSize(sym->type) < 4) { - if (packRegsDPTRuse(operandFromSymbol(sym))) { - - D (fprintf (stderr, "FILL GAPS: found more DPTR use for " - "%s in func %s\n", - sym->name, currFunc ? currFunc->name : "UNKNOWN")); - /* if this was ssigned to registers then */ - if (bitVectBitValue(_G.totRegAssigned,sym->key)) { - - /* take it out of the register assigned set */ - bitVectUnSetBit(_G.totRegAssigned,sym->key); + registers */ + + while (loop++ < 10) { + change = 0; + + for (sym = hTabFirstItem(liveRanges,&key) ; sym ; + sym = hTabNextItem(liveRanges,&key)) { + int size = getSize(sym->type); + + if (sym->liveFrom == sym->liveTo) continue; + + if (sym->uptr && sym->dptr==0 && !sym->ruonly && + size < 4 && size > 1) { + + if (packRegsDPTRuse(operandFromSymbol(sym))) { + + /* if this was ssigned to registers then */ + if (bitVectBitValue(_G.totRegAssigned,sym->key)) { + /* take it out of the register assigned set */ + bitVectUnSetBit(_G.totRegAssigned,sym->key); + } else if (sym->usl.spillLoc) { + sym->usl.spillLoc->allocreq--; + sym->usl.spillLoc = NULL; + } + sym->nRegs = 0; - } else if (sym->usl.spillLoc) sym->usl.spillLoc->allocreq--; - - sym->isspilt = sym->spillA = 0; - } - } - } - - /* look for livernages that was spilt by the allocator */ - for (sym = hTabFirstItem(liveRanges,&key) ; sym ; - sym = hTabNextItem(liveRanges,&key)) { - - int i; - int pdone = 0; - - if (!sym->spillA || !sym->clashes || sym->remat) continue ; - - /* find the liveRanges this one clashes with, that are - still assigned to registers & mark the registers as used*/ - for ( i = 0 ; i < sym->clashes->size ; i ++) { - int k; - symbol *clr; - - if (bitVectBitValue(sym->clashes,i) == 0 || /* those that clash with this */ - bitVectBitValue(_G.totRegAssigned,i) == 0) /* and are still assigned to registers */ - continue ; - - assert (clr = hTabItemWithKey(liveRanges,i)); - - /* mark these registers as used */ - for (k = 0 ; k < clr->nRegs ; k++ ) - useReg(clr->regs[k]); - } - - if (willCauseSpill(sym->nRegs,sym->regType)) { - /* NOPE :( clear all registers & and continue */ - freeAllRegs(); - continue ; - } - - /* THERE IS HOPE !!!! */ - for (i=0; i < sym->nRegs ; i++ ) { - if (sym->regType == REG_PTR) - sym->regs[i] = getRegPtrNoSpil (); - else - sym->regs[i] = getRegGprNoSpil (); - } - - /* for all its definitions & uses check if the registers - allocated needs positioning NOTE: we can position - only ONCE if more than One positioning required - then give up */ - sym->isspilt = 0; - for (i = 0 ; i < sym->defs->size ; i++ ) { - if (bitVectBitValue(sym->defs,i)) { - iCode *ic; - if (!(ic = hTabItemWithKey(iCodehTab,i))) continue ; - if (SKIP_IC(ic)) continue; - assert(isSymbolEqual(sym,OP_SYMBOL(IC_RESULT(ic)))); /* just making sure */ - /* if left is assigned to registers */ - if (IS_SYMOP(IC_LEFT(ic)) && - bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_LEFT(ic))->key)) { - pdone += positionRegs(sym,OP_SYMBOL(IC_LEFT(ic))); + sym->isspilt = sym->spillA = 0; + continue ; } - if (IS_SYMOP(IC_RIGHT(ic)) && - bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RIGHT(ic))->key)) { - pdone += positionRegs(sym,OP_SYMBOL(IC_RIGHT(ic))); + + /* try assigning other dptrs */ + if (sym->dptr == 0 && packRegsDPTRnuse(operandFromSymbol(sym),1) && !getenv("DPTRnDISABLE")) { + /* if this was ssigned to registers then */ + if (bitVectBitValue(_G.totRegAssigned,sym->key)) { + /* take it out of the register assigned set */ + bitVectUnSetBit(_G.totRegAssigned,sym->key); + } else if (sym->usl.spillLoc) { + sym->usl.spillLoc->allocreq--; + sym->usl.spillLoc = NULL; + } + sym->nRegs = 0; + sym->isspilt = sym->spillA = 0; } - if (pdone > 1) break; } } - for (i = 0 ; i < sym->uses->size ; i++ ) { - if (bitVectBitValue(sym->uses,i)) { - iCode *ic; - if (!(ic = hTabItemWithKey(iCodehTab,i))) continue ; - if (SKIP_IC(ic)) continue; - if (!IS_ASSIGN_ICODE(ic)) continue ; - - /* if result is assigned to registers */ - if (IS_SYMOP(IC_RESULT(ic)) && - bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RESULT(ic))->key)) { - pdone += positionRegs(sym,OP_SYMBOL(IC_RESULT(ic))); - } - if (pdone > 1) break; + + /* look for livernages that was spilt by the allocator */ + for (sym = hTabFirstItem(liveRanges,&key) ; sym ; + sym = hTabNextItem(liveRanges,&key)) { + + int i; + int pdone = 0; + + if (!sym->spillA || !sym->clashes || sym->remat) continue ; + if (!sym->uses || !sym->defs) continue ; + /* find the liveRanges this one clashes with, that are + still assigned to registers & mark the registers as used*/ + for ( i = 0 ; i < sym->clashes->size ; i ++) { + int k; + symbol *clr; + + if (bitVectBitValue(sym->clashes,i) == 0 || /* those that clash with this */ + bitVectBitValue(_G.totRegAssigned,i) == 0) /* and are still assigned to registers */ + continue ; + + clr = hTabItemWithKey(liveRanges,i); + assert(clr); + + /* mark these registers as used */ + for (k = 0 ; k < clr->nRegs ; k++ ) + useReg(clr->regs[k]); } - } - /* had to position more than once GIVE UP */ - if (pdone > 1) { - /* UNDO all the changes we made to try this */ - sym->isspilt = 1; + + if (willCauseSpill(sym->nRegs,sym->regType)) { + /* NOPE :( clear all registers & and continue */ + freeAllRegs(); + continue ; + } + + /* THERE IS HOPE !!!! */ for (i=0; i < sym->nRegs ; i++ ) { - sym->regs[i] = NULL; + if (sym->regType == REG_PTR) + sym->regs[i] = getRegPtrNoSpil (); + else + sym->regs[i] = getRegGprNoSpil (); } - freeAllRegs(); - D (fprintf (stderr, "Fill Gap gave up due to positioning for " - "%s in function %s\n", + + /* For all its definitions check if the registers + allocated needs positioning NOTE: we can position + only ONCE if more than One positioning required + then give up. + We may need to perform the checks twice; once to + position the registers as needed, the second to + verify any register repositioning is still + compatible. + */ + sym->isspilt = 0; + for (pass=0; pass<2; pass++) { + for (i = 0 ; i < sym->defs->size ; i++ ) { + if (bitVectBitValue(sym->defs,i)) { + iCode *ic; + if (!(ic = hTabItemWithKey(iCodehTab,i))) continue ; + if (SKIP_IC(ic)) continue; + assert(isSymbolEqual(sym,OP_SYMBOL(IC_RESULT(ic)))); /* just making sure */ + /* if left is assigned to registers */ + if (IS_SYMOP(IC_LEFT(ic)) && + bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_LEFT(ic))->key)) { + pdone += (positionRegs(sym,OP_SYMBOL(IC_LEFT(ic)))>0); + } + if (IS_SYMOP(IC_RIGHT(ic)) && + bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RIGHT(ic))->key)) { + pdone += (positionRegs(sym,OP_SYMBOL(IC_RIGHT(ic)))>0); + } + if (pdone > 1) break; + } + } + for (i = 0 ; i < sym->uses->size ; i++ ) { + if (bitVectBitValue(sym->uses,i)) { + iCode *ic; + if (!(ic = hTabItemWithKey(iCodehTab,i))) continue ; + if (SKIP_IC(ic)) continue; + if (POINTER_SET(ic) || POINTER_GET(ic)) continue ; + + /* if result is assigned to registers */ + if (IS_SYMOP(IC_RESULT(ic)) && + bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RESULT(ic))->key)) { + pdone += (positionRegs(sym,OP_SYMBOL(IC_RESULT(ic)))>0); + } + if (pdone > 1) break; + } + } + if (pdone == 0) break; /* second pass only if regs repositioned */ + if (pdone > 1) break; + } + /* had to position more than once GIVE UP */ + if (pdone > 1) { + /* UNDO all the changes we made to try this */ + sym->isspilt = 1; + for (i=0; i < sym->nRegs ; i++ ) { + sym->regs[i] = NULL; + } + freeAllRegs(); + D (fprintf (stderr, "Fill Gap gave up due to positioning for " + "%s in function %s\n", + sym->name, currFunc ? currFunc->name : "UNKNOWN")); + continue ; + } + D (fprintf (stderr, "FILLED GAP for %s in function %s\n", sym->name, currFunc ? currFunc->name : "UNKNOWN")); - continue ; + _G.totRegAssigned = bitVectSetBit(_G.totRegAssigned,sym->key); + sym->isspilt = sym->spillA = 0 ; + sym->usl.spillLoc->allocreq--; + sym->usl.spillLoc = NULL; + freeAllRegs(); + change ++; } - D (fprintf (stderr, "FILLED GAP for %s in function %s\n", - sym->name, currFunc ? currFunc->name : "UNKNOWN")); - _G.totRegAssigned = bitVectSetBit(_G.totRegAssigned,sym->key); - sym->isspilt = sym->spillA = 0 ; - sym->usl.spillLoc->allocreq--; - freeAllRegs(); + if (!change) break; } } @@ -1554,7 +1748,7 @@ createRegMask (eBBlock ** ebbs, int count) "createRegMask cannot find live range"); exit (0); } - +#if 0 /* special case for ruonly */ if (sym->ruonly && sym->liveFrom != sym->liveTo) { int size = getSize(sym->type); @@ -1563,6 +1757,7 @@ createRegMask (eBBlock ** ebbs, int count) ic->rMask = bitVectSetBit (ic->rMask, j++); continue ; } +#endif /* if no register assigned to it */ if (!sym->nRegs || sym->isspilt) continue; @@ -1586,14 +1781,17 @@ rematStr (symbol * sym) char *s = buffer; iCode *ic = sym->rematiCode; + *s = 0; + while (1) { /* if plus or minus print the right hand side */ if (ic->op == '+' || ic->op == '-') { - sprintf (s, "0x%04x %c ", (int) operandLitValue (IC_RIGHT (ic)), - ic->op); + SNPRINTF (s, sizeof(buffer) - strlen(buffer), + "0x%04x %c ", (int) operandLitValue (IC_RIGHT (ic)), + ic->op); s += strlen (s); ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode; continue; @@ -1604,7 +1802,8 @@ rematStr (symbol * sym) continue; } /* we reached the end */ - sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname); + SNPRINTF (s, sizeof(buffer) - strlen(buffer), + "%s", OP_SYMBOL (IC_LEFT (ic))->rname); break; } @@ -1649,10 +1848,7 @@ regTypeNum () } /* if the symbol has only one definition & - that definition is a get_pointer and the - pointer we are getting is rematerializable and - in "data" space */ - + that definition is a get_pointer */ if (bitVectnBitsOn (sym->defs) == 1 && (ic = hTabItemWithKey (iCodehTab, bitVectFirstBit (sym->defs))) && @@ -1660,19 +1856,18 @@ regTypeNum () !sym->noSpilLoc && !IS_BITVAR (sym->etype)) { - - - /* if remat in data space */ - if (OP_SYMBOL (IC_LEFT (ic))->remat && + /* and that pointer is remat in data space */ + if (IS_SYMOP (IC_LEFT (ic)) && + OP_SYMBOL (IC_LEFT (ic))->remat && !IS_CAST_ICODE(OP_SYMBOL (IC_LEFT (ic))->rematiCode) && - DCL_TYPE (aggrToPtr (sym->type, FALSE)) == POINTER) + DCL_TYPE (aggrToPtr (operandType(IC_LEFT(ic)), FALSE)) == POINTER) { /* create a psuedo symbol & force a spil */ symbol *psym = newSymbol (rematStr (OP_SYMBOL (IC_LEFT (ic))), 1); psym->type = sym->type; psym->etype = sym->etype; - strcpy (psym->rname, psym->name); + strncpyz (psym->rname, psym->name, sizeof(psym->rname)); sym->isspilt = 1; sym->usl.spillLoc = psym; continue; @@ -1916,6 +2111,7 @@ pack: /* replace the result with the result of */ /* this assignment and remove this assignment */ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key); + IC_RESULT (dic) = IC_RESULT (ic); if (IS_ITEMP (IC_RESULT (dic)) && OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq) @@ -1935,7 +2131,7 @@ pack: remiCodeFromeBBlock (ebp, ic); bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key); hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL); - OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key); + OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key); return 1; } @@ -2022,8 +2218,9 @@ findAssignToSym (operand * op, iCode * ic) /*-----------------------------------------------------------------*/ static int packRegsForSupport (iCode * ic, eBBlock * ebp) -{ +{ int change = 0; + /* for the left & right operand :- look to see if the left was assigned a true symbol in far space in that case replace them */ @@ -2038,11 +2235,16 @@ packRegsForSupport (iCode * ic, eBBlock * ebp) /* found it we need to remove it from the block */ - for (sic = dic; sic != ic; sic = sic->next) + for (sic = dic; sic != ic; sic = sic->next) { bitVectUnSetBit (sic->rlive, IC_LEFT (ic)->key); + sic->rlive = bitVectSetBit (sic->rlive, IC_RIGHT (dic)->key); + } + wassert(IS_SYMOP(IC_LEFT (ic))); + wassert(IS_SYMOP(IC_RIGHT (dic))); IC_LEFT (ic)->operand.symOperand = IC_RIGHT (dic)->operand.symOperand; + OP_SYMBOL(IC_LEFT(ic))->liveTo = ic->seq; IC_LEFT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key; bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key); remiCodeFromeBBlock (ebp, dic); @@ -2072,13 +2274,17 @@ right: } /* found it we need to remove it from the block */ - for (sic = dic; sic != ic; sic = sic->next) + for (sic = dic; sic != ic; sic = sic->next) { bitVectUnSetBit (sic->rlive, IC_RIGHT (ic)->key); + sic->rlive = bitVectSetBit (sic->rlive, IC_RIGHT (dic)->key); + } + wassert(IS_SYMOP(IC_RIGHT (ic))); + wassert(IS_SYMOP(IC_RIGHT (dic))); IC_RIGHT (ic)->operand.symOperand = IC_RIGHT (dic)->operand.symOperand; IC_RIGHT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key; - + OP_SYMBOL(IC_RIGHT(ic))->liveTo = ic->seq; remiCodeFromeBBlock (ebp, dic); bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key); hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL); @@ -2091,6 +2297,130 @@ right: #define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly) +/*-----------------------------------------------------------------*/ +/* packRegsDPTRnuse - color live ranges that can go into extra DPTRS */ +/*-----------------------------------------------------------------*/ +static int packRegsDPTRnuse( operand *op , int dptr) +{ + int i,key; + iCode *ic; + + if (!IS_SYMOP(op) || !IS_ITEMP(op)) return 0; + if (OP_SYMBOL(op)->remat || OP_SYMBOL(op)->ruonly || OP_SYMBOL(op)->dptr) + return 0; + + /* first check if any overlapping liverange has already been + assigned to this DPTR */ + if (OP_SYMBOL(op)->clashes) { + for (i = 0 ; i < OP_SYMBOL(op)->clashes->size ; i++ ) { + symbol *sym; + if (bitVectBitValue(OP_SYMBOL(op)->clashes,i)) { + sym = hTabItemWithKey(liveRanges,i); + if (sym->dptr == dptr) return 0; + } + } + } + + /* future for more dptrs */ + if (dptr > 1) { + OP_SYMBOL(op)->dptr = dptr; + return 1; + } + + /* DPTR1 is special since it is also used as a scratch by the backend . + so we walk thru the entire live range of this operand and make sure + DPTR1 will not be used by the backed . The logic here is to find out if + more than one operand in an icode is in far space then we give up : we + don't keep it live across functions for now + */ + + ic = hTabFirstItemWK(iCodeSeqhTab,OP_SYMBOL(op)->liveFrom); + for (; ic && ic->seq <= OP_SYMBOL(op)->liveTo; + ic = hTabNextItem(iCodeSeqhTab,&key)) { + int nfs =0; + + if (ic->op == CALL || ic->op == PCALL) return 0; + + /* single operand icode are ok */ + if (ic->op == IFX || ic->op == IPUSH) + continue ; + + if (ic->op == SEND ) { + if (ic->argreg != 1 ) return 0; + else continue ; + } + /* two special cases first */ + if (POINTER_GET(ic) && !isOperandEqual(IC_LEFT(ic),op) && /* pointer get */ + !OP_SYMBOL(IC_LEFT(ic))->ruonly && /* with result in far space */ + (isOperandInFarSpace(IC_RESULT(ic)) && + !isOperandInReg(IC_RESULT(ic)))) { + return 0; + } + + if (POINTER_SET(ic) && !isOperandEqual(IC_RESULT(ic),op) && /* pointer set */ + !OP_SYMBOL(IC_RESULT(ic))->ruonly && /* with right in far space */ + (isOperandInFarSpace(IC_RIGHT(ic)) && + !isOperandInReg(IC_RIGHT(ic)))) { + return 0; + } + + if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) && /* if symbol operand */ + !isOperandEqual(IC_RESULT(ic),op) && /* not the same as this */ + ((isOperandInFarSpace(IC_RESULT(ic)) || /* in farspace or */ + OP_SYMBOL(IC_RESULT(ic))->onStack) && /* on the stack */ + !isOperandInReg(IC_RESULT(ic)))) { /* and not in register */ + nfs++; + } + /* same for left */ + if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) && /* if symbol operand */ + !isOperandEqual(IC_LEFT(ic),op) && /* not the same as this */ + ((isOperandInFarSpace(IC_LEFT(ic)) || /* in farspace or */ + OP_SYMBOL(IC_LEFT(ic))->onStack) && /* on the stack */ + !isOperandInReg(IC_LEFT(ic)))) { /* and not in register */ + nfs++; + } + /* same for right */ + if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) && /* if symbol operand */ + !isOperandEqual(IC_RIGHT(ic),op) && /* not the same as this */ + ((isOperandInFarSpace(IC_RIGHT(ic)) || /* in farspace or */ + OP_SYMBOL(IC_RIGHT(ic))->onStack) && /* on the stack */ + !isOperandInReg(IC_RIGHT(ic)))) { /* and not in register */ + nfs++; + } + + // Check that no other ops in this range have been assigned to dptr1. + // I don't understand why this is not caught by the first check, above. + // But it isn't always, see bug 769624. + if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) && + (OP_SYMBOL(IC_RESULT(ic))->dptr == 1)) + { + //fprintf(stderr, "dptr1 already in use in live range #1\n"); + return 0; + } + + if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) && + (OP_SYMBOL(IC_LEFT(ic))->dptr == 1)) + { + //fprintf(stderr, "dptr1 already in use in live range # 2\n"); + return 0; + } + + if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) && + (OP_SYMBOL(IC_RIGHT(ic))->dptr == 1)) + { + //fprintf(stderr, "dptr1 already in use in live range # 3\n"); + return 0; + } + + if (nfs && IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) && + OP_SYMBOL(IC_RESULT(ic))->ruonly) return 0; + + if (nfs > 1) return 0; + } + OP_SYMBOL(op)->dptr = dptr; + return 1; +} + /*-----------------------------------------------------------------*/ /* packRegsDPTRuse : - will reduce some registers for single Use */ /*-----------------------------------------------------------------*/ @@ -2130,15 +2460,19 @@ packRegsDPTRuse (operand * op) /* if PCALL cannot be sure give up */ if (ic->op == PCALL) return NULL; + /* if SEND & not the first parameter then giveup */ + if (ic->op == SEND && ic->argreg != 1 && + ((isOperandInFarSpace(IC_LEFT(ic)) && !isOperandInReg(IC_LEFT(ic))) || + isOperandEqual(op,IC_LEFT(ic)))) return NULL; + /* if CALL then make sure it is VOID || return value not used or the return value is assigned to this one */ if (ic->op == CALL) { if (OP_SYMBOL(IC_RESULT(ic))->liveTo == OP_SYMBOL(IC_RESULT(ic))->liveFrom) continue ; etype = getSpec(type = operandType(IC_RESULT(ic))); - //if (getSize(type) == 0 || isOperandEqual(op,IC_RESULT(ic))) - if (getSize(type) == 0) - continue ; + if (getSize(type) == 0 || isOperandEqual(op,IC_RESULT(ic))) + continue ; return NULL ; } @@ -2157,32 +2491,43 @@ packRegsDPTRuse (operand * op) if (POINTER_SET(ic) && !isOperandEqual(IC_RESULT(ic),op) && getSize(operandType(IC_RESULT(ic))) > 1 ) return NULL; - /* conditionals can destroy 'b' - make sure B wont be used in this one*/ - if ((IS_CONDITIONAL(ic) || ic->op == '*' || ic->op == '/' ) && + /* conditionals can destroy 'b' - make sure B wont + be used in this one*/ + if ((IS_CONDITIONAL(ic) || ic->op == '*' || ic->op == '/' || + ic->op == LEFT_OP || ic->op == RIGHT_OP ) && getSize(operandType(op)) > 3) return NULL; + /* if this is a cast to a bigger type */ + if (ic->op==CAST) { + if (!IS_PTR(OP_SYM_TYPE(IC_RESULT(ic))) && + getSize(OP_SYM_TYPE(IC_RESULT(ic))) > + getSize(OP_SYM_TYPE(IC_RIGHT(ic)))) { + return 0; + } + } + /* general case */ if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) && !isOperandEqual(IC_RESULT(ic),op) && - ((isOperandInFarSpace(IC_RESULT(ic)) && !isOperandInReg(IC_RESULT(ic))) || - OP_SYMBOL(IC_RESULT(ic))->ruonly || - OP_SYMBOL(IC_RESULT(ic))->onStack)) return NULL; + ( ( ( isOperandInFarSpace(IC_RESULT(ic)) || OP_SYMBOL(IC_RESULT(ic))->onStack) && + !isOperandInReg(IC_RESULT(ic))) || + OP_SYMBOL(IC_RESULT(ic))->ruonly)) return NULL; if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) && !isOperandEqual(IC_RIGHT(ic),op) && - (OP_SYMBOL(IC_RIGHT(ic))->liveTo > ic->seq || + (OP_SYMBOL(IC_RIGHT(ic))->liveTo >= ic->seq || IS_TRUE_SYMOP(IC_RIGHT(ic)) || OP_SYMBOL(IC_RIGHT(ic))->ruonly) && - ((isOperandInFarSpace(IC_RIGHT(ic)) && !isOperandInReg(IC_RIGHT(ic)))|| - OP_SYMBOL(IC_RIGHT(ic))->onStack)) return NULL; + ( ( isOperandInFarSpace(IC_RIGHT(ic)) || OP_SYMBOL(IC_RIGHT(ic))->onStack) && + !isOperandInReg(IC_RIGHT(ic))) ) return NULL; if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) && !isOperandEqual(IC_LEFT(ic),op) && - (OP_SYMBOL(IC_LEFT(ic))->liveTo > ic->seq || + (OP_SYMBOL(IC_LEFT(ic))->liveTo >= ic->seq || IS_TRUE_SYMOP(IC_LEFT(ic)) || OP_SYMBOL(IC_LEFT(ic))->ruonly) && - ((isOperandInFarSpace(IC_LEFT(ic)) && !isOperandInReg(IC_LEFT(ic)))|| - OP_SYMBOL(IC_LEFT(ic))->onStack)) return NULL; + ( ( isOperandInFarSpace(IC_LEFT(ic)) || OP_SYMBOL(IC_LEFT(ic))->onStack) && + !isOperandInReg(IC_LEFT(ic))) ) return NULL; if (IC_LEFT(ic) && IC_RIGHT(ic) && IS_ITEMP(IC_LEFT(ic)) && IS_ITEMP(IC_RIGHT(ic)) && @@ -2191,6 +2536,11 @@ packRegsDPTRuse (operand * op) return NULL; } OP_SYMBOL(op)->ruonly = 1; + if (OP_SYMBOL(op)->usl.spillLoc) { + if (OP_SYMBOL(op)->spillA) + OP_SYMBOL(op)->usl.spillLoc->allocreq--; + OP_SYMBOL(op)->usl.spillLoc = NULL; + } return dic; } @@ -2236,6 +2586,17 @@ packRegsForAccUse (iCode * ic) return; } + /* if we are calling a reentrant function that has stack parameters */ + if (ic->op == CALL && + IFFUNC_ISREENT(operandType(IC_LEFT(ic))) && + FUNC_HASSTACKPARM(operandType(IC_LEFT(ic)))) + return; + + if (ic->op == PCALL && + IFFUNC_ISREENT(operandType(IC_LEFT(ic))->next) && + FUNC_HASSTACKPARM(operandType(IC_LEFT(ic))->next)) + return; + /* if + or - then it has to be one byte result */ if ((ic->op == '+' || ic->op == '-') && getSize (operandType (IC_RESULT (ic))) > 1) @@ -2311,14 +2672,8 @@ packRegsForAccUse (iCode * ic) /* make sure that the result of this icode is not on the stack, since acc is used to compute stack offset */ -#if 0 - if (IS_TRUE_SYMOP (IC_RESULT (uic)) && - OP_SYMBOL (IC_RESULT (uic))->onStack) - return; -#else if (isOperandOnStack(IC_RESULT(uic))) return; -#endif /* if either one of them in far space then we cannot */ if ((IS_TRUE_SYMOP (IC_LEFT (uic)) && @@ -2338,19 +2693,6 @@ packRegsForAccUse (iCode * ic) IC_LEFT (uic)->key != IC_RESULT (ic)->key) return; -#if 0 - // this is too dangerous and need further restrictions - // see bug #447547 - - /* 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; - } -#endif - /* if the other one is not on stack then we can */ if (IC_LEFT (uic)->key == IC_RESULT (ic)->key && (IS_ITEMP (IC_RIGHT (uic)) || @@ -2381,7 +2723,7 @@ packForPush (iCode * ic, eBBlock * ebp) iCode *dic, *lic; bitVect *dbv; - if (ic->op != IPUSH || !IS_ITEMP (IC_LEFT (ic))) + if ((ic->op != IPUSH && ic->op != SEND) || !IS_ITEMP (IC_LEFT (ic))) return; /* must have only definition & one usage */ @@ -2396,6 +2738,8 @@ packForPush (iCode * ic, eBBlock * ebp) if (dic->op != '=' || POINTER_SET (dic)) return; + + if (dic->eBBlockNum != ic->eBBlockNum) return ; /* make sure the right side does not have any definitions inbetween */ @@ -2404,6 +2748,7 @@ packForPush (iCode * ic, eBBlock * ebp) if (bitVectBitValue(dbv,lic->key)) return ; } /* make sure they have the same type */ + if (IS_SPEC(operandType(IC_LEFT(ic)))) { sym_link *itype=operandType(IC_LEFT(ic)); sym_link *ditype=operandType(IC_RIGHT(dic)); @@ -2413,9 +2758,18 @@ packForPush (iCode * ic, eBBlock * ebp) return; } /* extend the live range of replaced operand if needed */ - if (OP_SYMBOL(IC_RIGHT(dic))->liveTo < ic->seq) { - OP_SYMBOL(IC_RIGHT(dic))->liveTo = ic->seq; + if (OP_SYMBOL(IC_RIGHT(dic))->liveTo < OP_SYMBOL(IC_LEFT(ic))->liveTo) { + OP_SYMBOL(IC_RIGHT(dic))->liveTo = OP_SYMBOL(IC_LEFT(ic))->liveTo; + OP_SYMBOL(IC_RIGHT(dic))->clashes = + bitVectUnion(OP_SYMBOL(IC_RIGHT(dic))->clashes, + OP_SYMBOL(IC_LEFT(ic))->clashes); } + for (lic = ic; lic && lic != dic; lic = lic->prev) + { + bitVectUnSetBit (lic->rlive, IC_LEFT (ic)->key); + if (IS_ITEMP (IC_RIGHT (dic))) + bitVectSetBit (lic->rlive, IC_RIGHT (dic)->key); + } /* we now we know that it has one & only one def & use and the that the definition is an assignment */ IC_LEFT (ic) = IC_RIGHT (dic); @@ -2475,6 +2829,18 @@ packRegisters (eBBlock * ebp) } + /* if this is an itemp & used as a pointer + & assigned to a literal then remat */ + if (IS_ASSIGN_ICODE(ic) && + IS_ITEMP(IC_RESULT(ic)) && + bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 && + isOperandLiteral(IC_RIGHT(ic))) + { + OP_SYMBOL (IC_RESULT (ic))->remat = 1; + OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic; + OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL; + } + /* if straight assignment then carry remat flag if this is the only definition */ if (ic->op == '=' && @@ -2495,6 +2861,7 @@ packRegisters (eBBlock * ebp) cast is remat, then we can remat this cast as well */ if (ic->op == CAST && IS_SYMOP(IC_RIGHT(ic)) && + !OP_SYMBOL(IC_RESULT(ic))->isreqv && OP_SYMBOL(IC_RIGHT(ic))->remat ) { sym_link *to_type = operandType(IC_LEFT(ic)); sym_link *from_type = operandType(IC_RIGHT(ic)); @@ -2523,54 +2890,57 @@ packRegisters (eBBlock * ebp) } /* mark the pointer usages */ - if (POINTER_SET (ic)) + if (POINTER_SET (ic) && IS_SYMOP (IC_RESULT (ic))) OP_SYMBOL (IC_RESULT (ic))->uptr = 1; - if (POINTER_GET (ic)) + if (POINTER_GET (ic) && IS_SYMOP (IC_LEFT (ic))) OP_SYMBOL (IC_LEFT (ic))->uptr = 1; if (ic->op == RETURN && IS_SYMOP (IC_LEFT(ic))) OP_SYMBOL (IC_LEFT (ic))->uptr = 1; + if (ic->op == RECEIVE && ic->argreg == 1 && + IS_SYMOP (IC_RESULT (ic)) && + getSize (operandType(IC_RESULT(ic))) <= 3) + OP_SYMBOL (IC_RESULT(ic))->uptr = 1; + + if (ic->op == SEND && ic->argreg == 1 && + IS_SYMOP(IC_LEFT(ic)) && + getSize (aggrToPtr(operandType(IC_LEFT(ic)),FALSE)) <= 3) + OP_SYMBOL (IC_LEFT(ic))->uptr = 1; + if (!SKIP_IC2 (ic)) { /* if we are using a symbol on the stack then we should say ds390_ptrRegReq */ + if (options.useXstack && ic->parmPush + && (ic->op == IPUSH || ic->op == IPOP)) + ds390_ptrRegReq++; if (ic->op == IFX && IS_SYMOP (IC_COND (ic))) ds390_ptrRegReq += ((OP_SYMBOL (IC_COND (ic))->onStack ? !options.stack10bit : 0) + - OP_SYMBOL (IC_COND (ic))->iaccess); + OP_SYMBOL (IC_COND (ic))->iaccess + + (SPEC_OCLS(OP_SYMBOL (IC_COND (ic))->etype) == idata)); else if (ic->op == JUMPTABLE && IS_SYMOP (IC_JTCOND (ic))) ds390_ptrRegReq += ((OP_SYMBOL (IC_JTCOND (ic))->onStack ? !options.stack10bit : 0) + - OP_SYMBOL (IC_JTCOND (ic))->iaccess); + OP_SYMBOL (IC_JTCOND (ic))->iaccess + + (SPEC_OCLS(OP_SYMBOL (IC_JTCOND (ic))->etype) == idata)); else { if (IS_SYMOP (IC_LEFT (ic))) ds390_ptrRegReq += ((OP_SYMBOL (IC_LEFT (ic))->onStack ? !options.stack10bit : 0) + - OP_SYMBOL (IC_LEFT (ic))->iaccess); + OP_SYMBOL (IC_LEFT (ic))->iaccess + + (SPEC_OCLS(OP_SYMBOL (IC_LEFT (ic))->etype) == idata)); if (IS_SYMOP (IC_RIGHT (ic))) ds390_ptrRegReq += ((OP_SYMBOL (IC_RIGHT (ic))->onStack ? !options.stack10bit : 0) + - OP_SYMBOL (IC_RIGHT (ic))->iaccess); + OP_SYMBOL (IC_RIGHT (ic))->iaccess + + (SPEC_OCLS(OP_SYMBOL (IC_RIGHT (ic))->etype) == idata)); if (IS_SYMOP (IC_RESULT (ic))) ds390_ptrRegReq += ((OP_SYMBOL (IC_RESULT (ic))->onStack ? !options.stack10bit : 0) + - OP_SYMBOL (IC_RESULT (ic))->iaccess); + OP_SYMBOL (IC_RESULT (ic))->iaccess + + (SPEC_OCLS(OP_SYMBOL (IC_RESULT (ic))->etype) == idata)); } } -#if 0 - /* if the condition of an if instruction - is defined in the previous instruction then - mark the itemp as a conditional */ - if ((IS_CONDITIONAL (ic) || - (IS_BITWISE_OP(ic) && isBitwiseOptimizable(ic))) && - ic->next && ic->next->op == IFX && - isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) && - OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq) - { - - OP_SYMBOL (IC_RESULT (ic))->regType = REG_CND; - continue; - } -#else /* if the condition of an if instruction is defined in the previous instruction and this is the only usage then @@ -2585,29 +2955,34 @@ packRegisters (eBBlock * ebp) OP_SYMBOL (IC_RESULT (ic))->regType = REG_CND; continue; } -#endif - +#if 1 /* reduce for support function calls */ if (ic->supportRtn || ic->op == '+' || ic->op == '-') packRegsForSupport (ic, ebp); - +#endif /* some cases the redundant moves can - can be eliminated for return statements */ - if ((ic->op == RETURN || ic->op == SEND) && + can be eliminated for return statements . Can be elminated for the first SEND */ + if ((ic->op == RETURN || + ((ic->op == SEND || ic->op == RECEIVE)&& ic->argreg == 1)) && !isOperandInFarSpace (IC_LEFT (ic)) && !options.model) { packRegsDPTRuse (IC_LEFT (ic)); } - if ((ic->op == CALL && getSize(operandType(IC_RESULT(ic))) <= 4)) { - packRegsDPTRuse (IC_RESULT (ic)); + if (ic->op == CALL) { + sym_link *ftype = operandType(IC_LEFT(ic)); + if (getSize(operandType(IC_RESULT(ic))) <= 4 && + !IFFUNC_ISBUILTIN(ftype)) { + packRegsDPTRuse (IC_RESULT (ic)); + } } /* if pointer set & left has a size more than one and right is not in far space */ if (POINTER_SET (ic) && !isOperandInFarSpace (IC_RIGHT (ic)) && + IS_SYMOP (IC_RESULT (ic)) && !OP_SYMBOL (IC_RESULT (ic))->remat && !IS_OP_RUONLY (IC_RIGHT (ic)) && getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1) { @@ -2618,6 +2993,7 @@ packRegisters (eBBlock * ebp) /* if pointer get */ if (POINTER_GET (ic) && !isOperandInFarSpace (IC_RESULT (ic)) && + IS_SYMOP (IC_LEFT (ic)) && !OP_SYMBOL (IC_LEFT (ic))->remat && !IS_OP_RUONLY (IC_RESULT (ic)) && getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1) { @@ -2650,7 +3026,7 @@ packRegisters (eBBlock * ebp) remiCodeFromeBBlock (ebp, ic); bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key); hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL); - OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key); + OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key); ic = ic->prev; } else @@ -2673,7 +3049,7 @@ packRegisters (eBBlock * ebp) remiCodeFromeBBlock (ebp, ic); bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key); hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL); - OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key); + OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key); ic = ic->prev; } } @@ -2686,7 +3062,7 @@ packRegisters (eBBlock * ebp) ------------- push V1 */ - if (ic->op == IPUSH) + if (ic->op == IPUSH || ic->op == SEND) { packForPush (ic, ebp); } @@ -2703,7 +3079,7 @@ packRegisters (eBBlock * ebp) if ((IS_ARITHMETIC_OP (ic) || IS_CONDITIONAL(ic) || IS_BITWISE_OP (ic) - || ic->op == LEFT_OP || ic->op == RIGHT_OP || ic->op == CALL + || ic->op == LEFT_OP || ic->op == RIGHT_OP || (ic->op == ADDRESS_OF && isOperandOnStack (IC_LEFT (ic))) ) && IS_ITEMP (IC_RESULT (ic)) && @@ -2735,6 +3111,10 @@ ds390_assignRegisters (eBBlock ** ebbs, int count) for (i = 0; i < count; i++) packRegisters (ebbs[i]); + /* liveranges probably changed by register packing + so we compute them again */ + recomputeLiveRanges (ebbs, count); + if (options.dump_pack) dumpEbbsToFileExt (DUMP_PACK, ebbs, count); @@ -2770,8 +3150,17 @@ ds390_assignRegisters (eBBlock ** ebbs, int count) createRegMask (ebbs, count); /* redo that offsets for stacked automatic variables */ - redoStackOffsets (); + if (currFunc) + redoStackOffsets (); + /* make sure r0 & r1 are flagged as used if they might be used */ + /* as pointers */ + if (currFunc && ds390_ptrRegReq) + { + currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, R0_IDX); + currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, R1_IDX); + } + if (options.dump_rassgn) { dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count); dumpLiveRanges (DUMP_LRANGE, liveRanges); @@ -2789,8 +3178,8 @@ ds390_assignRegisters (eBBlock ** ebbs, int count) /* free up any _G.stackSpil locations allocated */ applyToSet (_G.stackSpil, deallocStackSpil); _G.slocNum = 0; - setToNull ((void **) &_G.stackSpil); - setToNull ((void **) &_G.spiltSet); + setToNull ((void *) &_G.stackSpil); + setToNull ((void *) &_G.spiltSet); /* mark all registers as free */ ds390_nRegs = 8; freeAllRegs ();