More enhancements to register optimization algorithms.
[fw/sdcc] / src / pic / pcode.c
index 1bdeb311061dc8458873bf2539a70a8f4ccc1c63..6aad570383c1467926b7fc7e309d2098d41bbf22 100644 (file)
@@ -70,30 +70,24 @@ static hTab *pic14pCodePeepCommandsHash = NULL;
 
 
 static pFile *the_pFile = NULL;
-static int peepOptimizing = 1;
-static int GpCodeSequenceNumber = 1;
-static int GpcFlowSeq = 1;
+static pBlock *pb_dead_pcodes = NULL;
 
-#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))
+/* Hardcoded flags to change the behavior of the PIC port */
+static int peepOptimizing = 1;        /* run the peephole optimizer if nonzero */
+static int functionInlining = 1;      /* inline functions if nonzero */
 
-#define isCALL(x)       ((isPCI(x)) && (PCI(x)->op == POC_CALL))
-#define isSTATUS_REG(r) ((r)->pc_type == PO_STATUS)
+static int GpCodeSequenceNumber = 1;
+int GpcFlowSeq = 1;
 
-#define isPCOLAB(x)     ((PCOP(x)->type) == PO_LABEL)
+extern void RemoveUnusedRegisters(void);
+extern void BuildFlowTree(pBlock *pb);
+extern void pCodeRegOptimizeRegUsage(void);
 
 /****************************************************************/
 /*                      Forward declarations                    */
 /****************************************************************/
 
-static void unlinkPC(pCode *pc);
+void unlinkpCode(pCode *pc);
 #if 0
 static void genericAnalyze(pCode *pc);
 static void AnalyzeGOTO(pCode *pc);
@@ -108,13 +102,20 @@ static void pCodePrintLabel(FILE *of, pCode *pc);
 static void pCodePrintFunction(FILE *of, pCode *pc);
 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
 static char *get_op_from_instruction( pCodeInstruction *pcc);
-char *get_op( pCodeOp *pcop);
+char *get_op( pCodeOp *pcop,char *buff,int buf_size);
 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
 int pCodePeepMatchRule(pCode *pc);
 void pBlockStats(FILE *of, pBlock *pb);
+pBlock *newpBlock(void);
 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, 
@@ -175,7 +176,7 @@ pCodeInstruction pciADDLW = {
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
   POC_NOP,
-  PCC_W,   // inCond
+  (PCC_W | PCC_LITERAL),   // inCond
   (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
 };
 
@@ -196,7 +197,7 @@ pCodeInstruction pciANDLW = {
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
   POC_NOP,
-  PCC_W,   // inCond
+  (PCC_W | PCC_LITERAL),   // inCond
   (PCC_W | PCC_Z) // outCond
 };
 
@@ -259,7 +260,7 @@ pCodeInstruction pciBCF = {
   1,1,  // dest, bit instruction
   0,0,  // branch, skip
   POC_BSF,
-  PCC_REGISTER,   // inCond
+  (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
   PCC_REGISTER // outCond
 };
 
@@ -280,8 +281,8 @@ pCodeInstruction pciBSF = {
   1,1,  // dest, bit instruction
   0,0,  // branch, skip
   POC_BCF,
-  PCC_REGISTER,   // inCond
-  PCC_REGISTER // outCond
+  (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
+  (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
 };
 
 pCodeInstruction pciBTFSC = {
@@ -301,8 +302,8 @@ pCodeInstruction pciBTFSC = {
   0,1,  // dest, bit instruction
   1,1,  // branch, skip
   POC_BTFSS,
-  PCC_REGISTER,   // inCond
-  PCC_NONE // outCond
+  (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
+  PCC_EXAMINE_PCOP // outCond
 };
 
 pCodeInstruction pciBTFSS = {
@@ -322,8 +323,8 @@ pCodeInstruction pciBTFSS = {
   0,1,  // dest, bit instruction
   1,1,  // branch, skip
   POC_BTFSC,
-  PCC_REGISTER,   // inCond
-  PCC_NONE // outCond
+  (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
+  PCC_EXAMINE_PCOP // outCond
 };
 
 pCodeInstruction pciCALL = {
@@ -406,7 +407,7 @@ pCodeInstruction pciCLRF = {
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
   POC_NOP,
-  PCC_REGISTER, // inCond
+  PCC_NONE, // inCond
   PCC_REGISTER  // outCond
 };
 
@@ -427,7 +428,7 @@ pCodeInstruction pciCLRW = {
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
   POC_NOP,
-  PCC_W, // inCond
+  PCC_NONE, // inCond
   PCC_W  // outCond
 };
 
@@ -679,7 +680,7 @@ pCodeInstruction pciIORLW = {
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
   POC_NOP,
-  PCC_W,   // inCond
+  (PCC_W | PCC_LITERAL),   // inCond
   (PCC_W | PCC_Z) // outCond
 };
 
@@ -763,7 +764,7 @@ pCodeInstruction pciMOVLW = {
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
   POC_NOP,
-  PCC_NONE,   // inCond
+  (PCC_NONE | PCC_LITERAL),   // inCond
   PCC_W // outCond
 };
 
@@ -825,7 +826,7 @@ pCodeInstruction pciRETLW = {
   0,0,  // dest, bit instruction
   1,0,  // branch, skip
   POC_NOP,
-  PCC_NONE,   // inCond
+  PCC_LITERAL,   // inCond
   PCC_W // outCond
 };
 
@@ -993,7 +994,7 @@ pCodeInstruction pciSUBLW = {
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
   POC_NOP,
-  PCC_W,   // inCond
+  (PCC_W | PCC_LITERAL),   // inCond
   (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
 };
 
@@ -1119,7 +1120,7 @@ pCodeInstruction pciXORLW = {
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
   POC_NOP,
-  PCC_W,   // inCond
+  (PCC_W | PCC_LITERAL),   // inCond
   (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
 };
 
@@ -1157,6 +1158,7 @@ void SAFE_snprintf(char **str, size_t *size, const  char  *format, ...)
   len = strlen(*str);
   if(len > *size) {
     fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
+    fprintf(stderr,"len = %d is > str size %d\n",len,*size);
   }
 
   *str += len;
@@ -1185,6 +1187,7 @@ void SAFE_snprintf(char **str, size_t *size, const  char  *format, ...)
   len = strlen(buffer);
   if(len > *size) {
     fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
+    fprintf(stderr,"len = %d is > str size %d\n",len,*size);
   }
 
   strcpy(*str, buffer);
@@ -1229,6 +1232,9 @@ void  pCodeInitRegisters(void)
   pc_wsave.rIdx = IDX_WSAVE;
   pc_ssave.rIdx = IDX_SSAVE;
 
+  /* probably should put this in a separate initialization routine */
+  pb_dead_pcodes = newpBlock();
+
 }
 
 /*-----------------------------------------------------------------*/
@@ -1587,11 +1593,11 @@ pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
     memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
     pci->pcop = pcop;
 
-    if(pci->inCond == PCC_EXAMINE_PCOP)
-      pci->inCond   = RegCond(pcop);
+    if(pci->inCond & PCC_EXAMINE_PCOP)
+      pci->inCond  |= RegCond(pcop);
 
-    if(pci->outCond == PCC_EXAMINE_PCOP)
-      pci->outCond   = RegCond(pcop);
+    if(pci->outCond & PCC_EXAMINE_PCOP)
+      pci->outCond  |= RegCond(pcop);
 
     pci->pc.prev = pci->pc.next = NULL;
     return (pCode *)pci;
@@ -1799,6 +1805,9 @@ pCode *newpCodeFlow(void )
   pcflow->ToConflicts = 0;
 
   pcflow->end = NULL;
+
+  pcflow->registers = newSet();
+
   return ( (pCode *)pcflow);
 
 }
@@ -1913,6 +1922,7 @@ pBlock *newpBlock(void)
   PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
   PpB->tregisters = NULL;
   PpB->visited = 0;
+  PpB->FlowTree = NULL;
 
   return PpB;
 
@@ -2003,13 +2013,21 @@ pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space)
   pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
   pcop->type = PO_IMMEDIATE;
   if(name) {
+    regs *r = dirregWithName(name);
     pcop->name = Safe_strdup(name);
+    PCOI(pcop)->r = r;
+    if(r) {
+      //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
+      PCOI(pcop)->rIdx = r->rIdx;
+    } else {
+      //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
+      PCOI(pcop)->rIdx = -1;
+    }
     //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
   } else {
     pcop->name = NULL;
   }
 
-
   PCOI(pcop)->index = index;
   PCOI(pcop)->offset = offset;
   PCOI(pcop)->_const = code_space;
@@ -2316,7 +2334,7 @@ void printpBlock(FILE *of, pBlock *pb)
 /*                                                                 */
 /*-----------------------------------------------------------------*/
 
-static void unlinkPC(pCode *pc)
+void unlinkpCode(pCode *pc)
 {
 
 
@@ -2333,13 +2351,34 @@ static void unlinkPC(pCode *pc)
     pc->prev = pc->next = NULL;
   }
 }
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+
 static void genericDestruct(pCode *pc)
 {
-  //fprintf(stderr,"warning, calling default pCode destructor\n");
 
-  unlinkPC(pc);
+  unlinkpCode(pc);
 
-  free(pc);
+  if(isPCI(pc)) {
+    /* For instructions, tell the register (if there's one used)
+     * that it's no longer needed */
+    regs *reg = getRegFromInstruction(pc);
+    if(reg)
+      deleteSetItem (&(reg->reglives.usedpCodes),pc);
+  }
+
+  /* Instead of deleting the memory used by this pCode, mark
+   * the object as bad so that if there's a pointer to this pCode
+   * dangling around somewhere then (hopefully) when the type is
+   * checked we'll catch it.
+   */
+
+  pc->type = PC_BAD;
+
+  addpCode2pBlock(pb_dead_pcodes, pc);
+
+  //free(pc);
 
 }
 
@@ -2360,34 +2399,43 @@ void pBlockRegs(FILE *of, pBlock *pb)
 
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
-char *get_op(pCodeOp *pcop)
+char *get_op(pCodeOp *pcop,char *buffer, int size)
 {
   regs *r;
-  static char buffer[50];
+  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) {
@@ -2411,7 +2459,7 @@ char *get_op(pCodeOp *pcop)
 
     case PO_DIR:
       s = buffer;
-      size = sizeof(buffer);
+      //size = sizeof(buffer);
       if( PCOR(pcop)->instance) {
        SAFE_snprintf(&s,&size,"(%s + %d)",
                      pcop->name,
@@ -2422,8 +2470,13 @@ char *get_op(pCodeOp *pcop)
       return buffer;
 
     default:
-      if  (pcop->name)
+      if  (pcop->name) {
+       if(use_buffer) {
+         SAFE_snprintf(&buffer,&size,"%s",pcop->name);
+         return buffer;
+       }
        return pcop->name;
+      }
 
     }
   }
@@ -2438,7 +2491,7 @@ static char *get_op_from_instruction( pCodeInstruction *pcc)
 {
 
   if(pcc )
-    return get_op(pcc->pcop);
+    return get_op(pcc->pcop,NULL,0);
   
   return ("ERROR Null: "__FUNCTION__);
 
@@ -2522,9 +2575,11 @@ char *pCode2str(char *str, int size, pCode *pc)
     SAFE_snprintf(&s,&size,";\t--FLOW change\n");
     break;
   case PC_CSOURCE:
-  SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
+    SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
     break;
 
+  case PC_BAD:
+    SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
   }
 
   return str;
@@ -2865,6 +2920,9 @@ static void genericAnalyze(pCode *pc)
     fprintf(stderr,"analyze PC_FLOW\n");
 
     return;
+  case PC_BAD:
+    fprintf(stderr,,";A bad pCode is being used\n");
+
   }
 }
 #endif
@@ -3074,6 +3132,7 @@ static void AnalyzeRETURN(pCode *pc)
 /*-----------------------------------------------------------------*/
 regs * getRegFromInstruction(pCode *pc)
 {
+
   if(!pc                   || 
      !isPCI(pc)            ||
      !PCI(pc)->pcop        ||
@@ -3083,7 +3142,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:
@@ -3091,8 +3150,12 @@ regs * getRegFromInstruction(pCode *pc)
     return PCOR(PCI(pc)->pcop)->r;
 
   case PO_IMMEDIATE:
+    if(PCOI(PCI(pc)->pcop)->r)
+      return (PCOI(PCI(pc)->pcop)->r);
+
     //fprintf(stderr, "getRegFromInstruction - immediate\n");
-    return NULL; // PCOR(PCI(pc)->pcop)->r;
+    return dirregWithName(PCI(pc)->pcop->name);
+    //return NULL; // PCOR(PCI(pc)->pcop)->r;
 
   case PO_GPR_BIT:
     return PCOR(PCI(pc)->pcop)->r;
@@ -3150,10 +3213,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);
@@ -3301,7 +3365,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;
@@ -4192,7 +4256,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));
@@ -4237,7 +4301,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
@@ -4267,7 +4331,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);
@@ -4531,6 +4595,15 @@ void AnalyzeBanking(void)
   for(pb = the_pFile->pbHead; pb; pb = pb->next)
     LinkFlow(pb);
 
+  /* Phase 3 - Flow Analysis - Flow Tree
+   *
+   * In this phase, the individual flow blocks are examined
+   * to determine their order of excution.
+   */
+  /*
+  for(pb = the_pFile->pbHead; pb; pb = pb->next)
+    BuildFlowTree(pb);
+  */
 
   /* Phase x - Flow Analysis - Used Banks
    *
@@ -4550,6 +4623,17 @@ 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)
+  pCodeRegOptimizeRegUsage();
+
+  OptimizepCode('*');
+
 /*
   for(pb = the_pFile->pbHead; pb; pb = pb->next)
     DumpFlow(pb);
@@ -4658,7 +4742,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)
@@ -5176,6 +5261,8 @@ void InlinepCode(void)
   if(!the_pFile)
     return;
 
+  if(!functionInlining)
+    return;
 
   /* Loop through all of the function definitions and count the
    * number of times each one is called */
@@ -5202,7 +5289,7 @@ void InlinepCode(void)
 
   /* Now, Loop through the function definitions again, but this
    * time inline those functions that have only been called once. */
-
+  
   InlineFunction(the_pFile->pbHead);
   //fprintf(stderr,"inlining %d\n",__LINE__);