X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fpic%2Fpcoderegs.c;h=c115b3213ab9df8b8d6a7a56cd79eec6a74d6b47;hb=1e65e3bd5cbff5a1ab4a7a65c2ff68e4b5e5b43c;hp=0c8f4bebed9c1dc485ee9726b5e23259cb100b97;hpb=5db7b152dddfeac2395417a253993f63e21e0fe5;p=fw%2Fsdcc diff --git a/src/pic/pcoderegs.c b/src/pic/pcoderegs.c index 0c8f4beb..c115b321 100644 --- a/src/pic/pcoderegs.c +++ b/src/pic/pcoderegs.c @@ -26,129 +26,20 @@ pcoderegs.c The purpose of the code in this file is to optimize the register usage. */ -#include -#include "common.h" // Include everything in the SDCC src directory -#include "newalloc.h" -#include "ralloc.h" -#include "device.h" -#include "pcode.h" +#include "main.h" #include "pcoderegs.h" #include "pcodeflow.h" -#include "main.h" - -extern void dbg_dumpregusage(void); -extern pCode * findPrevInstruction(pCode *pci); -extern pBranch * pBranchAppend(pBranch *h, pBranch *n); -void unlinkpCode(pCode *pc); -extern int pCodeSearchCondition(pCode *pc, unsigned int cond, int contIfSkip); -char *pCode2str(char *str, int size, pCode *pc); -void SAFE_snprintf(char **str, size_t *size, const char *format, ...); -//static int sameRegs (const regs *reg1, const regs *reg2); - -int total_registers_saved=0; -int register_optimization=1; - -/*-----------------------------------------------------------------* -* void AddRegToFlow(regs *reg, pCodeFlow *pcfl) -*-----------------------------------------------------------------*/ -/* -void AddRegToFlow(regs *reg, pCodeFlow *pcfl) -{ - - if(!reg || ! pcfl || !isPCFL(pcflow)) - return; - - if(!pcfl->registers) - pcfl->registers = newSet(); - -} -*/ - - -/*-----------------------------------------------------------------* -* -*-----------------------------------------------------------------*/ -void dbg_regusage(set *fregs) -{ - regs *reg; - pCode *pcfl; - pCode *pc; - - - for (reg = setFirstItem(fregs) ; reg ; - reg = setNextItem(fregs)) { - - if(elementsInSet(reg->reglives.usedpCodes)) { - - fprintf (stderr, "%s addr=0x%03x rIdx=0x%03x", - reg->name, - reg->address, - reg->rIdx); - - pcfl = setFirstItem(reg->reglives.usedpFlows); - if(pcfl) - fprintf(stderr, "\n used in seq"); - - while(pcfl) { - fprintf(stderr," 0x%03x",pcfl->seq); - pcfl = setNextItem(reg->reglives.usedpFlows); - } - - pcfl = setFirstItem(reg->reglives.assignedpFlows); - if(pcfl) - fprintf(stderr, "\n assigned in seq"); - - while(pcfl) { - fprintf(stderr," 0x%03x",pcfl->seq); - pcfl = setNextItem(reg->reglives.assignedpFlows); - } - - pc = setFirstItem(reg->reglives.usedpCodes); - if(pc) - fprintf(stderr, "\n used in instructions "); - - while(pc) { - pcfl = PCODE(PCI(pc)->pcflow); - if(pcfl) - fprintf(stderr," 0x%03x:",pcfl->seq); - fprintf(stderr,"0x%03x",pc->seq); - - pc = setNextItem(reg->reglives.usedpCodes); - } - - fprintf(stderr, "\n"); - } - } -} +#include "ralloc.h" -/*-----------------------------------------------------------------* -* -*-----------------------------------------------------------------*/ -void dbg_dumpregusage(void) -{ - - fprintf(stderr,"*** Register Usage ***\n"); - fprintf(stderr,"InternalRegs:\n"); - dbg_regusage(dynInternalRegs); - fprintf(stderr,"AllocRegs:\n"); - dbg_regusage(dynAllocRegs); - fprintf(stderr,"StackRegs:\n"); - dbg_regusage(dynStackRegs); - fprintf(stderr,"DirectRegs:\n"); - dbg_regusage(dynDirectRegs); - fprintf(stderr,"DirectBitRegs:\n"); - dbg_regusage(dynDirectBitRegs); - fprintf(stderr,"ProcessorRegs:\n"); - dbg_regusage(dynProcessorRegs); - -} +static int total_registers_saved=0; +static int register_optimization=1; /*-----------------------------------------------------------------* * void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl) *-----------------------------------------------------------------*/ -void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl) +static void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl) { pCode *pc=NULL; @@ -192,6 +83,7 @@ void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl) addSetIfnotP(& (reg->reglives.assignedpFlows), pcfl); addSetIfnotP(& (reg->reglives.usedpCodes), pc); + reg->wasUsed = 1; } @@ -237,8 +129,6 @@ void pCodeRegMapLiveRanges(pBlock *pb) } #endif - // dbg_dumpregusage(); - } @@ -277,20 +167,21 @@ static void Remove1pcode(pCode *pc, regs *reg, int debug_code) } - if(1){ - /* - Debug stuff. Comment out the instruction we're about to delete. - */ + if(1) { + /* + * Debug stuff. Comment out the instruction we're about to delete. + */ char buff1[256]; size_t size = 256; - char *pbuff,**ppbuff; - pbuff = buff1; - ppbuff = &pbuff; + char *pbuff; + pbuff = &buff1[0]; - SAFE_snprintf(ppbuff,&size, ";%d", debug_code); - pCode2str(*ppbuff, size, pc); + SNPRINTF(pbuff, size, ";%d", debug_code); + size -= strlen(pbuff); + pbuff += strlen(pbuff); + pCode2str(pbuff, size, pc); pCodeInsertBefore(pc, newpCodeCharP(buff1)); //fprintf(stderr,"removing instruction:\n%s\n",buff1); } @@ -303,7 +194,7 @@ static void Remove1pcode(pCode *pc, regs *reg, int debug_code) * void RemoveRegsFromSet(set *regset) * *-----------------------------------------------------------------*/ -void RemoveRegsFromSet(set *regset) +static void RemoveRegsFromSet(set *regset) { regs *reg; int used; @@ -370,9 +261,7 @@ void RemoveRegsFromSet(set *regset) } } -void RegsUnMapLiveRanges(void); -extern pFile *the_pFile; -void pic14_ReMapLiveRanges(void) +static void pic14_ReMapLiveRanges(void) { pBlock *pb; if (!the_pFile) return; @@ -453,7 +342,7 @@ static void Remove2pcodes(pCode *pcflow, pCode *pc1, pCode *pc2, regs *reg, int /*-----------------------------------------------------------------* * *-----------------------------------------------------------------*/ -int regUsedinRange(pCode *pc1, pCode *pc2, regs *reg) +static int regUsedinRange(pCode *pc1, pCode *pc2, regs *reg) { int i=0; regs *testreg; @@ -475,7 +364,7 @@ int regUsedinRange(pCode *pc1, pCode *pc2, regs *reg) return 0; } -int regIsSpecial (regs *reg, int mayBeGlobal) +static int regIsSpecial (regs *reg, int mayBeGlobal) { if (!reg) return 0; @@ -484,23 +373,6 @@ int regIsSpecial (regs *reg, int mayBeGlobal) return 0; } -#if 0 -static int regIsLocal (regs *reg) -{ - if (!reg) return 1; - /* temporaries are local */ - if (reg->type == REG_TMP) return 1; - /* registers named r0x... are local */ - if (reg->name && !strncmp(reg->name,"r0x", 3)) - { - //fprintf (stderr, "reg %s is not marked REG_TMP...\n", reg->name); - return 1; - } - - return 0; -} -#endif - /*-----------------------------------------------------------------* * void pCodeOptime2pCodes(pCode *pc1, pCode *pc2) * @@ -512,7 +384,7 @@ static int regIsLocal (regs *reg) * * *-----------------------------------------------------------------*/ -int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *reg, int can_free, int optimize_level) +static int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *reg, int can_free, int optimize_level) { pCode *pct1, *pct2; regs *reg1, *reg2; @@ -522,24 +394,27 @@ int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *reg, int if (!isPCI(pc1) || !isPCI(pc2)) return 0; if (PCI(pc1)->pcflow != PCI(pc2)->pcflow) return 0; - if(pc2->seq < pc1->seq) { + if (pc2->seq < pc1->seq) { pct1 = pc2; pc2 = pc1; pc1 = pct1; } /* disable this optimization for now -- it's buggy */ - if(pic14_options.disable_df) return 0; + if (pic14_options.disable_df) return 0; //fprintf(stderr,"pCodeOptime2pCodes\n"); //pc1->print(stderr,pc1); //pc2->print(stderr,pc2); if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_MOVFW) ){ + /* + * CLRF sets Z + * MOVFW affects Z + * MOVWF does not touch Z + * MOVLW does not touch Z + */ pCode *newpc; - int regUsed = 0; - int wUsed = 0; - int wSaved = 0; /* clrf reg ; pc1 stuff... @@ -552,41 +427,26 @@ int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *reg, int */ DFPRINTF((stderr, " optimising CLRF reg ... MOVF reg,W to ... MOVLW 0\n")); pct2 = findNextInstruction(pc2->next); - - if(pct2 && PCI(pct2)->op == POC_MOVWF) { - wSaved = wUsed = 1; /* Maybe able to replace with clrf pc2->next->reg. */ - } else { - wUsed = pCodeSearchCondition(pct2,PCC_W,1) != -1; - } - regUsed = regUsedinRange(pct2,0,reg); - if ((regUsed&&wUsed) || (pCodeSearchCondition(pct2,PCC_Z,0) != -1)) { - /* Do not optimise as exisiting code is required. */ - } else { - /* Can optimise. */ - if(regUsed) { - newpc = newpCode(POC_CLRF, PCI(pc1)->pcop); - } else if(wSaved && !wUsed) { - newpc = newpCode(POC_CLRF, PCI(pct2)->pcop); - pct2->destruct(pct2); - } else { - newpc = newpCode(POC_MOVLW, newpCodeOpLit(0)); - } + if (pCodeSearchCondition(pct2, PCC_Z, 0) == -1) { + /* Z is definitely overwritten before use */ + newpc = newpCode(POC_MOVLW, newpCodeOpLit(0)); pCodeInsertAfter(pc2, newpc); PCI(newpc)->pcflow = PCFL(pcfl_used); newpc->seq = pc2->seq; //fprintf (stderr, "%s:%d(%s): Remove2pcodes (CLRF reg, ..., MOVF reg,W)\n", __FILE__, __LINE__, __FUNCTION__); - Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free); - total_registers_saved++; // debugging stats. + //Remove2pcodes(pcfl_used, pc2, NULL, reg, 0); + pc2->destruct(pc2); + //total_registers_saved++; // debugging stats. } } else if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_IORFW) ){ DFPRINTF((stderr, " optimising CLRF/IORFW\n")); pct2 = findNextInstruction(pc2->next); - /* We must ensure that is destroyed before being read---IORLW must be performed unless this is proven. */ - if(pCodeSearchCondition(pct2, PCC_Z,0) != -1) { + /* We must ensure that Z is destroyed before being read---IORLW must be performed unless this is proven. */ + if (pCodeSearchCondition(pct2, PCC_Z, 0) != -1) { pct2 = newpCode(POC_IORLW, newpCodeOpLit(0)); pct2->seq = pc2->seq; PCI(pct2)->pcflow = PCFL(pcfl_used); @@ -710,7 +570,7 @@ int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *reg, int /*-----------------------------------------------------------------* * void pCodeRegOptimeRegUsage(pBlock *pb) *-----------------------------------------------------------------*/ -void OptimizeRegUsage(set *fregs, int optimize_multi_uses, int optimize_level) +static void OptimizeRegUsage(set *fregs, int optimize_multi_uses, int optimize_level) { regs *reg; int used; @@ -843,7 +703,6 @@ void OptimizeRegUsage(set *fregs, int optimize_multi_uses, int optimize_level) if(pc1 && isPCI(pc1) && ( (pcfl1 = PCI(pc1)->pcflow) != NULL) ) { - //while(rset2 && searching) { if(rset2) { pc2 = rset2->item; @@ -859,819 +718,13 @@ void OptimizeRegUsage(set *fregs, int optimize_multi_uses, int optimize_level) } } - rset1 = rset1->next; + rset1 = rset2; } } } } } -#if 0 - -/* The following routines implement pCode optimizations based on - * dataflow analysis. The effects should be similar to those - * of pCodeOptime2pCodes() but more powerful. - * - * Unfortunately, the current approach (comparing operands by - * their associated registers) is seriously flawed: - * Some pCodeOps do not provide access to their repsective regs - * (PO_DIRs are created from arbitrary strings, immediates need - * to take offset and index into account, ...) - * - * This has to be rewritten based on pCodeOps instead of regs... - */ - -/* ------------------------------------------------------------------ - Returns TRUE iff reg1 and reg2 are the same registers. - ------------------------------------------------------------------ */ - -static int sameRegs (const regs *reg1, const regs *reg2) -{ - if (reg1 == reg2) return 1; - if (!reg1 || !reg2) return 0; - assert (reg1->name && reg2->name); - - /* Compare names, as rIdx is not unique... */ - if (!strcmp(reg1->name, reg2->name)) return 1; - - /* Name mismatch -- not the same register. */ - return 0; -} - -/* ------------------------------------------------------------------ - Returns 1 if the register is live at pc (read in this flow), - returns -1 if the register is NOT live at pc (assigned a new value - prior to readingi the old value in this flow) or - return 0 if the register is not mentioned. - ------------------------------------------------------------------ */ - -static int checkRegInFlow (regs **reg, int *cond, pCode *pc) -{ - const int verbose = 0; - /* find next PCI at or after pc */ - while (pc && isPCFL(pc)) pc = pc->next; - - assert (reg && cond); - - /* remove pseudo flags from cond */ - *cond &= ~(PCC_REGISTER | PCC_EXAMINE_PCOP); - - if (verbose && pc) - { - fprintf (stderr, "Checking for reg %s, cond %x on pc ", *reg ? (*reg)->name : "", *cond); pc->print (stderr, pc); - } - - while (pc && !isPCFL(pc)) - { - if (verbose) - { - fprintf (stderr, " now checking for reg %s, cond %x on pc ", *reg ? (*reg)->name : "", *cond); - pc->print (stderr, pc); - } - if (isPCI(pc)) - { - pCode *pcprev; - regs *op = NULL; - int prevIsSkip = 0; - - pcprev = findPrevInstruction (pc); - if (pcprev && isPCI_SKIP(pcprev)) - prevIsSkip = 1; - - if ((PCI(pc)->inCond | PCI(pc)->outCond) & PCC_REGISTER) - { - op = getRegFromInstruction (pc); - - /* pCodeOpRegBits do not provide register information... */ - //if (!op) { __asm__("int3"); pc->print (stderr, pc); } - //assert (op); - if (!op) - { - if (reg) - return 1; /* assume `reg' is alive */ - } - - /* SPECIAL CASE: jump to unknown destination -- assume everything alive */ - if (op->type == PO_PCL) - { - return 1; - } - } // if - - if (PCI(pc)->inCond & PCC_REGISTER) - { - /* `op' is live (possibly read) */ - if (*reg && sameRegs (op, *reg)) - { - if (verbose) - { - fprintf (stderr, "reg is read in pc "); - pc->print (stderr, pc); - } - return 1; - } - } - - /* handle additional implicit operands */ - switch (PCI(pc)->op) - { - case POC_CALL: /* read arguments from WREG, clobbers WREG */ - if (*cond & PCC_W) - { - if (verbose) - { - fprintf (stderr, "conditions are read at pc "); - pc->print (stderr, pc); - } - return 1; - } - *cond &= ~PCC_W; - break; - case POC_RETURN: /* returns WREG to caller */ - //fprintf (stderr, "reached RETURN, reg %s, cond %x\n", *reg ? (*reg)->name : "", *cond); - if (*cond & PCC_W) - { - if (verbose) - { - fprintf (stderr, "conditions are read at pc "); - pc->print (stderr, pc); - } - return 1; - } - /* afterwards, no condition is alive */ - *cond = 0; - /* afterwards, all local registers are dead */ - if (*reg && regIsLocal (*reg)) *reg = NULL; - break; - case POC_RETLW: - case POC_RETFIE: /* this does not erturn WREG to the "caller", thus its rather a RETLW */ - /* this discards WREG */ - *cond &= ~PCC_W; - /* afterwards, no condition is alive */ - *cond = 0; - /* afterwards, all local registers are dead */ - if (*reg && regIsLocal (*reg)) *reg = NULL; - break; - default: - /* no implicit arguments */ - break; - } - - if (PCI(pc)->inCond & (*cond)) - { - /* a condition is read */ - if (verbose) - { - fprintf (stderr, "conditions are read at pc "); - pc->print (stderr, pc); - } - return 1; - } - - /* remove outConds from `cond' */ - (*cond) &= ~(PCI(pc)->outCond); - - if (PCI(pc)->outCond & PCC_REGISTER) - { - /* `op' is (possibly) discarded */ - if (*reg && !prevIsSkip && sameRegs (op, *reg)) - { - if (verbose) - { - fprintf (stderr, "reg is assigned (cont'd) at pc "); - pc->print (stderr, pc); - } - *reg = NULL; - } - } - - /* have all interesting conditions/registers been discarded? */ - if (!(*reg) && !(*cond)) - { - if (verbose) - { - fprintf (stderr, "reg and conditions are discarded after "); - pc->print (stderr, pc); - } - return -1; - } - } // if - - pc = pc->next; - } // while - - /* no use of (or only conditional writes to) `reg' found in flow */ - if (verbose) - { - fprintf (stderr, "analysis inconclusive: reg %s, cond %x remains\n", *reg ? "remains" : "is void", *cond); - } - return 0; -} - -/* ------------------------------------------------------------------ - This will return 1 only if - - reg is NULL or of type REG_TMP - - reg is NULL or its value is discarded after pc - - cond is 0 or all conditions are overwritten before being used - ------------------------------------------------------------------ */ - -typedef struct { - pCode *pc; - regs *reg; - int cond; -} df_state_t; - -df_state_t *df_free_states = NULL; - -static df_state_t * -df_newState (regs *reg, int cond, pCode *pc) -{ - df_state_t *state; - - if (df_free_states) { - state = df_free_states; - df_free_states = (df_state_t *)df_free_states->pc; - } else { - state = Safe_calloc(1, sizeof(df_state_t)); - } - state->pc = pc; - state->reg = reg; - state->cond = cond; - return state; -} - -static int -df_containsState (set *set, df_state_t *state) -{ - /* scan set for presence of `state' */ - df_state_t *curr; - for (curr = setFirstItem (set); curr; curr = setNextItem (set)) - { - if ((curr->pc == state->pc) - && (curr->reg == state->reg) - && (curr->cond == state->cond)) - { - /* `state' found */ - return 1; - } - } - return 0; -} - -static void -df_releaseState (df_state_t *state) -{ - state->pc = (pCode *)df_free_states; - df_free_states = (df_state_t *)state; - state->reg = NULL; - state->cond = 0; -} - -static void -df_removeStates () -{ - df_state_t *next; - while (df_free_states) - { - next = (df_state_t *)df_free_states->pc; - Safe_free(df_free_states); - df_free_states = next; - } // while -} - -int regIsDead (regs *reg, int cond, pCode *pc) -{ - set *seenStates = NULL; - set *todo = NULL; - pCode *curr; - df_state_t *state; - int result = 1; - - /* sanity checks */ - if (reg && !regIsLocal (reg)) return 0; - - pc = findNextInstruction (pc->next); - - addSet (&todo, df_newState(reg, cond, pc)); - - while ((result == 1) && (state = getSet (&todo))) - { - int res; - - if (df_containsState (seenStates, state)) continue; - addSet (&seenStates, state); - - curr = state->pc; - reg = state->reg; - cond = state->cond; - - //fprintf (stderr, "Checking for reg %s/cond %x at pc ", reg ? reg->name : "", cond); - //curr->print (stderr, curr); - - res = checkRegInFlow (®, &cond, curr); - switch (res) - { - case 1: /* `reg' or `cond' is read---not dead */ - result = 0; - break; - case -1: /* `reg' and `cond' are discarded in this flow---need to check other open flows */ - break; - default: /* `reg' is not read and (possibly) not assigned---check successor flows */ - if (curr) - { - pCodeFlow *pcfl = PCI(curr)->pcflow; - pCodeFlowLink *link; - pCode *first; - assert (pcfl); - - for (link = setFirstItem(pcfl->to); link; link = setNextItem (pcfl->to)) - { - /* add the first pCodeInstruction in the new flow to `todo' */ - first = findNextInstruction (&link->pcflow->pc); - if (first) addSet (&todo, df_newState (reg, cond, first)); - } // for - } - break; - } // switch - } // while - - /* clean up */ - while (NULL != (state = getSet (&todo))) { df_releaseState (state); } - while (NULL != (state = getSet (&seenStates))) { df_releaseState (state); } - - /* if result remained 1, `reg' is not even possibly read and thus dead */ - return result; -} - - - -/* ------------------------------------------------------------------ - Safely remove a pCode. - This needs to check that the previous instruction was no SKIP - (otherwise the SKIP instruction would have to be removed as well, - which may not be done for SFRs (side-effects on read possible)). - ------------------------------------------------------------------ */ - -extern void unBuildFlow (pBlock *pb); -extern void RegsUnMapLiveRanges (); -extern void BuildFlow (pBlock *pb); -extern void LinkFlow (pBlock *pb); -extern void BuildFlowTree (pBlock *pb); -extern void pCodeRegMapLiveRanges (pBlock *pb); -extern pFile *the_pFile; - -static int pCodeRemove (pCode *pc, const char *comment) -{ - pCode *pcprev, *pcnext; - unsigned int result = 0; - - /* Sanity checks. */ - if (!pc) return 0; - if (!isPCI(pc)) return 0; - - pcprev = findPrevInstruction (pc->prev); - if (pcprev && isPCI_SKIP(pcprev)) - { - /* bail out until we know how to fix the Flow... */ - //return 0; - - /* we also need to remove the preceeding SKIP instruction(s) */ - result = pCodeRemove (pcprev, "=DF= removing preceeding SKIP as well"); - if (!result) - { - /* previous instruction could not be removed -- this cannot be removed as well */ - return result; - } - /* FIXME: We now have to update the flow! */ - } // if - - /* do not remove pCodes with SFRs as operands (even reading them might cause side effects) */ - { - regs *reg; - reg = getRegFromInstruction (pc); - /* accesses to the STATUS register aer always safe, but others... */ - if (reg && reg->type == REG_SFR && reg->pc_type != PO_STATUS) return result; - } - - /* MUST SUCEED FROM NOW ON (or revert the changes done since NOW ;-)) */ - - /* fix flow */ - if (PCI(pc)->pcflow && PCI(pc)->pcflow->end == pc) - { - pCode *pcprev; - pcprev = findPrevInstruction (pc->prev); - if (PCI(pcprev)->pcflow == PCI(pc)->pcflow) - { - PCI(pc)->pcflow->end = pcprev; - } else { - pBlock *pb = pc->pb; - RegsUnMapLiveRanges(); - unBuildFlow(pb); - BuildFlow(pb); - LinkFlow(pb); - BuildFlowTree(pb); - for (pb = the_pFile->pbHead; pb; pb = pb->next) - { - pCodeRegMapLiveRanges(pb); - } - } - } - - /* attach labels to next instruction */ - pcnext = findNextInstruction (pc->next); - if (pcnext) - { - PCI(pcnext)->label = pBranchAppend (PCI(pcnext)->label, PCI(pc)->label); - if (!PCI(pcnext)->cline) PCI(pcnext)->cline = PCI(pc)->cline; - } - else - { - fprintf (stderr, "Cannot move a label...\n"); - exit(EXIT_FAILURE); - } - - if (comment) - { - char buffer[512]; - int size = 512; - char *pbuff = &buffer[0]; - - SAFE_snprintf (&pbuff, &size, "; %s:%u(%s): %s", __FILE__, __LINE__, __FUNCTION__, comment); - pCodeInsertAfter(pc->prev, newpCodeCharP (&buffer[0])); - } // if - - if (1) - { - /* replace removed pCode with out-commented version of itself */ - char buffer[512]; - int size = 512; - char *pbuff = &buffer[0]; - - SAFE_snprintf (&pbuff, &size, "; %s:%u(%s): ", __FILE__, __LINE__, __FUNCTION__); - pCode2str (pbuff, size, pc); - pCodeInsertAfter(pc->prev, newpCodeCharP (&buffer[0])); - } - - pc->destruct (pc); - return result+1; -} - -/* ------------------------------------------------------------------ - Find and remove dead pCodes. - ------------------------------------------------------------------ */ - -static int removeIfDeadPCI (pCode *pc) -{ - pCode *pcnext = NULL; - pCode *curr; - unsigned int outCond; - unsigned int result = 0; - regs *dst; - - if (!pc) return 0; - dst = NULL; - - /* skip non-PCIs */ - pcnext = findNextInstruction (pc->next); - if (!isPCI(pc)) return 0; - - switch (PCI(pc)->op) - { - case POC_ADDLW: - case POC_ADDWF: - case POC_ADDFW: - case POC_ANDLW: - case POC_ANDWF: - case POC_ANDFW: - case POC_BCF: - case POC_BSF: - //case POC_BTFSC: - //case POC_BTFSS: - //case POC_CALL: - case POC_COMF: - case POC_COMFW: - case POC_CLRF: - case POC_CLRW: - //case POC_CLRWDT: - case POC_DECF: - case POC_DECFW: - //case POC_DECFSZ: - //case POC_DECFSZW: - //case POC_GOTO: - case POC_INCF: - case POC_INCFW: - //case POC_INCFSZ: - //case POC_INCFSZW: - case POC_IORLW: - case POC_IORWF: - case POC_IORFW: - case POC_MOVF: - case POC_MOVFW: - case POC_MOVLW: - case POC_MOVWF: - case POC_NOP: - //case POC_RETLW: - //case POC_RETURN: - //case POC_RETFIE: - case POC_RLF: - case POC_RLFW: - case POC_RRF: - case POC_RRFW: - case POC_SUBLW: - case POC_SUBWF: - case POC_SUBFW: - case POC_SWAPF: - case POC_SWAPFW: - //case POC_TRIS: - case POC_XORLW: - case POC_XORWF: - case POC_XORFW: - //case POC_BANKSEL: - //case POC_PAGESEL: - break; - - default: - /* do not remove unknown PCIs */ - return 0; - } // switch - - /* redundant checks---those instructions may never be removed */ - if (isPCI_BRANCH(pc)) return 0; - if (isPCI_SKIP(pc)) return 0; - - outCond = PCI(pc)->outCond; - curr = pcnext; - - /* unknown operands assigned to, then ignore */ - if ((outCond & (PCC_REGISTER | PCC_C | PCC_Z | PCC_DC | PCC_W)) != outCond) - return 0; - - if (outCond & PCC_REGISTER) - { - dst = getRegFromInstruction (pc); - if (!dst) return 0; - - /* special reg? */ - if (!regIsLocal (dst)) return 0; - if (regIsSpecial (dst,0)) return 0; - } - - //fprintf (stderr, "--> checking for liveness pc "); pc->print (stderr, pc); - if (regIsDead (dst, outCond, pc)) - { - /* no result from pc has been used -- pc is `dead' */ - //fprintf (stderr, "--> reg %s and cond %x assumed unused\n", dst ? dst->name : "", outCond); - //fprintf (stderr, "--> removing dead pc "); pc->print (stderr, pc); - result = pCodeRemove (pc, "=DF= removed dead pCode"); - } - - return result; -} - -/* ------------------------------------------------------------------ - This routine is intended to safely replace one pCodeInstruction - with a different pCodeInstruction. - If desired, the replaced pCode will be left in (commented out) for - debugging. - Further, an optional comment can be inserted to indicate the - reason for the possible removal of the pCode. - ------------------------------------------------------------------ */ - -static void replace_PCI (pCodeInstruction *pc, pCodeInstruction *newpc, char *comment) -{ - newpc->from = pBranchAppend (newpc->from, pc->from); - newpc->to = pBranchAppend (newpc->to, pc->to); - newpc->label = pBranchAppend (newpc->label, pc->label); - //newpc->pcflow = pc->pcflow; // updated in pCodeInsertAfter, ->pb is as well - newpc->cline = pc->cline; - - newpc->pc.seq = pc->pc.seq; - - pCodeInsertAfter (&pc->pc, &newpc->pc); - - /* FIXME: replacing pc will break the liverange maps (usedpCodes, ...) */ - pCodeRegMapLiveRanges( pc->pBlock ); /*FIXME:UNTESTED*/ - - if (comment) - { - pCodeInsertAfter (&pc->pc, newpCodeCharP (comment)); - } // if - - if (1) - { - /* replace pc with commented out version of itself */ - char buffer[1024], buffer2[1024]; - char *pbuff = &buffer[0]; - int size=1024; - pCode2str (&buffer2[0],1024,&pc->pc); - SAFE_snprintf (&pbuff,&size,"%s:%u(%s): removed pCode was %s\t", __FILE__, __LINE__, __FUNCTION__, &buffer2[0]); - pCodeInsertAfter (&pc->pc, newpCodeCharP (&buffer[0])); - } // if - - pc->pc.destruct (&pc->pc); -} - -/* ------------------------------------------------------------------ - Find the first (unique) assignment to `reg' (prior to pc). - ------------------------------------------------------------------ */ - -pCode *findAssignmentToReg (regs *reg, pCode *pc) -{ - pCode *curr; - - assert (pc && isPCI(pc) && reg); - - curr = findPrevInstruction (pc->prev); - - while (curr && PCI(curr)->pcflow == PCI(pc)->pcflow) - { - if (PCI(curr)->outCond & PCC_REGISTER) - { - regs *op = getRegFromInstruction (curr); - if (op && (sameRegs(op,reg))) - return curr; - } // if - curr = findPrevInstruction (curr->prev); - } // while - - /* no assignment to reg found */ - return NULL; -} - -/* ------------------------------------------------------------------ - Find a register that holds the same value as `reg' (an alias). - ------------------------------------------------------------------ */ - -regs *findRegisterAlias (regs *reg, pCode *pc) -{ - pCode *curr; - - if(!reg) return NULL; - - if (regIsSpecial (reg, 0)) return NULL; - - curr = findAssignmentToReg (reg, pc); - - /* no assignment found --> no alias found */ - if (!curr) return NULL; - - switch (PCI(curr)->op) - { - case POC_MOVWF: - /* find previous assignment to WREG */ - while (curr && !(PCI(curr)->outCond & PCC_W)) - curr = findPrevInstruction (curr->prev); - if (curr && PCI(curr)->op == POC_MOVFW) - { - regs *op = getRegFromInstruction (curr); - /* alias must not be changed since assignment... */ - if (PCI(curr)->pcop) - { - switch (PCI(curr)->pcop->type) - { - case PO_GPR_REGISTER: - case PO_GPR_TEMP: - /* these operands are ok */ - break; - default: - /* not a plain register operand */ - return NULL; - break; - } - } - if (!op || regIsSpecial (op, 0) || !regIsUnchangedSince (op, pc, curr)) return NULL; - //fprintf (stderr, "found register alias for %s: %s\n", reg->name, op && op->name ? op->name : ""); - return op; - } else { - /* unknown source to WREG -- unknown register alias */ - return NULL; - } - break; - - default: - /* unhandled instruction -- assume unknown source, no alias */ - return NULL; - } - - /* no alias found */ - return NULL; -} - -/* ------------------------------------------------------------------ - Analyze a single pCodeInstruction's dataflow relations and replace - it with a better variant if possible. - ------------------------------------------------------------------ */ - -void analyzeAndReplacePCI (pCodeInstruction *pci) -{ - regs *op_reg, *alias_reg; - - assert (pci); - - if (!isPCI(pci)) return; - - switch (pci->op) - { - case POC_MOVFW: - case POC_ADDFW: - case POC_ANDFW: - case POC_IORFW: - case POC_XORFW: - /* try to find a different source register */ - op_reg = getRegFromInstruction (&pci->pc); - if (pci->op == POC_MOVFW) /* touches Z */ - { - pCode *assignment = findAssignmentToReg (op_reg, &pci->pc); - if (assignment && isPCI(assignment) && (PCI(assignment)->op == POC_CLRF)) - { - replace_PCI (pci, PCI(newpCode(POC_MOVLW, newpCodeOpLit(0))), "replaced with CLRF"); - return; - } - } - - alias_reg = findRegisterAlias (op_reg, &pci->pc); - if (alias_reg) - { - replace_PCI (pci, PCI(newpCode(pci->op, newpCodeOpRegFromStr (alias_reg->name))), "=DF= replaced with move from register alias"); - } - break; - - default: - /* do not optimize */ - break; - } // switch -} - -extern pFile *the_pFile; - -/* ------------------------------------------------------------------ - Find and remove dead pCodes. - ------------------------------------------------------------------ */ - -static int removeDeadPCIs (void) -{ - pBlock *pb; - unsigned int removed = 0; - - if (!the_pFile) return removed; - - do { - removed = 0; - - /* iterate over all pBlocks */ - for (pb = the_pFile->pbHead; pb; pb = pb->next) - { - pCode *pc, *pcnext = NULL; - - /* iterate over all pCodes */ - for (pc = findNextInstruction (pb->pcHead); pc; pc = pcnext) - { - pcnext = findNextInstruction (pc->next); - removed += removeIfDeadPCI (pc); - } // while - } // for pb - - fprintf (stderr, "[removed %u dead pCodes]\n", removed); - } while (removed); - - return 0; -} - -/* ------------------------------------------------------------------ - This routine tries to optimize the dataflow by... - (1) - - This routine leaves in dead pCodes (assignments whose results are - not used) -- these should be removed in a following sweep phase. - ------------------------------------------------------------------ */ - -void optimizeDataflow (void) -{ - pBlock *pb; - - if (!the_pFile) return; - - //fprintf (stderr, "%s:%u(%s): Starting optimization...\n", __FILE__, __LINE__, __FUNCTION__); - - /* iterate over all pBlocks */ - for (pb = the_pFile->pbHead; pb; pb = pb->next) - { - pCode *pc, *pcnext = NULL; - - /* iterate over all pCodes */ - for (pc = findNextInstruction (pb->pcHead); pc; pc = pcnext) - { - pcnext = findNextInstruction (pc->next); - analyzeAndReplacePCI (PCI(pc)); - } // while - } // for pb - - while (removeDeadPCIs ()) { /* remove dead codes in multiple passes */}; - df_removeStates (); -} - -#endif - /*-----------------------------------------------------------------* * void pCodeRegOptimeRegUsage(pBlock *pb) *-----------------------------------------------------------------*/ @@ -1712,16 +765,6 @@ void pCodeRegOptimizeRegUsage(int level) if(total_registers_saved == t) DFPRINTF((stderr, "No registers saved on this pass\n")); - - - /* - fprintf(stderr,"dynamically allocated regs:\n"); - dbg_regusage(dynAllocRegs); - fprintf(stderr,"stack regs:\n"); - dbg_regusage(dynStackRegs); - fprintf(stderr,"direct regs:\n"); - dbg_regusage(dynDirectRegs); - */ } @@ -1729,7 +772,7 @@ void pCodeRegOptimizeRegUsage(int level) * void RegsUnMapLiveRanges(set *regset) * *-----------------------------------------------------------------*/ -void RegsSetUnMapLiveRanges(set *regset) +static void RegsSetUnMapLiveRanges(set *regset) { regs *reg;