#include "pcodeflow.h"
extern void pCodeInsertAfter(pCode *pc1, pCode *pc2);
+extern void pCodeInsertBefore(pCode *pc1, pCode *pc2);
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);
+char *pCode2str(char *str, int size, pCode *pc);
+void SAFE_snprintf(char **str, size_t *size, const char *format, ...);
int total_registers_saved=0;
+int register_optimization=1;
/*-----------------------------------------------------------------*
* void AddRegToFlow(regs *reg, pCodeFlow *pcfl)
/*-----------------------------------------------------------------*
*
*-----------------------------------------------------------------*/
-static void Remove1pcode(pCode *pc, regs *reg)
+static void Remove1pcode(pCode *pc, regs *reg, int debug_code)
{
+
pCode *pcn=NULL;
if(!reg || !pc)
return;
deleteSetItem (&(reg->reglives.usedpCodes),pc);
-/*
- fprintf(stderr,"removing instruction:\n");
- pc->print(stderr,pc);
-*/
+
if(PCI(pc)->label) {
pcn = findNextInstruction(pc->next);
}
}
+
+ 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;
+
+ SAFE_snprintf(ppbuff,&size, ";%d", debug_code);
+ pCode2str(*ppbuff, size, pc);
+ pCodeInsertBefore(pc, newpCodeCharP(buff1));
+ //fprintf(stderr,"removing instruction:\n%s\n",buff1);
+ }
+
pc->destruct(pc);
}
pc = setFirstItem(reg->reglives.usedpCodes);
- if(reg->type == REG_SFR) {
+ if(reg->type == REG_SFR || reg->type == REG_STK) {
//fprintf(stderr, "not removing SFR reg %s even though used only once\n",reg->name);
continue;
}
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);
+ Remove1pcode(pc, reg, 1);
/*
unlinkpCode(pc);
deleteSetItem (&(reg->reglives.usedpCodes),pc);
{
/* 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, int can_free)
{
+ static int debug_code=99;
if(!reg)
return;
+ //fprintf(stderr,"%s\n",__FUNCTION__);
if(pc1)
- Remove1pcode(pc1, reg);
+ Remove1pcode(pc1, reg, debug_code++);
if(pc2) {
- Remove1pcode(pc2, reg);
+ Remove1pcode(pc2, reg, debug_code++);
deleteSetItem (&(PCFL(pcflow)->registers), reg);
if(can_free) {
*
*
*-----------------------------------------------------------------*/
-int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *reg, int can_free)
+int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *reg, int can_free, int optimize_level)
{
pCode *pct1, *pct2;
regs *reg1, *reg2;
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) ){
/*
*/
pCode *newpc;
- //fprintf(stderr, " CLRF/MOVFW. instruction after MOVFW is:\n");
+ 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);
total_registers_saved++; // debugging stats.
} else if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_IORFW) ){
- //fprintf(stderr, " CLRF/IORFW.\n");
+ 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.
pct2 = findNextInstruction(pc2->next);
if(PCI(pc2)->op == POC_MOVFW) {
- //fprintf(stderr, " MOVWF/MOVFW. instruction after MOVFW is:\n");
- //pct2->print(stderr,pct2);
+ /*
+ 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)) {
- pct2->seq = pc1->seq;
- unlinkpCode(pct2);
- pCodeInsertAfter(pc1,pct2);
- Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
- total_registers_saved++; // debugging stats.
- return 1;
+ //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);
+ fprintf(stderr,"ABCD\n");
+ 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");
}
pct1 = findPrevInstruction(pc1->prev);
- if(pct1 &&
- (PCI(pct1)->pcflow == PCI(pc1)->pcflow) &&
- (PCI(pct1)->op == POC_MOVFW)) {
+ if(pct1 && (PCI(pct1)->pcflow == PCI(pc1)->pcflow)) {
- reg1 = getRegFromInstruction(pct1);
- if(reg1 && !regUsedinRange(pc1,pc2,reg1)) {
- //fprintf(stderr, " MOVF/MOVFW. \n");
- /*
- movf reg1,w
- movwf reg
+ if ( (PCI(pct1)->op == POC_MOVFW) &&
+ (PCI(pc2)->op == POC_MOVFW)) {
- 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;
+ reg1 = getRegFromInstruction(pct1);
+ if(reg1 && !regUsedinRange(pc1,pc2,reg1)) {
+ /*
+ fprintf(stderr, " MOVF/MOVFW. \n");
+ fprintf(stderr, " ...optimizing\n");
+ */
- Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
- Remove2pcodes(pcfl_used, pct1, NULL, reg1, 0);
- total_registers_saved++; // debugging stats.
+ /*
+ 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, int optimize_multi_uses)
+void OptimizeRegUsage(set *fregs, int optimize_multi_uses, int optimize_level)
{
regs *reg;
int used;
reg = fregs->item;
fregs = fregs->next;
- if(reg->type == REG_SFR) {
+ if(reg->type == REG_SFR || reg->type == REG_STK) {
//fprintf(stderr,"skipping SFR: %s\n",reg->name);
continue;
}
//fprintf(stderr, " and used in same flow\n");
- pCodeOptime2pCodes(pc1, pc2, pcfl_used, reg, 1);
+ pCodeOptime2pCodes(pc1, pc2, pcfl_used, reg, 1,optimize_level);
} else {
// fprintf(stderr, " and used in different flows\n");
/*
register has been used twice without ever being assigned */
- //fprintf(stderr,"WARNING %s: reg %s used without being assigned\n",__FUNCTION__,reg->name);
+ 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.
}
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) {
pcfl_assigned = PCODE(PCI(pc)->pcflow);
- Remove1pcode(pc, reg);
+ Remove1pcode(pc, reg,2);
deleteSetItem (&(PCFL(pcfl_assigned)->registers), reg);
/*
if(pc1 && isPCI(pc1) && ( (pcfl1 = PCI(pc1)->pcflow) != NULL) ) {
- while(rset2 && searching) {
+ //while(rset2 && searching) {
+ if(rset2) {
pc2 = rset2->item;
if(pc2 && isPCI(pc2) && ( (pcfl2 = PCI(pc2)->pcflow) != NULL) ) {
if(pcfl2 == pcfl1) {
-/*
- fprintf(stderr, " two instruction in same flow\n");
- pc1->print(stderr, pc1);
- pc2->print(stderr, pc2);
-*/
- //if(pCodeOptime2pCodes(pc1, pc2, pcfl_used, reg, 1))
- // searching = 0;
+
+ if(pCodeOptime2pCodes(pc1, pc2, pcfl_used, reg, 0,optimize_level))
+ searching = 0;
}
}
- rset2 = rset2->next;
+ //rset2 = rset2->next;
}
}
/*-----------------------------------------------------------------*
* void pCodeRegOptimeRegUsage(pBlock *pb)
*-----------------------------------------------------------------*/
-void pCodeRegOptimizeRegUsage(void)
+void pCodeRegOptimizeRegUsage(int level)
{
int passes;
int saved = 0;
int t = total_registers_saved;
- int optimize_multi = 0;
-
- do {
- passes = 4;
- //fprintf(stderr, " multi opti %d\n",optimize_multi);
+ if(!register_optimization)
+ return;
+#define OPT_PASSES 4
+ passes = OPT_PASSES;
- do {
- saved = total_registers_saved;
+ do {
+ saved = total_registers_saved;
- /* Identify registers used in one flow sequence */
- OptimizeRegUsage(dynAllocRegs,optimize_multi);
- OptimizeRegUsage(dynStackRegs,0);
- OptimizeRegUsage(dynDirectRegs,0);
+ /* Identify registers used in one flow sequence */
+ 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);
+ 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);
+ passes--;
- } while( passes-- && (total_registers_saved != saved));
-
- optimize_multi++;
- } while (optimize_multi < 2);
+ } while( passes && ((total_registers_saved != saved) || (passes==OPT_PASSES-1)) );
if(total_registers_saved == t)
fprintf(stderr, "No registers saved on this pass\n");