static int total_registers_saved=0;
static int register_optimization=1;
-/*-----------------------------------------------------------------*
-* void AddRegToFlow(regs *reg, pCodeFlow *pcfl)
-*-----------------------------------------------------------------*/
-/*
-static void AddRegToFlow(regs *reg, pCodeFlow *pcfl)
-{
-
- if(!reg || ! pcfl || !isPCFL(pcflow))
- return;
-
- if(!pcfl->registers)
- pcfl->registers = newSet();
-
-}
-*/
-
-
-#if 0
-/*-----------------------------------------------------------------*
-*
-*-----------------------------------------------------------------*/
-static 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");
- }
- }
-}
-#endif
-
-#if 0
-/*-----------------------------------------------------------------*
-*
-*-----------------------------------------------------------------*/
-static 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);
-
-}
-#endif
-
/*-----------------------------------------------------------------*
* void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl)
*-----------------------------------------------------------------*/
}
#endif
- // dbg_dumpregusage();
-
}
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)
*
}
}
-#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 : "<none>", *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 : "<none>", *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 : "<none>", *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
-}
-
-static 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 : "<none>", 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)).
- ------------------------------------------------------------------ */
-
-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];
-
- 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];
-
- SNPRINTF (pbuff, size, "; %s:%u(%s): ", __FILE__, __LINE__, __FUNCTION__);
- size -= strlen(pbuff);
- pbuff += strlen(pbuff);
- 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 : "<none>", 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);
- 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).
- ------------------------------------------------------------------ */
-
-static 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).
- ------------------------------------------------------------------ */
-
-static 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 : "<no 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.
- ------------------------------------------------------------------ */
-
-static 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
-}
-
-/* ------------------------------------------------------------------
- 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.
- ------------------------------------------------------------------ */
-
-static 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)
*-----------------------------------------------------------------*/
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);
- */
}