X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fpic16%2Fpcoderegs.c;h=1de9fbe1b0c8b35e7b4cae7be11711a1a00e5e06;hb=259fb25d65ee3cd76034fce37e3e8cbffb2aa566;hp=844c83363e4b020e15df9c9d3c39a504138bf92f;hpb=a2780cc9b0d0dc70f15a78a441258193d1422594;p=fw%2Fsdcc diff --git a/src/pic16/pcoderegs.c b/src/pic16/pcoderegs.c index 844c8336..1de9fbe1 100644 --- a/src/pic16/pcoderegs.c +++ b/src/pic16/pcoderegs.c @@ -37,6 +37,11 @@ #include "pcoderegs.h" #include "pcodeflow.h" + +#define DEBUG_REMOVE1PCODE 0 +#define HAVE_DBGREGUSAGE 0 + + extern void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2); extern pCode * pic16_findPrevInstruction(pCode *pci); extern pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n); @@ -66,7 +71,8 @@ void AddRegToFlow(regs *reg, pCodeFlow *pcfl) /*-----------------------------------------------------------------* * *-----------------------------------------------------------------*/ -#if 0 + +#if HAVE_DBGREGUSAGE static void dbg_regusage(set *fregs) { regs *reg; @@ -119,13 +125,13 @@ static void dbg_regusage(set *fregs) } } } -#endif /*-----------------------------------------------------------------* * *-----------------------------------------------------------------*/ -#if 0 -static void dbg_dumpregusage(void) + +//static +void dbg_dumpregusage(void) { fprintf(stderr,"*** Register Usage ***\n"); @@ -168,6 +174,7 @@ static void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl) reg = pic16_getRegFromInstruction(pc); if(reg && (reg->type != REG_TMP)) { + #if 0 fprintf(stderr, "reg= %p\n", reg); fprintf(stderr, "flow seq %d, inst seq %d %s ",PCODE(pcfl)->seq,pc->seq,reg->name); @@ -186,7 +193,9 @@ static void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl) if(PCC_REGISTER & PCI(pc)->outCond) addSetIfnotP(& (reg->reglives.assignedpFlows), pcfl); - addSetIfnotP(& (reg->reglives.usedpCodes), pc); + addSetIfnotP(& (reg->reglives.usedpCodes), pc); + +// reg->wasUsed=1; #if 1 /* check to see if this pCode has 2 memory operands, @@ -204,6 +213,8 @@ static void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl) addSetIfnotP(& (reg->reglives.assignedpFlows), pcfl); addSetIfnotP(& (reg->reglives.usedpCodes), pc); + +// reg->wasUsed=1; } } #endif @@ -253,7 +264,9 @@ void pic16_pCodeRegMapLiveRanges(pBlock *pb) } #endif -// dbg_dumpregusage(); +#if HAVE_DBGREGUSAGE + dbg_dumpregusage(); +#endif } @@ -270,7 +283,7 @@ static void Remove1pcode(pCode *pc, regs *reg) deleteSetItem (&(reg->reglives.usedpCodes),pc); -#if 0 +#if DEBUG_REMOVE1PCODE fprintf(stderr,"removing instruction:\n"); pc->print(stderr,pc); #endif @@ -288,8 +301,12 @@ static void Remove1pcode(pCode *pc, regs *reg) if(pcn) { if(PCI(pcn)->cline) { - //fprintf(stderr, "source line has been optimized completely out\n"); - //pc->print(stderr,pc); + +#if DEBUG_REMOVE1PCODE + fprintf(stderr, "source line has been optimized completely out\n"); + pc->print(stderr,pc); +#endif + } else { PCI(pcn)->cline = PCI(pc)->cline; } @@ -321,7 +338,7 @@ static void RemoveRegsFromSet(set *regset) if(used == 0) { -// fprintf(stderr,"%s:%d: getting rid of reg %s\n",__FILE__, __LINE__, reg->name); +// fprintf(stderr,"%s:%d: getting rid of reg %s\n",__FILE__, __LINE__, reg->name); reg->isFree = 1; reg->wasUsed = 0; @@ -358,9 +375,6 @@ static void RemoveRegsFromSet(set *regset) fprintf(stderr,"reg %s, type =%d\n",r->name, r->type); } - fprintf(stderr,"%s:%d: removing reg %s because it is used only once\n",__FILE__, __LINE__, reg->name); - - Remove1pcode(pc, reg); /* pic16_unlinkpCode(pc); @@ -396,6 +410,68 @@ void pic16_RemoveUnusedRegisters(void) fprintf(stderr, " *** Saved %d registers ***\n", total_registers_saved); } +static int insideLRBlock(pCode *pc) +{ + pCode *pc1; + int t1=-1, t2=-1; + + pc1 = pc->prev; + while(pc1) { + if(isPCINFO(pc1) && (PCINF(pc1)->type == INF_LOCALREGS)) { + t1 = PCOLR (PCINF (pc1)->oper1)->type; + break; + } + pc1 = pc1->prev; + } + + pc1 = pc->next; + while(pc1) { + if(isPCINFO(pc1) && (PCINF(pc1)->type == INF_LOCALREGS)) { + t2 = PCOLR (PCINF (pc1)->oper1)->type; + break; + } + pc1 = pc1->next; + } + + if((t1 == LR_ENTRY_BEGIN && t2 == LR_ENTRY_END) + || (t1 == LR_EXIT_BEGIN && t2 == LR_EXIT_END)) + return 1; + + return 0; +} + + +static void RemoveRegFromLRBlock(regs *reg) +{ + if(elementsInSet(reg->reglives.usedpCodes) == 2) { + pCode *pc1; + + /* only continue if there are just 2 uses of the register, + * in in the local *entry* block and one in the local *exit* block */ + + /* search for entry block */ + pc1 = indexSet(reg->reglives.usedpCodes, 1); + + if(insideLRBlock( pc1 )) { + fprintf(stderr, "usedpCodes[0] inside LR block\n"); + deleteSetItem(&pc1->pb->tregisters, PCOR(PCI(pc1)->pcop)->r); + Remove1pcode(pc1, reg); + } + + pc1 = indexSet(reg->reglives.usedpCodes, 0); + if(insideLRBlock( pc1 )) { + fprintf(stderr, "usedpCodes[1] inside LR block\n"); + deleteSetItem(&pc1->pb->tregisters, PCOR(PCI(pc1)->pcop)->r); + Remove1pcode(pc1, reg); + } + + /* remove r0x00 */ + reg->isFree = 1; + reg->wasUsed = 0; + } +} + + /*-----------------------------------------------------------------* * @@ -426,12 +502,20 @@ static void Remove2pcodes(pCode *pcflow, pCode *pc1, pCode *pc2, regs *reg, int } pCodeRegMapLiveRangesInFlow(PCFL(pcflow)); + +#if 1 +// fprintf(stderr, "register %s is used in %d pCodes, assigned in %d pCodes\n", reg->name, +// elementsInSet(reg->reglives.usedpCodes), +// elementsInSet(reg->reglives.assignedpFlows)); + + RemoveRegFromLRBlock(reg); +#endif + } /*-----------------------------------------------------------------* * *-----------------------------------------------------------------*/ -#if 0 static int regUsedinRange(pCode *pc1, pCode *pc2, regs *reg) { int i=0; @@ -443,6 +527,13 @@ static int regUsedinRange(pCode *pc1, pCode *pc2, regs *reg) return 1; } + if(PCI(pc1)->is2MemOp) { + testreg = pic16_getRegFromInstruction2(pc1); + if(testreg && (testreg->rIdx == reg->rIdx)) { + return 1; + } + } + pc1 = pic16_findNextInstruction(pc1->next); } while (pc1 && (pc1 != pc2) && (i++ < 100)) ; @@ -466,15 +557,13 @@ static int regUsedinRange(pCode *pc1, pCode *pc2, regs *reg) *-----------------------------------------------------------------*/ static int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *reg, int can_free, int optimize_level) { - // pc1 and pc2 have to given in execution order -- this not guaranteed. - // The check on pcX->seq does not help much as (nearly) all seq's are - // zero at the moment... - pCode *pct1, *pct2; regs *reg1, *reg2; int t = total_registers_saved; + if(reg->type == REG_SFR)return 0; + if(pc2->seq < pc1->seq) { pct1 = pc2; pc2 = pc1; @@ -513,7 +602,27 @@ static int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *re PCI(newpc)->pcflow = PCFL(pcfl_used); newpc->seq = pc2->seq; - Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free); + /* take care if register is used after pc2, if yes, then don't delete + * clrf reg, because, reg should be initialized with zero */ + { + pCode *spc; + int maxSeq=0; + + for(spc=setFirstItem(reg->reglives.usedpCodes);spc;spc=setNextItem(reg->reglives.usedpCodes)) { + if(maxSeq < spc->seq)maxSeq = spc->seq; + } + +// fprintf(stderr, "pc1->seq = %d\tpc2->seq = %d\tspc->seq = %d\n", pc1->seq, pc2->seq, maxSeq); + + if(maxSeq > pc2->seq) { + /* this means that a pCode uses register after pc2, then + * we can't delete pc1 pCode */ + Remove2pcodes(pcfl_used, NULL, pc2, reg, can_free); + } else { + /* we can remove both pCodes */ + Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free); + } + } total_registers_saved++; // debugging stats. } else if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_IORFW) ){ @@ -574,19 +683,19 @@ static int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *re if(usesW(pct3)) ; // Remove2pcodes(pcfl_used, pc1, NULL, reg, can_free); - else + else { Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free); - - total_registers_saved++; // debugging stats. - return 1; - } else { - //fprintf(stderr,"didn't optimize because Z bit is used\n"); - } + total_registers_saved++; // debugging stats. + return 1; + } + } else { +// fprintf(stderr,"didn't optimize because Z bit is used\n"); + } } #if 0 fprintf(stderr, " couldn't optimize\n"); if(reg2) - fprintf(stderr, " %s is used in range\n",reg2->name); + fprintf(stderr, " %s is used in range\n", reg2->name); else fprintf(stderr, " reg2 is NULL\n"); #endif @@ -601,10 +710,11 @@ static int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *re reg1 = pic16_getRegFromInstruction(pct1); if(reg1 && !regUsedinRange(pc1,pc2,reg1)) { - /* + +#if 0 fprintf(stderr, " MOVF/MOVFW. \n"); fprintf(stderr, " ...optimizing\n"); - */ +#endif /* Change: @@ -670,14 +780,6 @@ static int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *re return (total_registers_saved != t); } -#else - -static int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *reg, int can_free, int optimize_level) -{ - return 0; -} - -#endif /*-----------------------------------------------------------------* * void pCodeRegOptimeRegUsage(pBlock *pb) @@ -735,7 +837,7 @@ static void OptimizeRegUsage(set *fregs, int optimize_multi_uses, int optimize_l */ //fprintf(stderr," used only twice\n"); - if(pcfl_used->seq == pcfl_assigned->seq) { + if(pcfl_used->seq == pcfl_assigned->seq && !(setNextItem(reg->reglives.usedpFlows)) && !(setNextItem(reg->reglives.assignedpFlows))) { //fprintf(stderr, " and used in same flow\n"); @@ -838,41 +940,44 @@ void pic16_pCodeRegOptimizeRegUsage(int level) int saved = 0; int t = total_registers_saved; - if(!register_optimization) - return; -#define OPT_PASSES 4 - passes = OPT_PASSES; + if(getenv("NO_REG_OPT")) + return; - do { - saved = total_registers_saved; + if(!register_optimization) + return; - /* Identify registers used in one flow sequence */ - OptimizeRegUsage(pic16_dynAllocRegs,level, (OPT_PASSES-passes)); - OptimizeRegUsage(pic16_dynStackRegs,level, (OPT_PASSES-passes)); - OptimizeRegUsage(pic16_dynDirectRegs,0, (OPT_PASSES-passes)); +#define OPT_PASSES 8 + passes = OPT_PASSES; - if((total_registers_saved != saved) - && (pic16_pcode_verbose)) - fprintf(stderr, " *** pass %d, Saved %d registers, total saved %d ***\n", - (1+OPT_PASSES-passes),total_registers_saved-saved,total_registers_saved); - - passes--; + do { + saved = total_registers_saved; + + /* Identify registers used in one flow sequence */ + OptimizeRegUsage(pic16_dynAllocRegs,level, (OPT_PASSES-passes)); + OptimizeRegUsage(pic16_dynStackRegs,level, (OPT_PASSES-passes)); + OptimizeRegUsage(pic16_dynDirectRegs,0, (OPT_PASSES-passes)); - } while( passes && ((total_registers_saved != saved) || (passes==OPT_PASSES-1)) ); + if((total_registers_saved != saved) + && (pic16_pcode_verbose)) + fprintf(stderr, " *** pass %d, Saved %d registers, total saved %d ***\n", + (1+OPT_PASSES-passes),total_registers_saved-saved,total_registers_saved); + + passes--; - if(total_registers_saved == t) + } while( passes && ((total_registers_saved != saved) || (passes==OPT_PASSES-1)) ); - if(pic16_debug_verbose) - fprintf(stderr, "No registers saved on this pass\n"); + if(total_registers_saved == t) + if(pic16_debug_verbose) + fprintf(stderr, "No registers saved on this pass\n"); #if 0 - fprintf(stderr,"dynamically allocated regs:\n"); - dbg_regusage(pic16_dynAllocRegs); - fprintf(stderr,"stack regs:\n"); - dbg_regusage(pic16_dynStackRegs); - fprintf(stderr,"direct regs:\n"); - dbg_regusage(pic16_dynDirectRegs); + fprintf(stderr,"dynamically allocated regs:\n"); + dbg_regusage(pic16_dynAllocRegs); + fprintf(stderr,"stack regs:\n"); + dbg_regusage(pic16_dynStackRegs); + fprintf(stderr,"direct regs:\n"); + dbg_regusage(pic16_dynDirectRegs); #endif } @@ -888,7 +993,6 @@ static void RegsSetUnMapLiveRanges(set *regset) while(regset) { reg = regset->item; regset = regset->next; - deleteSet(®->reglives.usedpCodes); deleteSet(®->reglives.usedpFlows); @@ -900,12 +1004,10 @@ static void RegsSetUnMapLiveRanges(set *regset) void pic16_RegsUnMapLiveRanges(void) { - RegsSetUnMapLiveRanges(pic16_dynAllocRegs); RegsSetUnMapLiveRanges(pic16_dynStackRegs); RegsSetUnMapLiveRanges(pic16_dynDirectRegs); RegsSetUnMapLiveRanges(pic16_dynProcessorRegs); RegsSetUnMapLiveRanges(pic16_dynDirectBitRegs); RegsSetUnMapLiveRanges(pic16_dynInternalRegs); - }