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 total_registers_saved=0;
+int register_optimization=1;
/*-----------------------------------------------------------------*
* void AddRegToFlow(regs *reg, pCodeFlow *pcfl)
pCodeRegMapLiveRangesInFlow(PCFL(pcflow));
}
-
+#if 0
for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
pcflow != NULL;
pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
regs *r = setFirstItem(PCFL(pcflow)->registers);
- //fprintf(stderr,"flow seq %d\n", pcflow->seq);
+ fprintf(stderr,"flow seq %d\n", pcflow->seq);
+
while (r) {
- //fprintf(stderr, " %s\n",r->name);
+ fprintf(stderr, " %s\n",r->name);
r = setNextItem(PCFL(pcflow)->registers);
}
}
+#endif
// dbg_dumpregusage();
reg = regset->item;
regset = regset->next;
-/*
- for (reg = setFirstItem(regset) ; reg ;
- reg = setNextItem(regset)) {
-*/
used = elementsInSet(reg->reglives.usedpCodes);
if(used <= 1) {
{
/* First, get rid of registers that are used only one time */
-
- RemoveRegsFromSet(dynInternalRegs);
+ //RemoveRegsFromSet(dynInternalRegs);
RemoveRegsFromSet(dynAllocRegs);
RemoveRegsFromSet(dynStackRegs);
/*
/*-----------------------------------------------------------------*
*
*-----------------------------------------------------------------*/
-static void Remove2pcodes(pCode *pcflow, pCode *pc1, pCode *pc2, regs *reg)
+static void Remove2pcodes(pCode *pcflow, pCode *pc1, pCode *pc2, regs *reg, int can_free)
{
if(!reg)
return;
Remove1pcode(pc2, reg);
deleteSetItem (&(PCFL(pcflow)->registers), reg);
- reg->isFree = 1;
- reg->wasUsed = 0;
+ if(can_free) {
+ reg->isFree = 1;
+ reg->wasUsed = 0;
+ }
}
return 0;
}
+/*-----------------------------------------------------------------*
+ * void pCodeOptime2pCodes(pCode *pc1, pCode *pc2)
+ *
+ * ADHOC pattern checking
+ * Now look for specific sequences that are easy to optimize.
+ * Many of these sequences are characteristic of the compiler
+ * (i.e. it'd probably be a waste of time to apply these adhoc
+ * checks to hand written assembly.)
+ *
+ *
+ *-----------------------------------------------------------------*/
+int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *reg, int can_free, int optimize_level)
+{
+ pCode *pct1, *pct2;
+ regs *reg1, *reg2;
+
+ int t = total_registers_saved;
+
+ if(pc2->seq < pc1->seq) {
+ pct1 = pc2;
+ pc2 = pc1;
+ pc1 = pct1;
+ }
+/*
+ fprintf(stderr,"pCodeOptime2pCodes\n");
+ pc1->print(stderr,pc1);
+ pc2->print(stderr,pc2);
+*/
+ if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_MOVFW) ){
+
+ /*
+ clrf reg
+ stuff...
+ movf reg,w
+
+ can be replaced with
+
+ stuff...
+ movlw 0
+ */
+
+ pCode *newpc;
+ //fprintf(stderr, " CLRF/MOVFW. instruction after MOVFW is:\n");
+ pct1 = findNextInstruction(pc2->next);
+
+ if(PCI(pct1)->op == POC_MOVWF) {
+ newpc = newpCode(POC_CLRF, PCI(pct1)->pcop);
+ pct1->destruct(pct1);
+ } else {
+ newpc = newpCode(POC_MOVLW, newpCodeOpLit(0));
+ }
+
+ pCodeInsertAfter(pc2, newpc);
+ PCI(newpc)->pcflow = PCFL(pcfl_used);
+ newpc->seq = pc2->seq;
+
+ 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) ){
+ //fprintf(stderr, " CLRF/IORFW.\n");
+
+ pct2 = findNextInstruction(pc2->next);
+
+ if(pCodeSearchCondition(pct2, PCC_Z) > 0) {
+ pct2 = newpCode(POC_IORLW, newpCodeOpLit(0));
+ pct2->seq = pc2->seq;
+ PCI(pct2)->pcflow = PCFL(pcfl_used);
+ pCodeInsertAfter(pc1,pct2);
+ }
+ Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
+ total_registers_saved++; // debugging stats.
+
+ } else if(PCI(pc1)->op == POC_MOVWF) {
+
+ pct2 = findNextInstruction(pc2->next);
+
+ if(PCI(pc2)->op == POC_MOVFW) {
+ /*
+ fprintf(stderr, " MOVWF/MOVFW. instruction after MOVFW is:\n");
+ pct2->print(stderr,pct2);
+ */
+
+ if(PCI(pct2)->op == POC_MOVWF) {
+ /*
+ Change:
+
+ movwf reg
+
+ stuff...
+
+ movf reg,w
+ movwf reg2
+
+ To:
+
+
+ */
+ reg2 = getRegFromInstruction(pct2);
+ //if(reg2 && !regUsedinRange(pc1,pc2,reg2) && (reg2->type != REG_SFR)) {
+ if(reg2 && !regUsedinRange(pc1,pc2,reg2)) {
+
+ if(pCodeSearchCondition(pct2, PCC_Z) < 1) {
+ pCode *pct3 = findNextInstruction(pct2->next);
+ pct2->seq = pc1->seq;
+ unlinkpCode(pct2);
+ pCodeInsertAfter(findPrevInstruction(pc1->prev),pct2);
+
+#define usesW(x) ((x) && (isPCI(x)) && ( (PCI(x)->inCond & PCC_W) != 0))
+
+ if(usesW(pct3))
+ ; // Remove2pcodes(pcfl_used, pc1, NULL, reg, can_free);
+ 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");
+ }
+ }
+/*
+ fprintf(stderr, " couldn't optimize\n");
+ if(reg2)
+ fprintf(stderr, " %s is used in range\n",reg2->name);
+ else
+ fprintf(stderr, " reg2 is NULL\n");
+*/
+ }
+ }
+
+ pct1 = findPrevInstruction(pc1->prev);
+ if(pct1 && (PCI(pct1)->pcflow == PCI(pc1)->pcflow)) {
+
+ if ( (PCI(pct1)->op == POC_MOVFW) &&
+ (PCI(pc2)->op == POC_MOVFW)) {
+
+ reg1 = getRegFromInstruction(pct1);
+ if(reg1 && !regUsedinRange(pc1,pc2,reg1)) {
+ /*
+ fprintf(stderr, " MOVF/MOVFW. \n");
+ fprintf(stderr, " ...optimizing\n");
+ */
+
+ /*
+ Change:
+
+ movf reg1,w
+ movwf reg
+
+ stuff...
+ movf reg,w
+
+ To:
+
+ stuff...
+
+ movf reg1,w
+
+ Or, if we're not deleting the register then the "To" is:
+
+ stuff...
+
+ movf reg1,w
+ movwf reg
+
+
+ */
+ pct2 = newpCode(PCI(pc2)->op, PCI(pct1)->pcop);
+ pCodeInsertAfter(pc2, pct2);
+ PCI(pct2)->pcflow = PCFL(pcfl_used);
+ pct2->seq = pc2->seq;
+
+ if(can_free) {
+ Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
+ } else {
+ /* If we're not freeing the register then that means (probably)
+ * the register is needed somewhere else.*/
+ unlinkpCode(pc1);
+ pCodeInsertAfter(pct2, pc1);
+
+ Remove2pcodes(pcfl_used, pc2, NULL, reg, can_free);
+ }
+
+ Remove2pcodes(pcfl_used, pct1, NULL, reg1, 0);
+ total_registers_saved++; // debugging stats.
+
+ }
+ } else if ( (PCI(pct1)->op == POC_MOVWF) &&
+ (PCI(pc2)->op == POC_MOVFW)) {
+ //fprintf(stderr,"movwf MOVWF/MOVFW\n");
+ if(optimize_level > 1 && can_free) {
+ pct2 = newpCode(POC_MOVFW, PCI(pc1)->pcop);
+ pCodeInsertAfter(pc2, pct2);
+ Remove2pcodes(pcfl_used, pc1, pc2, reg, 1);
+ total_registers_saved++; // debugging stats.
+ }
+ }
+
+
+ }
+
+ }
+
+ return (total_registers_saved != t);
+}
+
/*-----------------------------------------------------------------*
* void pCodeRegOptimeRegUsage(pBlock *pb)
*-----------------------------------------------------------------*/
-void OptimizeRegUsage(set *fregs)
+void OptimizeRegUsage(set *fregs, int optimize_multi_uses, int optimize_level)
{
regs *reg;
int used;
+ pCode *pc1=NULL, *pc2=NULL;
while(fregs) {
- pCode *pcfl_used, *pcfl_assigned;
+ pCode *pcfl_used, *pcfl_assigned;
/* Step through the set by directly accessing the 'next' pointer.
* We could also step through by using the set API, but the
* instructions are examined. If possible, they're optimized out.
*/
- pCode *pc1, *pc2;
- pCode *pct1, *pct2; /* two temporaries */
- regs *reg1, *reg2;
-
/*
fprintf (stderr, "OptimizeRegUsage: %s addr=0x%03x rIdx=0x%03x type=%d used=%d\n",
reg->name,
if(pcfl_used->seq == pcfl_assigned->seq) {
//fprintf(stderr, " and used in same flow\n");
- if(pc2->seq < pc1->seq) {
- pct1 = pc2;
- pc2 = pc1;
- pc1 = pct1;
- }
-
- //pc1->print(stderr,pc1);
- //pc2->print(stderr,pc2);
-
-
- /* ADHOC pattern checking
- * Now look for specific sequences that are easy to optimize.
- * Many of these sequences are characteristic of the compiler
- * (i.e. it'd probably be a waste of time to apply these adhoc
- * checks to hand written assembly.)
- *
- */
- if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_MOVFW) ){
-
- /*
- clrf reg
- stuff...
- movf reg,w
-
- can be replaced with
-
- stuff...
- movlw 0
- */
-
- pCode *newpc;
- //fprintf(stderr, " CLRF/MOVFW. instruction after MOVFW is:\n");
- pct1 = findNextInstruction(pc2->next);
- //t->print(stderr,t);
-
- if(PCI(pct1)->op == POC_MOVWF) {
- newpc = newpCode(POC_CLRF, PCI(pct1)->pcop);
- pct1->destruct(pct1);
- } else {
- newpc = newpCode(POC_MOVLW, newpCodeOpLit(0));
- }
-
- pCodeInsertAfter(pc2, newpc);
- PCI(newpc)->pcflow = PCFL(pcfl_used);
- newpc->seq = pc2->seq;
- Remove2pcodes(pcfl_used, pc1, pc2, reg);
- total_registers_saved++; // debugging stats.
-
- } else if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_IORFW) ){
- //fprintf(stderr, " CLRF/IORWF.\n");
-
- Remove2pcodes(pcfl_used, pc1, pc2, reg);
- total_registers_saved++; // debugging stats.
-
- } else if(PCI(pc1)->op == POC_MOVWF) {
-
- pct2 = findNextInstruction(pc2->next);
-
- if(PCI(pc2)->op == POC_MOVFW) {
- //fprintf(stderr, " MOVWF/MOVFW. instruction after MOVFW is:\n");
- // t->print(stderr,t);
-
- if(PCI(pct2)->op == POC_MOVWF) {
- reg2 = getRegFromInstruction(pct2);
- if(reg2 && !regUsedinRange(pc1,pc2,reg2)) {
- pct2->seq = pc1->seq;
- unlinkpCode(pct2);
- pCodeInsertAfter(pc1,pct2);
- Remove2pcodes(pcfl_used, pc1, pc2, reg);
- total_registers_saved++; // debugging stats.
- continue;
- }
- }
- }
-
- pct1 = findPrevInstruction(pc1->prev);
- if(pct1 &&
- (PCI(pct1)->pcflow == PCI(pc1)->pcflow) &&
- (PCI(pct1)->op == POC_MOVFW)) {
-
- reg1 = getRegFromInstruction(pct1);
- if(reg1 && !regUsedinRange(pc1,pc2,reg1)) {
- //fprintf(stderr, " MOVF/MOVFW. \n");
- /*
- movf reg1,w
- movwf reg
-
- stuff...
- opcode reg,w
- */
- pct2 = newpCode(PCI(pc2)->op, PCI(pct1)->pcop);
- pCodeInsertAfter(pc2, pct2);
- PCI(pct2)->pcflow = PCFL(pcfl_used);
- pct2->seq = pc2->seq;
-
- Remove2pcodes(pcfl_used, pc1, pc2, reg);
- Remove2pcodes(pcfl_used, pct1, NULL, reg1);
- total_registers_saved++; // debugging stats.
-
- }
- }
-
-
- }
+ pCodeOptime2pCodes(pc1, pc2, pcfl_used, reg, 1,optimize_level);
} else {
// fprintf(stderr, " and used in different flows\n");
- //pc1->print(stderr,pc1);
- //pc2->print(stderr,pc2);
}
} else if(pcfl_used) {
} else {
//fprintf(stderr,"WARNING %s: reg %s assigned without being used\n",__FUNCTION__,reg->name);
- Remove2pcodes(pcfl_assigned, pc1, pc2, reg);
+ Remove2pcodes(pcfl_assigned, pc1, pc2, reg, 1);
total_registers_saved++; // debugging stats.
}
} else {
+ /* register has been used either once, or more than twice */
+
if(used && !pcfl_used && pcfl_assigned) {
pCode *pc;
reg->wasUsed = 0;
total_registers_saved++; // debugging stats.
- }
+ } else if( (used > 2) && optimize_multi_uses) {
+ set *rset1=NULL;
+ set *rset2=NULL;
+ int searching=1;
+
+ pCodeFlow *pcfl1=NULL, *pcfl2=NULL;
+
+ /* examine the number of times this register is used */
+
+
+ rset1 = reg->reglives.usedpCodes;
+ while(rset1 && searching) {
+
+ pc1 = rset1->item;
+ rset2 = rset1->next;
+
+ if(pc1 && isPCI(pc1) && ( (pcfl1 = PCI(pc1)->pcflow) != NULL) ) {
+
+ //while(rset2 && searching) {
+ if(rset2) {
+
+ pc2 = rset2->item;
+ if(pc2 && isPCI(pc2) && ( (pcfl2 = PCI(pc2)->pcflow) != NULL) ) {
+ if(pcfl2 == pcfl1) {
+
+ if(pCodeOptime2pCodes(pc1, pc2, pcfl_used, reg, 0,optimize_level))
+ searching = 0;
+ }
+ }
+
+ //rset2 = rset2->next;
+
+ }
+ }
+ rset1 = rset1->next;
+ }
+ }
}
}
/*-----------------------------------------------------------------*
* void pCodeRegOptimeRegUsage(pBlock *pb)
*-----------------------------------------------------------------*/
-void pCodeRegOptimizeRegUsage(void)
+void pCodeRegOptimizeRegUsage(int level)
{
- int passes = 4;
+ int passes;
int saved = 0;
+ int t = total_registers_saved;
+
+ if(!register_optimization)
+ return;
+#define OPT_PASSES 4
+ passes = OPT_PASSES;
do {
saved = total_registers_saved;
/* Identify registers used in one flow sequence */
- OptimizeRegUsage(dynAllocRegs);
- OptimizeRegUsage(dynStackRegs);
- OptimizeRegUsage(dynDirectRegs);
+ OptimizeRegUsage(dynAllocRegs,level, (OPT_PASSES-passes));
+ OptimizeRegUsage(dynStackRegs,level, (OPT_PASSES-passes));
+ OptimizeRegUsage(dynDirectRegs,0, (OPT_PASSES-passes));
if(total_registers_saved != saved)
- fprintf(stderr, " *** Saved %d registers, total saved %d ***\n", total_registers_saved-saved,total_registers_saved);
+ fprintf(stderr, " *** pass %d, Saved %d registers, total saved %d ***\n",
+ (1+OPT_PASSES-passes),total_registers_saved-saved,total_registers_saved);
+
+ passes--;
+
+ } while( passes && ((total_registers_saved != saved) || (passes==OPT_PASSES-1)) );
+
+ if(total_registers_saved == t)
+ fprintf(stderr, "No registers saved on this pass\n");
- } while( passes-- && (total_registers_saved != saved));
/*
fprintf(stderr,"dynamically allocated regs:\n");
dbg_regusage(dynAllocRegs);
fprintf(stderr,"direct regs:\n");
dbg_regusage(dynDirectRegs);
*/
+}
+
+
+/*-----------------------------------------------------------------*
+ * void RegsUnMapLiveRanges(set *regset)
+ *
+ *-----------------------------------------------------------------*/
+void RegsSetUnMapLiveRanges(set *regset)
+{
+ regs *reg;
+
+ while(regset) {
+ reg = regset->item;
+ regset = regset->next;
+
+
+ deleteSet(®->reglives.usedpCodes);
+ deleteSet(®->reglives.usedpFlows);
+ deleteSet(®->reglives.assignedpFlows);
+
+ }
+
+}
+
+void RegsUnMapLiveRanges(void)
+{
+ RegsSetUnMapLiveRanges(dynAllocRegs);
+ RegsSetUnMapLiveRanges(dynStackRegs);
+ RegsSetUnMapLiveRanges(dynDirectRegs);
+ RegsSetUnMapLiveRanges(dynProcessorRegs);
+ RegsSetUnMapLiveRanges(dynDirectBitRegs);
+ RegsSetUnMapLiveRanges(dynInternalRegs);
}