X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fpic16%2Fpcoderegs.c;h=1de9fbe1b0c8b35e7b4cae7be11711a1a00e5e06;hb=6cb515b98c5977589446a39a6271958383d0a3da;hp=26ed6cdb4a54d3eda5307d04174b3a4ca50bd51e;hpb=437d64783e5a2f4a6cb2f096627d57f5a9fa734f;p=fw%2Fsdcc diff --git a/src/pic16/pcoderegs.c b/src/pic16/pcoderegs.c index 26ed6cdb..1de9fbe1 100644 --- a/src/pic16/pcoderegs.c +++ b/src/pic16/pcoderegs.c @@ -1,6 +1,6 @@ /*------------------------------------------------------------------------- - pcoderegs.c - post code generation register optimizations + pcoderegs.c - post code generation register optimizations Written By - Scott Dattalo scott@dattalo.com Ported To PIC16 By - m.dubuc@rogers.com @@ -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,6 +71,8 @@ void AddRegToFlow(regs *reg, pCodeFlow *pcfl) /*-----------------------------------------------------------------* * *-----------------------------------------------------------------*/ + +#if HAVE_DBGREGUSAGE static void dbg_regusage(set *fregs) { regs *reg; @@ -122,7 +129,9 @@ static void dbg_regusage(set *fregs) /*-----------------------------------------------------------------* * *-----------------------------------------------------------------*/ -static void dbg_dumpregusage(void) + +//static +void dbg_dumpregusage(void) { fprintf(stderr,"*** Register Usage ***\n"); @@ -140,7 +149,7 @@ static void dbg_dumpregusage(void) dbg_regusage(pic16_dynProcessorRegs); } - +#endif /*-----------------------------------------------------------------* * void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl) @@ -164,13 +173,18 @@ static void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl) reg = pic16_getRegFromInstruction(pc); - if(reg) { -/* + 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); - fprintf(stderr, "addr = 0x%03x, type = %d rIdx=0x%03x\n", - reg->address,reg->type,reg->rIdx); -*/ + fprintf(stderr, "addr = 0x%03x, type = %d rIdx=0x%03x ", + reg->address,reg->type,reg->rIdx); + fprintf(stderr, "command = %s\n", PCI(pc)->mnemonic); + +#endif +// fprintf(stderr, "%s:%d: trying to get first operand from pCode reg= %s\n", __FILE__, __LINE__, reg->name); addSetIfnotP(& (PCFL(pcfl)->registers), reg); if((PCC_REGISTER | PCC_LITERAL) & PCI(pc)->inCond) @@ -179,7 +193,32 @@ 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, + and set up the second operand too */ + if(PCI(pc)->is2MemOp) { + reg = pic16_getRegFromInstruction2(pc); + if(reg) { +// fprintf(stderr, "%s:%d: trying to get second operand from pCode reg= %s\n", __FILE__, __LINE__, reg->name); + addSetIfnotP(& (PCFL(pcfl)->registers), reg); + + if((PCC_REGISTER | PCC_LITERAL) & PCI(pc)->inCond) + addSetIfnotP(& (reg->reglives.usedpFlows), pcfl); + + if((PCC_REGISTER | PCC_REGISTER2) & PCI(pc)->outCond) + addSetIfnotP(& (reg->reglives.assignedpFlows), pcfl); + + addSetIfnotP(& (reg->reglives.usedpCodes), pc); + +// reg->wasUsed=1; + } + } +#endif + } @@ -225,7 +264,9 @@ void pic16_pCodeRegMapLiveRanges(pBlock *pb) } #endif -// dbg_dumpregusage(); +#if HAVE_DBGREGUSAGE + dbg_dumpregusage(); +#endif } @@ -241,10 +282,12 @@ static void Remove1pcode(pCode *pc, regs *reg) return; deleteSetItem (&(reg->reglives.usedpCodes),pc); -/* + +#if DEBUG_REMOVE1PCODE fprintf(stderr,"removing instruction:\n"); pc->print(stderr,pc); -*/ +#endif + if(PCI(pc)->label) { pcn = pic16_findNextInstruction(pc->next); @@ -258,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; } @@ -287,9 +334,12 @@ static void RemoveRegsFromSet(set *regset) if(used <= 1) { - //fprintf(stderr," reg %s isfree=%d, wasused=%d\n",reg->name,reg->isFree,reg->wasUsed); +// fprintf(stderr," reg %s isfree=%d, wasused=%d\n",reg->name,reg->isFree,reg->wasUsed); + if(used == 0) { - //fprintf(stderr," getting rid of reg %s\n",reg->name); + +// fprintf(stderr,"%s:%d: getting rid of reg %s\n",__FILE__, __LINE__, reg->name); + reg->isFree = 1; reg->wasUsed = 0; } else { @@ -299,11 +349,10 @@ static void RemoveRegsFromSet(set *regset) pc = setFirstItem(reg->reglives.usedpCodes); if(reg->type == REG_SFR) { - //fprintf(stderr, "not removing SFR reg %s even though used only once\n",reg->name); + fprintf(stderr, "not removing SFR reg %s even though used only once\n", reg->name); continue; } - if(isPCI(pc)) { if(PCI(pc)->label) { pCode *pcn = pic16_findNextInstruction(pc->next); @@ -325,7 +374,7 @@ static void RemoveRegsFromSet(set *regset) pc->print(stderr,pc); fprintf(stderr,"reg %s, type =%d\n",r->name, r->type); } - //fprintf(stderr," removing reg %s because it is used only once\n",reg->name); + Remove1pcode(pc, reg); /* pic16_unlinkpCode(pc); @@ -357,9 +406,72 @@ void pic16_RemoveUnusedRegisters(void) */ RemoveRegsFromSet(pic16_dynDirectBitRegs); - if(total_registers_saved) fprintf(stderr, " *** Saved %d registers ***\n", total_registers_saved); + if(total_registers_saved && pic16_pcode_verbose) + 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; + } +} + + /*-----------------------------------------------------------------* * @@ -369,6 +481,12 @@ static void Remove2pcodes(pCode *pcflow, pCode *pc1, pCode *pc2, regs *reg, int if(!reg) return; +#if 0 + fprintf(stderr,"removing 2 instructions:\n"); + pc1->print(stderr,pc1); + pc2->print(stderr,pc2); +#endif + if(pc1) Remove1pcode(pc1, reg); @@ -384,6 +502,15 @@ 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 + } /*-----------------------------------------------------------------* @@ -400,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)) ; @@ -428,6 +562,8 @@ static int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *re int t = total_registers_saved; + if(reg->type == REG_SFR)return 0; + if(pc2->seq < pc1->seq) { pct1 = pc2; pc2 = pc1; @@ -466,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) ){ @@ -485,13 +641,18 @@ static int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *re } else if(PCI(pc1)->op == POC_MOVWF) { + reg1 = pic16_getRegFromInstruction(pc1); + + if(reg1->type == REG_SFR)return (total_registers_saved != t); + pct2 = pic16_findNextInstruction(pc2->next); if(PCI(pc2)->op == POC_MOVFW) { - /* + +#if 0 fprintf(stderr, " MOVWF/MOVFW. instruction after MOVFW is:\n"); pct2->print(stderr,pct2); - */ +#endif if(PCI(pct2)->op == POC_MOVWF) { /* @@ -509,8 +670,8 @@ static int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *re */ reg2 = pic16_getRegFromInstruction(pct2); - //if(reg2 && !regUsedinRange(pc1,pc2,reg2) && (reg2->type != REG_SFR)) { - if(reg2 && !regUsedinRange(pc1,pc2,reg2)) { + if(reg2 && !regUsedinRange(pc1,pc2,reg2) && (reg2->type != REG_SFR)) { +// if(reg2 && !regUsedinRange(pc1,pc2,reg2)) if(pic16_pCodeSearchCondition(pct2, PCC_Z) < 1) { pCode *pct3 = pic16_findNextInstruction(pct2->next); @@ -522,22 +683,22 @@ 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 } } @@ -549,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: @@ -600,7 +762,9 @@ static int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *re } } else if ( (PCI(pct1)->op == POC_MOVWF) && (PCI(pc2)->op == POC_MOVFW)) { - //fprintf(stderr,"movwf MOVWF/MOVFW\n"); + +// fprintf(stderr,"movwf MOVWF/MOVFW\n"); + if(optimize_level > 1 && can_free) { pct2 = pic16_newpCode(POC_MOVFW, PCI(pc1)->pcop); pic16_pCodeInsertAfter(pc2, pct2); @@ -638,15 +802,16 @@ static void OptimizeRegUsage(set *fregs, int optimize_multi_uses, int optimize_l reg = fregs->item; fregs = fregs->next; - if(reg->type == REG_SFR) { - //fprintf(stderr,"skipping SFR: %s\n",reg->name); - continue; - } + if(reg->type == REG_SFR) { +// fprintf(stderr,"skipping SFR: %s\n",reg->name); + continue; + } pcfl_used = setFirstItem(reg->reglives.usedpFlows); pcfl_assigned = setFirstItem(reg->reglives.assignedpFlows); used = elementsInSet(reg->reglives.usedpCodes); +// fprintf(stderr, "%s:%d register %s used %d times in pCode\n", __FILE__, __LINE__, reg->name, used); if(used == 2) { /* @@ -654,12 +819,13 @@ static void OptimizeRegUsage(set *fregs, int optimize_multi_uses, int optimize_l * instructions are examined. If possible, they're optimized out. */ -/* +#if 0 fprintf (stderr, "OptimizeRegUsage: %s addr=0x%03x rIdx=0x%03x type=%d used=%d\n", reg->name, reg->address, reg->rIdx, reg->type, used); -*/ +#endif + pc1 = setFirstItem(reg->reglives.usedpCodes); pc2 = setNextItem(reg->reglives.usedpCodes); @@ -671,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"); @@ -689,7 +855,7 @@ static void OptimizeRegUsage(set *fregs, int optimize_multi_uses, int optimize_l //fprintf(stderr,"WARNING %s: reg %s used without being assigned\n",__FUNCTION__,reg->name); } else { - //fprintf(stderr,"WARNING %s: reg %s assigned without being used\n",__FUNCTION__,reg->name); +// fprintf(stderr,"WARNING %s: reg %s assigned without being used\n",__FUNCTION__,reg->name); Remove2pcodes(pcfl_assigned, pc1, pc2, reg, 1); total_registers_saved++; // debugging stats. } @@ -700,7 +866,7 @@ static void OptimizeRegUsage(set *fregs, int optimize_multi_uses, int optimize_l if(used && !pcfl_used && pcfl_assigned) { pCode *pc; - //fprintf(stderr,"WARNING %s: reg %s assigned without being used\n",__FUNCTION__,reg->name); + fprintf(stderr,"WARNING %s: reg %s assigned without being used\n",__FUNCTION__,reg->name); pc = setFirstItem(reg->reglives.usedpCodes); while(pc) { @@ -774,39 +940,45 @@ 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; + +#define OPT_PASSES 8 + passes = OPT_PASSES; - /* 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)); + do { + saved = total_registers_saved; - if(total_registers_saved != saved) - fprintf(stderr, " *** pass %d, Saved %d registers, total saved %d ***\n", - (1+OPT_PASSES-passes),total_registers_saved-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)); + + 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--; + passes--; - } while( passes && ((total_registers_saved != saved) || (passes==OPT_PASSES-1)) ); + } while( passes && ((total_registers_saved != saved) || (passes==OPT_PASSES-1)) ); - if(total_registers_saved == t) - 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"); -/* - 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); -*/ +#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); +#endif } @@ -821,7 +993,6 @@ static void RegsSetUnMapLiveRanges(set *regset) while(regset) { reg = regset->item; regset = regset->next; - deleteSet(®->reglives.usedpCodes); deleteSet(®->reglives.usedpFlows); @@ -833,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); - }