From 085eaef3aed957962961d27e50d47e3aba86b801 Mon Sep 17 00:00:00 2001 From: sdattalo Date: Sun, 23 Jun 2002 03:51:18 +0000 Subject: [PATCH] pCode live-range analysis algorithms have been added. git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@2026 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- ChangeLog | 12 +- src/SDCCset.c | 2 +- src/SDCCset.h | 1 + src/pic/device.c | 6 +- src/pic/glue.c | 2 +- src/pic/pcode.c | 92 +++++++----- src/pic/pcode.h | 31 +++- src/pic/pcodepeep.c | 5 +- src/pic/pcoderegs.c | 302 +++++++++++++++++++++++++++++++++++++++ src/pic/pcoderegs.h | 42 ++++++ src/pic/ralloc.c | 88 +++++++++--- src/pic/ralloc.h | 17 +++ support/scripts/inc2h.pl | 209 +++++++++++++++++++++++++++ 13 files changed, 740 insertions(+), 69 deletions(-) create mode 100644 src/pic/pcoderegs.c create mode 100644 src/pic/pcoderegs.h create mode 100755 support/scripts/inc2h.pl diff --git a/ChangeLog b/ChangeLog index 69d11c3b..79c96134 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,14 @@ -2002-05-10 Scott Dattal +2002-06-22 Scott Dattalo + * src/pic/*: Numerous bug fixes. Flow analysis has been enhanced. + - Rewrote the register banking algorithm. + - Added pCode live-range analysis to registers (for now, only non-used and + singly-used registers optimized away) + + * src/pic/pcoderegs.[ch]: Added new files for pCode live-range analysis + + * support/scripts/inc2h.pl Kevin L. Pauba submitted this perl script for converting MicroChip include files into SDCC Pic include files. + +2002-05-10 Scott Dattalo * src/pic/*: Added support for multiplication. Fixed many,many bugs. 2002-04-22 Michael Hope diff --git a/src/SDCCset.c b/src/SDCCset.c index 61b68a05..19babd6e 100644 --- a/src/SDCCset.c +++ b/src/SDCCset.c @@ -31,7 +31,7 @@ /* newSet - will allocate & return a new set entry */ /*-----------------------------------------------------------------*/ set * -newSet () +newSet (void) { set *lp; diff --git a/src/SDCCset.h b/src/SDCCset.h index e3f1520f..39328e63 100644 --- a/src/SDCCset.h +++ b/src/SDCCset.h @@ -54,6 +54,7 @@ set; #define V_ARG(type,var) type var = va_arg(ap,type) /* set related functions */ +set *newSet (void); void *addSet (set **, void *); void *addSetHead (set **, void *); void *getSet (set **); diff --git a/src/pic/device.c b/src/pic/device.c index bf465f38..b260f6f4 100644 --- a/src/pic/device.c +++ b/src/pic/device.c @@ -607,9 +607,9 @@ void assignRelocatableRegisters(set *regset, int used) for (reg = setFirstItem(regset) ; reg ; reg = setNextItem(regset)) { - // fprintf(stdout,"assigning %s\n",reg->name); + //fprintf(stdout,"assigning %s isFixed=%d, wasUsed=%d\n",reg->name,reg->isFixed,reg->wasUsed); - if((!reg->isFixed) && ( (used==0) || reg->wasUsed)) + if((!reg->isFixed) && ( used || reg->wasUsed)) address = assignRegister(reg,address); } @@ -630,7 +630,7 @@ void assignConfigWordValue(int address, int value) if(CONFIG_WORD_ADDRESS == address) config_word = value; - fprintf(stderr,"setting config word to 0x%x\n",value); + //fprintf(stderr,"setting config word to 0x%x\n",value); } /*-----------------------------------------------------------------* diff --git a/src/pic/glue.c b/src/pic/glue.c index c3248fdc..90cc028a 100644 --- a/src/pic/glue.c +++ b/src/pic/glue.c @@ -866,8 +866,8 @@ picglue () /* Put all variables into a cblock */ - writeUsedRegs(asmFile); AnalyzeBanking(); + writeUsedRegs(asmFile); /* create the overlay segments */ fprintf (asmFile, "%s", iComments2); diff --git a/src/pic/pcode.c b/src/pic/pcode.c index dce14196..bd5be723 100644 --- a/src/pic/pcode.c +++ b/src/pic/pcode.c @@ -78,26 +78,13 @@ static int functionInlining = 1; /* inline functions if nonzero */ static int GpCodeSequenceNumber = 1; static int GpcFlowSeq = 1; -#define isPCI(x) ((PCODE(x)->type == PC_OPCODE)) -#define isPCI_BRANCH(x) ((PCODE(x)->type == PC_OPCODE) && PCI(x)->isBranch) -#define isPCI_SKIP(x) ((PCODE(x)->type == PC_OPCODE) && PCI(x)->isSkip) -#define isPCI_BITSKIP(x)((PCODE(x)->type == PC_OPCODE) && PCI(x)->isSkip && PCI(x)->isBitInst) -#define isPCFL(x) ((PCODE(x)->type == PC_FLOW)) -#define isPCF(x) ((PCODE(x)->type == PC_FUNCTION)) -#define isPCL(x) ((PCODE(x)->type == PC_LABEL)) -#define isPCW(x) ((PCODE(x)->type == PC_WILD)) -#define isPCCS(x) ((PCODE(x)->type == PC_CSOURCE)) - -#define isCALL(x) ((isPCI(x)) && (PCI(x)->op == POC_CALL)) -#define isSTATUS_REG(r) ((r)->pc_type == PO_STATUS) - -#define isPCOLAB(x) ((PCOP(x)->type) == PO_LABEL) +extern void RemoveUnusedRegisters(void); /****************************************************************/ /* Forward declarations */ /****************************************************************/ -static void unlinkPC(pCode *pc); +void unlinkpCode(pCode *pc); #if 0 static void genericAnalyze(pCode *pc); static void AnalyzeGOTO(pCode *pc); @@ -119,6 +106,12 @@ void pBlockStats(FILE *of, pBlock *pb); extern void pCodeInsertAfter(pCode *pc1, pCode *pc2); extern pCodeOp *popCopyReg(pCodeOpReg *pc); pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval); +void pCodeRegMapLiveRanges(pBlock *pb); + + +/****************************************************************/ +/* PIC Instructions */ +/****************************************************************/ pCodeInstruction pciADDWF = { {PC_OPCODE, NULL, NULL, 0, NULL, @@ -410,7 +403,7 @@ pCodeInstruction pciCLRF = { 0,0, // dest, bit instruction 0,0, // branch, skip POC_NOP, - PCC_REGISTER, // inCond + PCC_NONE, // inCond PCC_REGISTER // outCond }; @@ -431,7 +424,7 @@ pCodeInstruction pciCLRW = { 0,0, // dest, bit instruction 0,0, // branch, skip POC_NOP, - PCC_W, // inCond + PCC_NONE, // inCond PCC_W // outCond }; @@ -1805,6 +1798,9 @@ pCode *newpCodeFlow(void ) pcflow->ToConflicts = 0; pcflow->end = NULL; + + pcflow->registers = newSet(); + return ( (pCode *)pcflow); } @@ -2322,7 +2318,7 @@ void printpBlock(FILE *of, pBlock *pb) /* */ /*-----------------------------------------------------------------*/ -static void unlinkPC(pCode *pc) +void unlinkpCode(pCode *pc) { @@ -2343,7 +2339,7 @@ static void genericDestruct(pCode *pc) { //fprintf(stderr,"warning, calling default pCode destructor\n"); - unlinkPC(pc); + unlinkpCode(pc); free(pc); @@ -2371,33 +2367,38 @@ char *get_op(pCodeOp *pcop,char *buffer, int size) regs *r; static char b[50]; char *s; - // int size; + int use_buffer = 1; // copy the string to the passed buffer pointer if(!buffer) { buffer = b; size = sizeof(b); + use_buffer = 0; // Don't bother copying the string to the buffer. } if(pcop) { switch(pcop->type) { case PO_INDF: case PO_FSR: - //fprintf(stderr,"get_op getting register name rIdx=%d\n",PCOR(pcc->pcop)->rIdx); - //r = pic14_regWithIdx(PCOR(pcc->pcop)->rIdx); - //return r->name; + if(use_buffer) { + SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name); + return buffer; + } return PCOR(pcop)->r->name; break; case PO_GPR_TEMP: r = pic14_regWithIdx(PCOR(pcop)->r->rIdx); - //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name); + + if(use_buffer) { + SAFE_snprintf(&buffer,&size,"%s",r->name); + return buffer; + } + return r->name; - // case PO_GPR_BIT: - // return PCOR(pcc->pcop)->r)->name; + case PO_IMMEDIATE: s = buffer; - //size = sizeof(buffer); - //fprintf(stderr,"PO_IMMEDIATE name = %s offset = %d\n",pcc->pcop->name,PCOI(pcc->pcop)->offset); + if(PCOI(pcop)->_const) { if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) { @@ -2432,8 +2433,13 @@ char *get_op(pCodeOp *pcop,char *buffer, int size) return buffer; default: - if (pcop->name) + if (pcop->name) { + if(use_buffer) { + SAFE_snprintf(&buffer,&size,"%s",pcop->name); + return buffer; + } return pcop->name; + } } } @@ -3093,7 +3099,7 @@ regs * getRegFromInstruction(pCode *pc) switch(PCI(pc)->pcop->type) { case PO_INDF: case PO_FSR: - return pic14_regWithIdx(PCOR(PCI(pc)->pcop)->rIdx); + return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0); case PO_BIT: case PO_GPR_TEMP: @@ -3160,10 +3166,11 @@ void AnalyzepBlock(pBlock *pb) if(!r) { /* register wasn't found */ - r = Safe_calloc(1, sizeof(regs)); - memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs)); - addSet(&pb->tregisters, r); - PCOR(PCI(pc)->pcop)->r = r; + //r = Safe_calloc(1, sizeof(regs)); + //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs)); + //addSet(&pb->tregisters, r); + addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r); + //PCOR(PCI(pc)->pcop)->r = r; //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx); }/* else fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx); @@ -3311,7 +3318,7 @@ void unBuildFlow(pBlock *pb) PCI(pc)->pcflow = NULL; pc = pcn; } else if(isPCFL(pc)) { - unlinkPC(pc); + unlinkpCode(pc); pc->destruct(pc); } else pc = pcn; @@ -4202,7 +4209,7 @@ void pBlockRemoveUnusedLabels(pBlock *pb) DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label)); if(pc->type == PC_LABEL) { - unlinkPC(pc); + unlinkpCode(pc); pCodeLabelDestruct(pc); } else { unlinkpCodeFromBranch(pc, PCODE(pcl)); @@ -4247,7 +4254,7 @@ void pBlockMergeLabels(pBlock *pb) pCode *pcn = pc->next; // Unlink the pCode label from it's pCode chain - unlinkPC(pc); + unlinkpCode(pc); //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key); // And link it into the instruction's pBranch labels. (Note, since @@ -4277,7 +4284,7 @@ void pBlockMergeLabels(pBlock *pb) pCode *pcn = pc->next; // Unlink the pCode label from it's pCode chain - unlinkPC(pc); + unlinkpCode(pc); PCI(pcnext)->cline = PCCS(pc); //fprintf(stderr, "merging CSRC\n"); //genericPrint(stderr,pcnext); @@ -4560,6 +4567,12 @@ void AnalyzeBanking(void) for(pb = the_pFile->pbHead; pb; pb = pb->next) FixBankFlow(pb); + + for(pb = the_pFile->pbHead; pb; pb = pb->next) + pCodeRegMapLiveRanges(pb); + + RemoveUnusedRegisters(); + /* for(pb = the_pFile->pbHead; pb; pb = pb->next) DumpFlow(pb); @@ -4668,7 +4681,8 @@ void buildCallTree(void ) /* Re-allocate the registers so that there are no collisions * between local variables when one function call another */ - pic14_deallocateAllRegs(); + // this is weird... + // pic14_deallocateAllRegs(); for(pb = the_pFile->pbHead; pb; pb = pb->next) { if(!pb->visited) diff --git a/src/pic/pcode.h b/src/pic/pcode.h index 8e4dd51a..9e6f9741 100644 --- a/src/pic/pcode.h +++ b/src/pic/pcode.h @@ -241,8 +241,11 @@ typedef enum /************************************************/ /*************** Structures ********************/ /************************************************/ +/* These are here as forward references - the + * full definition of these are below */ struct pCode; struct pCodeWildBlock; +struct pCodeRegLives; /************************************************* pBranch @@ -423,6 +426,7 @@ typedef struct pCodeCSource causes a branch, a Flow object will be inserted into the pCode chain to mark the beginning of the next contiguous chunk. + **************************************************/ typedef struct pCodeFlow @@ -451,6 +455,8 @@ typedef struct pCodeFlow int FromConflicts; int ToConflicts; + set *registers;/* Registers used in this flow */ + } pCodeFlow; /************************************************* @@ -710,7 +716,6 @@ typedef struct peepCommand { char *cmd; } peepCommand; - /************************************************* pCode Macros @@ -736,6 +741,25 @@ typedef struct peepCommand { #define PCWB(x) ((pCodeWildBlock *)(x)) + +/* + macros for checking pCode types +*/ +#define isPCI(x) ((PCODE(x)->type == PC_OPCODE)) +#define isPCI_BRANCH(x) ((PCODE(x)->type == PC_OPCODE) && PCI(x)->isBranch) +#define isPCI_SKIP(x) ((PCODE(x)->type == PC_OPCODE) && PCI(x)->isSkip) +#define isPCI_BITSKIP(x)((PCODE(x)->type == PC_OPCODE) && PCI(x)->isSkip && PCI(x)->isBitInst) +#define isPCFL(x) ((PCODE(x)->type == PC_FLOW)) +#define isPCF(x) ((PCODE(x)->type == PC_FUNCTION)) +#define isPCL(x) ((PCODE(x)->type == PC_LABEL)) +#define isPCW(x) ((PCODE(x)->type == PC_WILD)) +#define isPCCS(x) ((PCODE(x)->type == PC_CSOURCE)) + +#define isCALL(x) ((isPCI(x)) && (PCI(x)->op == POC_CALL)) +#define isSTATUS_REG(r) ((r)->pc_type == PO_STATUS) + +#define isPCOLAB(x) ((PCOP(x)->type) == PO_LABEL) + /*-----------------------------------------------------------------* * pCode functions. *-----------------------------------------------------------------*/ @@ -767,6 +791,11 @@ pCodeOp *newpCodeOpRegFromStr(char *name); pCodeOp *newpCodeOp(char *name, PIC_OPTYPE p); pCodeOp *pCodeOpCopy(pCodeOp *pcop); +pCode * findNextInstruction(pCode *pci); +pCode * findNextpCode(pCode *pc, PC_TYPE pct); +int isPCinFlow(pCode *pc, pCode *pcflow); +struct regs * getRegFromInstruction(pCode *pc); + extern void pcode_test(void); /*-----------------------------------------------------------------* diff --git a/src/pic/pcodepeep.c b/src/pic/pcodepeep.c index 2ba9fd1f..46a6b1d8 100644 --- a/src/pic/pcodepeep.c +++ b/src/pic/pcodepeep.c @@ -1405,7 +1405,8 @@ int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd) } b[0]=0; - get_op(pcops,b,sizeof(b)); + get_op(pcops,b,50); + n2 = get_op(pcopd,NULL,0); if( !n2 || strcmp(b,n2)) { @@ -1424,7 +1425,7 @@ int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd) break; } - // fprintf(stderr," - pass\n"); + //fprintf(stderr," - pass\n"); return 1; } diff --git a/src/pic/pcoderegs.c b/src/pic/pcoderegs.c new file mode 100644 index 00000000..efbddfa4 --- /dev/null +++ b/src/pic/pcoderegs.c @@ -0,0 +1,302 @@ +/*------------------------------------------------------------------------- + + pcoderegs.c - post code generation register optimizations + + Written By - Scott Dattalo scott@dattalo.com + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +-------------------------------------------------------------------------*/ + +/* + 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 "pcoderegs.h" +#include "pcodeflow.h" + +extern void dbg_dumpregusage(void); +void unlinkpCode(pCode *pc); + +/*-----------------------------------------------------------------* + * 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)) { + + 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"); + + } +} + +/*-----------------------------------------------------------------* + * + *-----------------------------------------------------------------*/ +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); + +} + + +/*-----------------------------------------------------------------* + * void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl) + *-----------------------------------------------------------------*/ +void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl) +{ + + pCode *pc=NULL; + pCode *pcprev=NULL; + + regs *reg; + + if(!pcfl) + return; + + + pc = findNextInstruction(pcfl->pc.next); + + while(isPCinFlow(pc,PCODE(pcfl))) { + + + reg = getRegFromInstruction(pc); + + if(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); +*/ + + addSetIfnotP(& (PCFL(pcfl)->registers), reg); + + if(PCC_REGISTER & PCI(pc)->inCond) + addSetIfnotP(& (reg->reglives.usedpFlows), pcfl); + + if(PCC_REGISTER & PCI(pc)->outCond) + addSetIfnotP(& (reg->reglives.assignedpFlows), pcfl); + + addSetIfnotP(& (reg->reglives.usedpCodes), pc); + } + + + pcprev = pc; + pc = findNextInstruction(pc->next); + + } + +} +/*-----------------------------------------------------------------* + * void pCodeRegMapLiveRanges(pBlock *pb) + *-----------------------------------------------------------------*/ +void pCodeRegMapLiveRanges(pBlock *pb) +{ + pCode *pcflow; + + for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); + pcflow != NULL; + pcflow = findNextpCode(pcflow->next, PC_FLOW) ) { + + if(!isPCFL(pcflow)) { + fprintf(stderr, "pCodeRegMapLiveRanges - pcflow is not a flow object "); + continue; + } + pCodeRegMapLiveRangesInFlow(PCFL(pcflow)); + } + + + 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); + while (r) { + //fprintf(stderr, " %s\n",r->name); + r = setNextItem(PCFL(pcflow)->registers); + + } + + } + + // dbg_dumpregusage(); + +} + + +/*-----------------------------------------------------------------* + * void RemoveRegsFromSet(set *regset) + * + *-----------------------------------------------------------------*/ +void RemoveRegsFromSet(set *regset) +{ + regs *reg; + int used; + for (reg = setFirstItem(regset) ; reg ; + reg = setNextItem(regset)) { + + + used = elementsInSet(reg->reglives.usedpCodes); + + if(used <= 1) { + + //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); + reg->isFree = 1; + reg->wasUsed = 0; + } else { + pCode *pc; + + //fprintf(stderr," reg %s used only once\n",reg->name); + + pc = setFirstItem(reg->reglives.usedpCodes); + if(isPCI(pc)) { + if(PCI(pc)->label) { + pCode *pcn = findNextInstruction(pc->next); + + if(pcn && PCI(pcn)->label) { + fprintf(stderr,"can't delete instruction with label...\n"); + pc->print(stderr,pc); + continue; + } + /* Move the label to the next instruction */ + + PCI(pcn)->label = PCI(pc)->label; + + } + + if(isPCI_SKIP(pc)) + fprintf(stderr, "WARNING, a skip instruction is being optimized out\n"); + + unlinkpCode(pc); + deleteSetItem (&(reg->reglives.usedpCodes),pc); + reg->isFree = 1; + reg->wasUsed = 0; + } + } + } + + } +} +/*-----------------------------------------------------------------* + * void RemoveUnusedRegisters(void) + * + *-----------------------------------------------------------------*/ +void RemoveUnusedRegisters(void) +{ + + + //fprintf(stderr,"InternalRegs:\n"); + RemoveRegsFromSet(dynInternalRegs); + //fprintf(stderr,"AllocRegs:\n"); + RemoveRegsFromSet(dynAllocRegs); + //fprintf(stderr,"StackRegs:\n"); + RemoveRegsFromSet(dynStackRegs); + + /* + don't do DirectRegs yet - there's a problem with arrays + //fprintf(stderr,"DirectRegs:\n"); + RemoveRegsFromSet(dynDirectRegs); + */ + //fprintf(stderr,"DirectBitRegs:\n"); + RemoveRegsFromSet(dynDirectBitRegs); + + + +} diff --git a/src/pic/pcoderegs.h b/src/pic/pcoderegs.h new file mode 100644 index 00000000..c37d72f4 --- /dev/null +++ b/src/pic/pcoderegs.h @@ -0,0 +1,42 @@ +/*------------------------------------------------------------------------- + + pcoderegs.h - post code generation register optimizations + + Written By - Scott Dattalo scott@dattalo.com + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +-------------------------------------------------------------------------*/ + +#ifndef __PCODEREGS_H__ +#define __PCODEREGS_H__ + +/************************************************* + + pCodeRegLives + + Records the set of registers used in a flow object. + +**************************************************/ + +typedef struct pCodeRegLives { + set *usedpFlows; /* set of pFlow objects that use this register */ + set *assignedpFlows; /* set of pFlow objects that assign values to this register */ + set *usedpCodes; /* set of all instructions that use this register */ + +} pCodeRegLives; + + +#endif // __PCODEREGS_H__ diff --git a/src/pic/ralloc.c b/src/pic/ralloc.c index f417f064..e8394512 100644 --- a/src/pic/ralloc.c +++ b/src/pic/ralloc.c @@ -45,6 +45,7 @@ /*-----------------------------------------------------------------*/ extern void genpic14Code (iCode *); +extern void assignConfigWordValue(int address, int value); /* Global data */ static struct @@ -64,12 +65,12 @@ _G; int pic14_ptrRegReq; /* one byte pointer register required */ -static set *dynAllocRegs=NULL; -static set *dynStackRegs=NULL; -static set *dynProcessorRegs=NULL; -static set *dynDirectRegs=NULL; -static set *dynDirectBitRegs=NULL; -static set *dynInternalRegs=NULL; +set *dynAllocRegs=NULL; +set *dynStackRegs=NULL; +set *dynProcessorRegs=NULL; +set *dynDirectRegs=NULL; +set *dynDirectBitRegs=NULL; +set *dynInternalRegs=NULL; static hTab *dynDirectRegNames= NULL; @@ -440,6 +441,8 @@ static regs* newReg(short type, short pc_type, int rIdx, char *name, int size, i dReg->size = size; dReg->alias = alias; dReg->reg_alias = NULL; + dReg->reglives.usedpFlows = newSet(); + dReg->reglives.assignedpFlows = newSet(); return dReg; } @@ -711,7 +714,7 @@ allocRegByName (char *name, int size) /*-----------------------------------------------------------------*/ /* RegWithIdx - returns pointer to register with index number */ /*-----------------------------------------------------------------*/ -static regs * +regs * typeRegWithIdx (int idx, int type, int fixed) { @@ -719,6 +722,40 @@ typeRegWithIdx (int idx, int type, int fixed) debugLog ("%s - requesting index = 0x%x\n", __FUNCTION__,idx); + switch (type) { + + case REG_GPR: + if( (dReg = regWithIdx ( dynAllocRegs, idx, fixed)) != NULL) { + + debugLog ("Found a Dynamic Register!\n"); + return dReg; + } + if( (dReg = regWithIdx ( dynDirectRegs, idx, fixed)) != NULL ) { + debugLog ("Found a Direct Register!\n"); + return dReg; + } + + break; + case REG_STK: + if( (dReg = regWithIdx ( dynStackRegs, idx, fixed)) != NULL ) { + debugLog ("Found a Stack Register!\n"); + return dReg; + } + break; + case REG_SFR: + if( (dReg = regWithIdx ( dynProcessorRegs, idx, fixed)) != NULL ) { + debugLog ("Found a Processor Register!\n"); + return dReg; + } + + case REG_CND: + case REG_PTR: + default: + break; + } + +#if 0 + if( (dReg = regWithIdx ( dynAllocRegs, idx, fixed)) != NULL) { debugLog ("Found a Dynamic Register!\n"); @@ -739,18 +776,15 @@ typeRegWithIdx (int idx, int type, int fixed) debugLog ("Found a Processor Register!\n"); return dReg; } -/* - if( (dReg = regWithIdx ( dynDirectBitRegs, idx, fixed)) != NULL ) { +#endif + + /* + if( (dReg = regWithIdx ( dynDirectBitRegs, idx, fixed)) != NULL ) { debugLog ("Found a bit Register!\n"); return dReg; - } -*/ -/* - fprintf(stderr,"%s %d - requested register: 0x%x\n",__FUNCTION__,__LINE__,idx); - werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - "regWithIdx not found"); - exit (1); -*/ + } + */ + return NULL; } @@ -760,8 +794,18 @@ typeRegWithIdx (int idx, int type, int fixed) regs * pic14_regWithIdx (int idx) { + regs *dReg; + + if( (dReg = typeRegWithIdx(idx,REG_GPR,0)) != NULL) + return dReg; + + if( (dReg = typeRegWithIdx(idx,REG_SFR,0)) != NULL) + return dReg; + + if( (dReg = typeRegWithIdx(idx,REG_STK,0)) != NULL) + return dReg; - return typeRegWithIdx(idx,-1,0); + return NULL; } /*-----------------------------------------------------------------*/ @@ -1001,7 +1045,7 @@ void aliasEQUs(FILE *of, set *fregs) for (reg = setFirstItem(fregs) ; reg ; reg = setNextItem(fregs)) { - if(!reg->isEmitted) + if(!reg->isEmitted && reg->wasUsed) fprintf (of, "%s\tEQU\t0x%03x\n", reg->name, reg->address); @@ -1017,7 +1061,7 @@ void writeUsedRegs(FILE *of) assignFixedRegisters(dynStackRegs); assignFixedRegisters(dynDirectRegs); - assignRelocatableRegisters(dynInternalRegs,1); + assignRelocatableRegisters(dynInternalRegs,0); assignRelocatableRegisters(dynAllocRegs,0); assignRelocatableRegisters(dynStackRegs,0); assignRelocatableRegisters(dynDirectRegs,0); @@ -1031,6 +1075,7 @@ void writeUsedRegs(FILE *of) aliasEQUs(of,dynStackRegs); } + #if 0 /*-----------------------------------------------------------------*/ /* allDefsOutOfRange - all definitions are out of a range */ @@ -2467,6 +2512,7 @@ DEFSETFUNC (markRegFree) DEFSETFUNC (deallocReg) { + fprintf(stderr,"deallocting register %s\n",((regs *)item)->name); ((regs *)item)->isFree = 1; ((regs *)item)->wasUsed = 0; @@ -3765,7 +3811,7 @@ pic14_assignRegisters (eBBlock ** ebbs, int count) setToNull ((void **) &_G.stackSpil); setToNull ((void **) &_G.spiltSet); /* mark all registers as free */ - pic14_freeAllRegs (); + //pic14_freeAllRegs (); debugLog ("leaving\n<><><><><><><><><><><><><><><><><>\n"); debugLogClose (); diff --git a/src/pic/ralloc.h b/src/pic/ralloc.h index f8af1de2..4e49651b 100644 --- a/src/pic/ralloc.h +++ b/src/pic/ralloc.h @@ -28,6 +28,7 @@ #ifndef SDCCRALLOC_H #define SDCCRALLOC_H 1 +#include "pcoderegs.h" enum @@ -68,18 +69,34 @@ typedef struct regs unsigned alias; /* Alias mask if register appears in multiple banks */ struct regs *reg_alias; /* If more than one register share the same address * then they'll point to each other. (primarily for bits)*/ + pCodeRegLives reglives; /* live range mapping */ } regs; extern regs regspic14[]; extern int pic14_nRegs; extern int Gstack_base_addr; +/* + As registers are created, they're added to a set (based on the + register type). Here are the sets of registers that are supported + in the PIC port: +*/ +extern set *dynAllocRegs; +extern set *dynStackRegs; +extern set *dynProcessorRegs; +extern set *dynDirectRegs; +extern set *dynDirectBitRegs; +extern set *dynInternalRegs; + + regs *pic14_regWithIdx (int); regs *dirregWithName (char *name ); void pic14_freeAllRegs (); void pic14_deallocateAllRegs (); regs *pic14_findFreeReg(short type); regs *pic14_allocWithIdx (int idx); +regs *typeRegWithIdx (int idx, int type, int fixed); + regs *allocDirReg (operand *op ); regs *allocRegByName (char *name, int size ); diff --git a/support/scripts/inc2h.pl b/support/scripts/inc2h.pl new file mode 100755 index 00000000..d586ed94 --- /dev/null +++ b/support/scripts/inc2h.pl @@ -0,0 +1,209 @@ +#!/usr/bin/perl + +# Copyright (c) 2002 Kevin L. Pauba + + +# License: +# +# SDCC is licensed under the GNU Public license (GPL) v2. Note that +# this license covers the code to the compiler and other executables, +# but explicitly does not cover any code or objects generated by sdcc. +# We have not yet decided on a license for the run time libraries, but +# it will not put any requirements on code linked against it. See: +# +# http://www.gnu.org/copyleft/gpl.html +# +# See http://sdcc.sourceforge.net/ for the latest information on sdcc. + + +$rcsid = q~$Id$~; +($junk, $file, $version, $date, $time, $programmer, $status) + = split(/\s+/, $rcsid); +($programName) = ($file =~ /(\S+),v/); + +if ($#ARGV != 0) { + Usage(); +} + +# +# Read the symbols at the end of this file. +# +while () { + next if /^\s*#/; + + if (/^alias\s+(\S+)\s+(\S+)/) { + # + # Set an alias for a special function register. + # Some MPASM include files are not entirely consistent + # with sfr names. + # + $alias{$2} = $1; + } elsif (/^address\s+(\S+)\s+(\S+)/) { + # + # Set a default address for a special function register. + # Some MPASM include files don't specify the address + # of all registers. + # + $addr{"$1"} = $2; + } elsif (/^(\S+)/) { + $type = $1; + } else { + foreach $key (split) { + eval "\$type{'$key'} = $type;"; + } + } +} + +# +# Print the header. +# +print <) { + if (/^;-* (\S+) Bits/i) { + if (defined($alias{$1})) { + $defaultType = "bits $alias{$1}"; + } else { + $defaultType = "bits $1"; + } + s/;/\/\//; + print "$_"; + } elsif (/^;-* Register Files/i) { + $defaultType = 'sfr'; + s/;/\/\//; + print "$_"; + } elsif (/^;=*/i) { + $defaultType = ''; + s/;/\/\//; + print "$_"; + } elsif (/^\s*;/) { + # + # Convert ASM comments to C style. + # + print "//$'"; + } elsif (/^\s*IFNDEF __(\S+)/) { + # + # Processor type. + # + $processor = $1; + print "//$_"; + } elsif (/^\s*(\S+)\s+EQU\s+H'(.+)'/) { + # + # Useful bit of information. + # + $name = $1; + $value = $2; + $rest = $'; + $rest =~ s/;/\/\//; + chomp($rest); + + if (defined($type{"$name"})) { + $type = $type{"$name"}; + } else { + $type = $defaultType; + } + + if ($type eq 'sfr') { + # + # A special function register. + # + printf("sfr at 0x%s %s;$rest\n", $value, $name); + $addr{"$name"} = "0x$value"; + } elsif ($type eq 'volatile') { + # + # A location that can change without + # direct program manipulation. + # + printf("data at 0x%s volatile char %s;$rest\n", $value, $name); + } elsif ($type =~ /^bits/) { + ($junk, $register) = split(/\s/, $type); + $bit = hex($value); + $addr = $addr{"$register"}; + printf("BIT_AT($addr,$bit) $name;$rest\n"); + } else { + # + # Other registers, bits and/or configurations. + # + if ($type eq 'other') { + # + # A known symbol. + # + printf("#define %-20s 0x%s$rest\n", $name, $value); + } else { + # + # A symbol that isn't defined in the data + # section at the end of the file. Let's + # add a comment so that we can add it later. + # + printf("#define %-20s 0x%s$rest\n", + $name, $value); + } + } + } elsif (/^\s*$/) { + # + # Blank line. + # + print; + } else { + # + # Anything else we'll just comment out. + # + print "// $_"; + } +} + +sub Usage { + print STDERR <