* device/lib/pic/libsdcc/fs2ulong.c, device/lib/pic/libsdcc/fsadd.c,
[fw/sdcc] / src / pic / pcoderegs.c
index 2f489e3e63cb6a5a2fea1b6faae7abfe153de672..c115b3213ab9df8b8d6a7a56cd79eec6a74d6b47 100644 (file)
@@ -26,130 +26,23 @@ pcoderegs.c
   The purpose of the code in this file is to optimize the register usage.
 
 */
-#include <stdio.h>
 
-#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 "ralloc.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, ...);
-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");
-               }
-       }
-}
-
-/*-----------------------------------------------------------------*
-* 
-*-----------------------------------------------------------------*/
-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;
-       pCode *pcprev=NULL;
        
        regs *reg;
        
@@ -159,11 +52,21 @@ void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl)
        
        pc = findNextInstruction(pcfl->pc.next);
        
-       while(isPCinFlow(pc,PCODE(pcfl))) {
-               
-               
+       while(pc && !isPCFL(pc)) {
+               while (pc && !isPCI(pc) && !isPCFL(pc))
+               {
+                       pc = pc->next;
+               } // while
+               if (!pc || isPCFL(pc)) continue;
+               assert( isPCI(pc) );
+
                reg = getRegFromInstruction(pc);
-               
+               #if 0
+               pc->print(stderr, pc);
+               fprintf( stderr, "--> reg %p (%s,%u), inCond/outCond: %x/%x\n",
+                       reg, reg ? reg->name : "(null)", reg ? reg->rIdx : -1,
+                       PCI(pc)->inCond, PCI(pc)->outCond );
+               #endif
                if(reg) {
                /*
                fprintf(stderr, "flow seq %d, inst seq %d  %s  ",PCODE(pcfl)->seq,pc->seq,reg->name);
@@ -173,21 +76,22 @@ void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl)
                        
                        addSetIfnotP(& (PCFL(pcfl)->registers), reg);
                        
-                       if((PCC_REGISTER | PCC_LITERAL) & PCI(pc)->inCond)
+                       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);
+                       reg->wasUsed = 1;
                }
                
                
-               pcprev = pc;
-               pc = findNextInstruction(pc->next);
+               //pc = findNextInstruction(pc->next);
+               pc = pc->next;
                
        }
-       
+
 }
 
 /*-----------------------------------------------------------------*
@@ -225,8 +129,6 @@ void pCodeRegMapLiveRanges(pBlock *pb)
        }
 #endif
        
-       //  dbg_dumpregusage();
-       
 }
 
 
@@ -235,7 +137,7 @@ void pCodeRegMapLiveRanges(pBlock *pb)
 *-----------------------------------------------------------------*/
 static void Remove1pcode(pCode *pc, regs *reg, int debug_code)
 {
-       
+
        pCode *pcn=NULL;
        
        if(!reg || !pc)
@@ -265,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);
        }
@@ -291,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;
@@ -357,6 +260,31 @@ void  RemoveRegsFromSet(set *regset)
                
        }
 }
+
+static void pic14_ReMapLiveRanges(void)
+{
+       pBlock *pb;
+       if (!the_pFile) return;
+       RegsUnMapLiveRanges();
+       for (pb = the_pFile->pbHead; pb; pb = pb->next)
+       {
+       #if 0
+               pCode *pc = findNextpCode(pb->pcHead, PC_FLOW);
+               if (pc) {
+                       pc->print( stderr, pc );
+               } else {
+                       fprintf( stderr, "unnamed pBlock\n");
+               }
+               pc = findNextInstruction(pb->pcHead);
+               while (pc) {
+                 pc->print( stderr, pc );
+                 pc = findNextInstruction(pc->next);;
+               }
+       #endif  
+               pCodeRegMapLiveRanges(pb);
+       } // for
+}
+
 /*-----------------------------------------------------------------*
 * void RemoveUnusedRegisters(void)
 *
@@ -364,6 +292,7 @@ void  RemoveRegsFromSet(set *regset)
 void RemoveUnusedRegisters(void)
 {
        /* First, get rid of registers that are used only one time */
+       pic14_ReMapLiveRanges();
        
        //RemoveRegsFromSet(dynInternalRegs);
        RemoveRegsFromSet(dynAllocRegs);
@@ -413,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;
@@ -435,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;
 
@@ -455,28 +384,37 @@ int regIsSpecial (regs *reg, int mayBeGlobal)
 * 
 *
 *-----------------------------------------------------------------*/
-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;
        
        int t = total_registers_saved;
+
+       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;
        
        //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...
@@ -489,40 +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) > 0;
-               }
-               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);
                
-               if(pCodeSearchCondition(pct2, PCC_Z,0) > 0) {
+               /* 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);
@@ -560,7 +484,9 @@ int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *reg, int
                                if (reg2 && !regIsSpecial (reg2, 1) && !regUsedinRange(pc1,pc2,reg2)) {
                                        pCode *pct3 = findNextInstruction(pct2->next);
                                        /* Check following instructions are not relying on the use of W or the Z flag condiction */
-                                       if ((pCodeSearchCondition(pct3,PCC_Z,0) < 1) || (pCodeSearchCondition(pct3,PCC_W,0) < 1)) {
+                                       /* XXX: We must ensure that this value is destroyed before use---otherwise it might be used in
+                                        *      subsequent flows (checking for < 1 is insufficient). */
+                                       if ((pCodeSearchCondition(pct3,PCC_Z,0) == -1) && (pCodeSearchCondition(pct3,PCC_W,0) == -1)) {
                                                DFPRINTF((stderr, "   optimising MOVF reg ... MOVF reg,W MOVWF reg2 to MOVWF reg2 ...\n"));
                                                pct2->seq = pc1->seq;
                                                unlinkpCode(pct2);
@@ -644,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;
@@ -666,11 +592,23 @@ void OptimizeRegUsage(set *fregs, int optimize_multi_uses, int optimize_level)
                fprintf(stderr,"Reg: %s\n",reg->name);
                */
                
+               /* Catch inconsistently set-up live ranges
+                * (see tracker items #1469504 + #1474602)
+                * FIXME: Actually we should rather fix the
+                * computation of the liveranges instead...
+                */
+               if (!reg || !reg->reglives.usedpFlows
+                       || !reg->reglives.assignedpFlows)
+               {
+                 //fprintf( stderr, "skipping reg w/o liveranges: %s\n", reg ? reg->name : "(unknown)");
+                 continue;
+               }
+
                if(reg->type == REG_SFR || reg->type == REG_STK || reg->isPublic || reg->isExtern|| reg->isFixed) {
                        //fprintf(stderr,"skipping SFR: %s\n",reg->name);
                        continue;
                }
-               
+
                pcfl_used = setFirstItem(reg->reglives.usedpFlows);
                pcfl_assigned = setFirstItem(reg->reglives.assignedpFlows);
                
@@ -765,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;
@@ -781,7 +718,7 @@ void OptimizeRegUsage(set *fregs, int optimize_multi_uses, int optimize_level)
                                                        
                                                }
                                        }
-                                       rset1 = rset1->next;
+                                       rset1 = rset2;
                                }
                        }
                }
@@ -797,7 +734,14 @@ void pCodeRegOptimizeRegUsage(int level)
        int passes;
        int saved = 0;
        int t = total_registers_saved;
-       
+
+#if 0
+       /* This is currently broken (need rewrite to correctly
+        * handle arbitrary pCodeOps instead of registers only). */
+       if (!pic14_options.disable_df)
+               optimizeDataflow ();
+#endif
+
        if(!register_optimization)
                return;
 #define OPT_PASSES 4
@@ -821,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);
-       */
 }
 
 
@@ -838,7 +772,7 @@ void pCodeRegOptimizeRegUsage(int level)
 * void RegsUnMapLiveRanges(set *regset)
 *
 *-----------------------------------------------------------------*/
-void  RegsSetUnMapLiveRanges(set *regset)
+static void RegsSetUnMapLiveRanges(set *regset)
 {
        regs *reg;