* src/pic16/glue.c (printIvalChar): fixed bug when emitting
[fw/sdcc] / src / pic16 / pcoderegs.c
index ba0098a9c4a2105d16b7427704ed43654b1db8e1..c823dd296dd9900a71d67e04b7b61b3b67324993 100644 (file)
@@ -167,7 +167,8 @@ static void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl)
 
     reg = pic16_getRegFromInstruction(pc);
 
-    if(reg) {
+    if(reg && (reg->type != REG_TMP)) {
+
 #if 0
       fprintf(stderr, "reg= %p\n", reg);
       fprintf(stderr, "flow seq %d, inst seq %d  %s  ",PCODE(pcfl)->seq,pc->seq,reg->name);
@@ -177,7 +178,7 @@ static void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl)
              
 #endif
 
-//      fprintf(stderr, "trying to get first operand from pCode reg= %s\n", reg->name);
+//      fprintf(stderr, "%s:%d: trying to get first operand from pCode reg= %s\n", __FILE__, __LINE__, reg->name);
       addSetIfnotP(& (PCFL(pcfl)->registers), reg);
 
       if((PCC_REGISTER | PCC_LITERAL) & PCI(pc)->inCond)
@@ -194,7 +195,7 @@ static void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl)
        if(PCI(pc)->is2MemOp) {
                        reg = pic16_getRegFromInstruction2(pc);
                        if(reg) {
-//                             fprintf(stderr, "trying to get second operand from pCode reg= %s\n", reg->name);
+//                             fprintf(stderr, "%s:%d: trying to get second operand from pCode reg= %s\n", __FILE__, __LINE__, reg->name);
                                addSetIfnotP(& (PCFL(pcfl)->registers), reg);
 
                                if((PCC_REGISTER | PCC_LITERAL) & PCI(pc)->inCond)
@@ -288,8 +289,10 @@ static void Remove1pcode(pCode *pc, regs *reg)
 
     if(pcn) {
       if(PCI(pcn)->cline) {
-       //fprintf(stderr, "source line has been optimized completely out\n");
-       //pc->print(stderr,pc);
+#if 0
+       fprintf(stderr, "source line has been optimized completely out\n");
+       pc->print(stderr,pc);
+#endif
       } else {
        PCI(pcn)->cline = PCI(pc)->cline;
       }
@@ -358,6 +361,9 @@ static void  RemoveRegsFromSet(set *regset)
            fprintf(stderr,"reg %s, type =%d\n",r->name, r->type);
          }
 
+
+         pc->print(stderr, pc);
+
          fprintf(stderr,"%s:%d: removing reg %s because it is used only once\n",__FILE__, __LINE__, reg->name);
 
 
@@ -396,6 +402,68 @@ void pic16_RemoveUnusedRegisters(void)
        fprintf(stderr, " *** Saved %d registers ***\n", total_registers_saved);
 }
 
+static int insideLRBlock(pCode *pc)
+{
+  pCode *pc1;
+  int t1=-1, t2=-1;
+
+    pc1 = pc->prev;
+    while(pc1) {
+      if(isPCINFO(pc1) && (PCINF(pc1)->type == INF_LOCALREGS)) {
+        t1 = PCOLR (PCINF (pc1)->oper1)->type;
+        break;
+      }
+      pc1 = pc1->prev;
+    }
+    
+    pc1 = pc->next;
+    while(pc1) {
+      if(isPCINFO(pc1) && (PCINF(pc1)->type == INF_LOCALREGS)) {
+        t2 = PCOLR (PCINF (pc1)->oper1)->type;
+        break;
+      }
+      pc1 = pc1->next;
+    }
+    
+    if((t1 == LR_ENTRY_BEGIN && t2 == LR_ENTRY_END)
+      || (t1 == LR_EXIT_BEGIN && t2 == LR_EXIT_END))
+        return 1;
+
+  return 0;
+}
+
+    
+static void RemoveRegFromLRBlock(regs *reg)
+{
+  if(elementsInSet(reg->reglives.usedpCodes) == 2) {
+    pCode *pc1;
+
+      /* only continue if there are just 2 uses of the register,
+       * in in the local *entry* block and one in the local *exit* block */
+        
+      /* search for entry block */
+      pc1 = indexSet(reg->reglives.usedpCodes, 1);
+
+      if(insideLRBlock( pc1 )) {
+        fprintf(stderr, "usedpCodes[0] inside LR block\n");
+        deleteSetItem(&pc1->pb->tregisters, PCOR(PCI(pc1)->pcop)->r);
+        Remove1pcode(pc1, reg);
+      }
+
+      pc1 = indexSet(reg->reglives.usedpCodes, 0);
+      if(insideLRBlock( pc1 )) {
+        fprintf(stderr, "usedpCodes[1] inside LR block\n");
+        deleteSetItem(&pc1->pb->tregisters, PCOR(PCI(pc1)->pcop)->r);
+        Remove1pcode(pc1, reg);
+      }
+        
+      /* remove r0x00 */
+      reg->isFree = 1;
+      reg->wasUsed = 0;
+  }
+}
+
+        
 
 /*-----------------------------------------------------------------*
  *
@@ -426,6 +494,15 @@ static void Remove2pcodes(pCode *pcflow, pCode *pc1, pCode *pc2, regs *reg, int
   }
 
   pCodeRegMapLiveRangesInFlow(PCFL(pcflow));
+  
+#if 1
+//  fprintf(stderr, "register %s is used in %d pCodes, assigned in %d pCodes\n", reg->name,
+//      elementsInSet(reg->reglives.usedpCodes),
+//      elementsInSet(reg->reglives.assignedpFlows));
+  
+  RemoveRegFromLRBlock(reg);
+#endif
+  
 }
 
 /*-----------------------------------------------------------------*
@@ -442,6 +519,13 @@ static int regUsedinRange(pCode *pc1, pCode *pc2, regs *reg)
       return 1;
     }
 
+    if(PCI(pc1)->is2MemOp) {
+      testreg = pic16_getRegFromInstruction2(pc1);
+      if(testreg && (testreg->rIdx == reg->rIdx)) {
+        return 1;
+      }
+    }
+
     pc1 = pic16_findNextInstruction(pc1->next);
 
   } while (pc1 && (pc1 != pc2) && (i++ < 100)) ;
@@ -470,6 +554,8 @@ static int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *re
 
   int t = total_registers_saved;
 
+  if(reg->type == REG_SFR)return 0;
+
   if(pc2->seq < pc1->seq) {
     pct1 = pc2;
     pc2 = pc1;
@@ -508,7 +594,27 @@ static int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *re
     PCI(newpc)->pcflow = PCFL(pcfl_used);
     newpc->seq = pc2->seq;
 
-    Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
+    /* take care if register is used after pc2, if yes, then don't delete
+     * clrf reg, because, reg should be initialized with zero */
+    {
+      pCode *spc;
+      int maxSeq=0;
+
+        for(spc=setFirstItem(reg->reglives.usedpCodes);spc;spc=setNextItem(reg->reglives.usedpCodes)) {
+          if(maxSeq < spc->seq)maxSeq = spc->seq;
+        }
+
+//        fprintf(stderr, "pc1->seq = %d\tpc2->seq = %d\tspc->seq = %d\n", pc1->seq, pc2->seq, maxSeq);
+
+        if(maxSeq > pc2->seq) {
+          /* this means that a pCode uses register after pc2, then
+           * we can't delete pc1 pCode */
+          Remove2pcodes(pcfl_used, NULL, pc2, reg, can_free);
+        } else {
+          /* we can remove both pCodes */
+          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) ){
@@ -527,13 +633,18 @@ static int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *re
 
   }  else if(PCI(pc1)->op == POC_MOVWF) {
 
+    reg1 = pic16_getRegFromInstruction(pc1);
+
+    if(reg1->type == REG_SFR)return (total_registers_saved != t);
+
     pct2 = pic16_findNextInstruction(pc2->next);
 
     if(PCI(pc2)->op == POC_MOVFW) {
-      /*
+
+#if 0
        fprintf(stderr, "   MOVWF/MOVFW. instruction after MOVFW is:\n");
        pct2->print(stderr,pct2);
-      */
+#endif
 
       if(PCI(pct2)->op == POC_MOVWF) {
        /*
@@ -551,8 +662,8 @@ static int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *re
            
        */
        reg2 = pic16_getRegFromInstruction(pct2);
-       //if(reg2 && !regUsedinRange(pc1,pc2,reg2) && (reg2->type != REG_SFR)) {
-       if(reg2 && !regUsedinRange(pc1,pc2,reg2)) {
+       if(reg2 && !regUsedinRange(pc1,pc2,reg2) && (reg2->type != REG_SFR)) {
+//     if(reg2 && !regUsedinRange(pc1,pc2,reg2)) 
 
          if(pic16_pCodeSearchCondition(pct2, PCC_Z) < 1) {
            pCode *pct3 = pic16_findNextInstruction(pct2->next);
@@ -564,22 +675,22 @@ static int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *re
 
            if(usesW(pct3))
              ; // Remove2pcodes(pcfl_used, pc1, NULL, reg, can_free);
-           else
+           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");
-           }
+             total_registers_saved++;  // debugging stats.
+             return 1;
+            }
+          } else {
+//            fprintf(stderr,"didn't optimize because Z bit is used\n");
+         }
        }
-/*
+#if 0
        fprintf(stderr, " couldn't optimize\n");
        if(reg2)
-         fprintf(stderr, " %s is used in range\n",reg2->name);
+         fprintf(stderr, " %s is used in range\n", reg2->name);
        else
          fprintf(stderr, " reg2 is NULL\n");
-*/
+#endif
       }
     }
 
@@ -591,10 +702,11 @@ static int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *re
 
        reg1 = pic16_getRegFromInstruction(pct1);
        if(reg1 && !regUsedinRange(pc1,pc2,reg1)) {
-         /*
+         
+#if 0
            fprintf(stderr, "   MOVF/MOVFW. \n");
            fprintf(stderr, "     ...optimizing\n");
-         */
+#endif
 
          /*
            Change:
@@ -642,7 +754,9 @@ static int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *re
        }
       } else if ( (PCI(pct1)->op == POC_MOVWF) &&
           (PCI(pc2)->op == POC_MOVFW)) {
-       //fprintf(stderr,"movwf MOVWF/MOVFW\n");
+
+//        fprintf(stderr,"movwf MOVWF/MOVFW\n");
+
        if(optimize_level > 1 && can_free) {
          pct2 = pic16_newpCode(POC_MOVFW, PCI(pc1)->pcop);
          pic16_pCodeInsertAfter(pc2, pct2);
@@ -715,7 +829,7 @@ static void OptimizeRegUsage(set *fregs, int optimize_multi_uses, int optimize_l
        */
 
        //fprintf(stderr," used only twice\n");
-       if(pcfl_used->seq == pcfl_assigned->seq) {
+       if(pcfl_used->seq == pcfl_assigned->seq && !(setNextItem(reg->reglives.usedpFlows)) && !(setNextItem(reg->reglives.assignedpFlows))) {
 
          //fprintf(stderr, "  and used in same flow\n");
 
@@ -818,41 +932,44 @@ void pic16_pCodeRegOptimizeRegUsage(int level)
   int saved = 0;
   int t = total_registers_saved;
 
-  if(!register_optimization)
-    return;
-#define OPT_PASSES 4
-  passes = OPT_PASSES;
+    if(getenv("NO_REG_OPT"))
+      return;
 
-  do {
-    saved = total_registers_saved;
+    if(!register_optimization)
+      return;
 
-    /* Identify registers used in one flow sequence */
-    OptimizeRegUsage(pic16_dynAllocRegs,level, (OPT_PASSES-passes));
-    OptimizeRegUsage(pic16_dynStackRegs,level, (OPT_PASSES-passes));
-    OptimizeRegUsage(pic16_dynDirectRegs,0, (OPT_PASSES-passes));
+#define OPT_PASSES 8
+    passes = OPT_PASSES;
 
-    if((total_registers_saved != saved)
-       && (pic16_pcode_verbose))
-      fprintf(stderr, " *** pass %d, Saved %d registers, total saved %d ***\n", 
-             (1+OPT_PASSES-passes),total_registers_saved-saved,total_registers_saved);
-      
-    passes--;
+    do {
+      saved = total_registers_saved;
 
-  } while( passes && ((total_registers_saved != saved) || (passes==OPT_PASSES-1)) );
+      /* Identify registers used in one flow sequence */
+      OptimizeRegUsage(pic16_dynAllocRegs,level, (OPT_PASSES-passes));
+      OptimizeRegUsage(pic16_dynStackRegs,level, (OPT_PASSES-passes));
+      OptimizeRegUsage(pic16_dynDirectRegs,0, (OPT_PASSES-passes));
 
-  if(total_registers_saved == t) 
+      if((total_registers_saved != saved)
+        && (pic16_pcode_verbose))
+          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(pic16_debug_verbose)
-    fprintf(stderr, "No registers saved on this pass\n");
+    if(total_registers_saved == t) 
+      if(pic16_debug_verbose)
+        fprintf(stderr, "No registers saved on this pass\n");
 
 
 #if 0
-  fprintf(stderr,"dynamically allocated regs:\n");
-  dbg_regusage(pic16_dynAllocRegs);
-  fprintf(stderr,"stack regs:\n");
-  dbg_regusage(pic16_dynStackRegs);
-  fprintf(stderr,"direct regs:\n");
-  dbg_regusage(pic16_dynDirectRegs);
+    fprintf(stderr,"dynamically allocated regs:\n");
+    dbg_regusage(pic16_dynAllocRegs);
+    fprintf(stderr,"stack regs:\n");
+    dbg_regusage(pic16_dynStackRegs);
+    fprintf(stderr,"direct regs:\n");
+    dbg_regusage(pic16_dynDirectRegs);
 #endif
 }
 
@@ -868,7 +985,6 @@ static void  RegsSetUnMapLiveRanges(set *regset)
   while(regset) {
     reg = regset->item;
     regset = regset->next;
-
     
     deleteSet(&reg->reglives.usedpCodes);
     deleteSet(&reg->reglives.usedpFlows);
@@ -880,12 +996,10 @@ static void  RegsSetUnMapLiveRanges(set *regset)
 
 void  pic16_RegsUnMapLiveRanges(void)
 {
-
   RegsSetUnMapLiveRanges(pic16_dynAllocRegs);
   RegsSetUnMapLiveRanges(pic16_dynStackRegs);
   RegsSetUnMapLiveRanges(pic16_dynDirectRegs);
   RegsSetUnMapLiveRanges(pic16_dynProcessorRegs);
   RegsSetUnMapLiveRanges(pic16_dynDirectBitRegs);
   RegsSetUnMapLiveRanges(pic16_dynInternalRegs);
-
 }