[llvm-commits] [llvm] r71073 - in /llvm/trunk/lib/Target/PIC16: PIC16.h PIC16AsmPrinter.cpp PIC16AsmPrinter.h PIC16ISelLowering.cpp PIC16InstrInfo.cpp PIC16InstrInfo.h PIC16InstrInfo.td PIC16MemSelOpt.cpp PIC16TargetAsmInfo.cpp PIC16TargetAsmInfo.h PIC16TargetMachine.cpp PIC16TargetMachine.h

Sanjiv Gupta sanjiv.gupta at microchip.com
Wed May 6 01:02:03 PDT 2009


Author: sgupta
Date: Wed May  6 03:02:01 2009
New Revision: 71073

URL: http://llvm.org/viewvc/llvm-project?rev=71073&view=rev
Log:
Emit banksel and movlp instructions.
Split large global data (both initialized and un-initialized) into multiple sections of <= 80 bytes.
Provide routines to manage PIC16 ABI naming conventions.


Added:
    llvm/trunk/lib/Target/PIC16/PIC16MemSelOpt.cpp
Modified:
    llvm/trunk/lib/Target/PIC16/PIC16.h
    llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp
    llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.h
    llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.cpp
    llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.cpp
    llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.h
    llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.td
    llvm/trunk/lib/Target/PIC16/PIC16TargetAsmInfo.cpp
    llvm/trunk/lib/Target/PIC16/PIC16TargetAsmInfo.h
    llvm/trunk/lib/Target/PIC16/PIC16TargetMachine.cpp
    llvm/trunk/lib/Target/PIC16/PIC16TargetMachine.h

Modified: llvm/trunk/lib/Target/PIC16/PIC16.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16.h?rev=71073&r1=71072&r2=71073&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16.h (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16.h Wed May  6 03:02:01 2009
@@ -18,6 +18,7 @@
 #include "llvm/Target/TargetMachine.h"
 #include <iosfwd>
 #include <cassert>
+#include <string>
 
 namespace llvm {
   class PIC16TargetMachine;
@@ -39,6 +40,94 @@
     UGE
   };
 }
+  // A Central object to manage all ABI naming conventions.
+  class PIC16ABINames {
+    public:
+    // Map the name of the symbol to its section name.
+    // Current ABI:
+    // ------------------------------------------------------
+    // Global variables do not have any '.' in their names.
+    // they are prefixed with @
+    // These are maily function names and global variable names.
+    // -------------------------------------------------------
+    // Functions and auto variables.
+    // Names are mangled as <prefix><funcname>.<id>.<varname>
+    // Where prefix is a special char '@' and id is any one of
+    // the following
+    // .auto. - an automatic var of a function.
+    // .temp. - temproray data of a function.
+    // .ret.  - return value label for a function.
+    // .frame. - Frame label for a function where retval, args
+    //           and temps are stored.
+    // .args. - Label used to pass arguments to a direct call.
+    // Example - Function name:   @foo
+    //           Its frame:       @foo.frame.
+    //           Its retval:      @foo.ret.
+    //           Its local vars:  @foo.auto.a
+    //           Its temp data:   @foo.temp.
+    //           Its arg passing: @foo.args.
+    //----------------------------------------------
+    // Libcall - compiler generated libcall names must have a .lib.
+    //           This id will be used to emit extern decls for libcalls.
+    // Example - libcall name:   @sra_i8.lib.
+    //           To pass args:   @sra_i8.args.
+    //           To return val:  @sra_i8.ret.
+    //----------------------------------------------
+    
+    enum IDs {
+      PREFIX_SYMBOL,
+
+      FUNC_AUTOS,
+      FUNC_FRAME,
+      FUNC_RET,
+      FUNC_ARGS,
+      FUNC_TEMPS,
+      
+      LIBCALL,
+      
+      FRAME_SECTION,
+      AUTOS_SECTION
+   };
+
+  };
+
+  inline static const char *getIDName(PIC16ABINames::IDs id) {
+    switch (id) {
+    default: assert(0 && "Unknown id");
+    case PIC16ABINames::PREFIX_SYMBOL:    return "@";
+    case PIC16ABINames::FUNC_AUTOS:       return ".auto.";
+    case PIC16ABINames::FUNC_FRAME:       return ".frame.";
+    case PIC16ABINames::FUNC_TEMPS:       return ".temp.";
+    case PIC16ABINames::FUNC_ARGS:       return ".args.";
+    case PIC16ABINames::FUNC_RET:       return ".ret.";
+    case PIC16ABINames::FRAME_SECTION:       return "fpdata";
+    case PIC16ABINames::AUTOS_SECTION:       return "fadata";
+    }
+  }
+
+  inline static PIC16ABINames::IDs getID(const std::string &Sym) {
+    if (Sym.find(getIDName(PIC16ABINames::FUNC_TEMPS)))
+     return PIC16ABINames::FUNC_TEMPS;
+
+    if (Sym.find(getIDName(PIC16ABINames::FUNC_FRAME)))
+     return PIC16ABINames::FUNC_FRAME;
+
+    if (Sym.find(getIDName(PIC16ABINames::FUNC_RET)))
+     return PIC16ABINames::FUNC_RET;
+
+    if (Sym.find(getIDName(PIC16ABINames::FUNC_ARGS)))
+     return PIC16ABINames::FUNC_ARGS;
+
+    if (Sym.find(getIDName(PIC16ABINames::FUNC_AUTOS)))
+     return PIC16ABINames::FUNC_AUTOS;
+
+    if (Sym.find(getIDName(PIC16ABINames::LIBCALL)))
+     return PIC16ABINames::LIBCALL;
+
+    // It does not have any ID. So its a global.
+    assert (0 && "Could not determine ID symbol type");
+  }
+
 
   inline static const char *PIC16CondCodeToString(PIC16CC::CondCodes CC) {
     switch (CC) {
@@ -73,11 +162,15 @@
   }
 
 
+
   FunctionPass *createPIC16ISelDag(PIC16TargetMachine &TM);
   FunctionPass *createPIC16CodePrinterPass(raw_ostream &OS, 
                                            PIC16TargetMachine &TM,
                                            CodeGenOpt::Level OptLevel,
                                            bool Verbose);
+  // Banksel optimzer pass.
+  FunctionPass *createPIC16MemSelOptimizerPass();
+  std::string getSectionNameForSym(const std::string &Sym);
 } // end namespace llvm;
 
 // Defines symbolic names for PIC16 registers.  This defines a mapping from

Modified: llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp?rev=71073&r1=71072&r2=71073&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp Wed May  6 03:02:01 2009
@@ -45,51 +45,6 @@
 }
 
 bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
-  std::string NewBank = "";
-  unsigned Operands = MI->getNumOperands();
-  if (Operands > 1) {
-    // If we have a Global address or external symbol then we need to print 
-    // banksel for it. 
-    unsigned BankSelVar = 0;
-    MachineOperand Op = MI->getOperand(BankSelVar);
-    while (BankSelVar < Operands-1) {
-      Op = MI->getOperand(BankSelVar);
-      if ((Op.getType() ==  MachineOperand::MO_GlobalAddress) ||
-          (Op.getType() ==  MachineOperand::MO_ExternalSymbol))
-        break;
-      BankSelVar++;
-    }
-    if (BankSelVar < Operands-1) {
-      unsigned OpType = Op.getType();
-      if (OpType == MachineOperand::MO_GlobalAddress ) 
-        NewBank = Op.getGlobal()->getSection(); 
-      else {
-        // External Symbol is generated for temp data and arguments. They are 
-        // in fpdata.<functionname>.# section.
-        std::string ESName = Op.getSymbolName();
-        int index = ESName.find_first_of(".");
-        std::string FnName = ESName.substr(0,index);
-        NewBank = "fpdata." + FnName +".#";
-      }
-      // Operand after global address or external symbol should be  banksel.
-      // Value 1 for this operand means we need to generate banksel else do not
-      // generate banksel.
-      const MachineOperand &BS = MI->getOperand(BankSelVar+1);
-      // If Section names are same then the variables are in same section.
-      // This is not true for external variables as section names for global
-      // variables in all files are same at this time. For eg. initialized 
-      // data in put in idata.# section in all files. 
-      if ((BS.getType() == MachineOperand::MO_Immediate 
-          && (int)BS.getImm() == 1) 
-          && ((Op.isGlobal() && Op.getGlobal()->hasExternalLinkage()) ||
-           (NewBank.compare(CurBank) != 0))) { 
-        O << "\tbanksel ";
-        printOperand(MI, BankSelVar);
-        O << "\n";
-        CurBank = NewBank;
-      }
-    }
-  }
   printInstruction(MI);
   return true;
 }
@@ -118,8 +73,8 @@
   SwitchToSection (fCodeSection);
 
   // Emit the frame address of the function at the beginning of code.
-  O << "    retlw  low(" << FunctionLabelBegin<< CurrentFnName << ".frame)\n";
-  O << "    retlw  high(" << FunctionLabelBegin<< CurrentFnName << ".frame)\n"; 
+  O << "    retlw  low(" << FunctionLabelBegin<< CurrentFnName << ".frame.)\n";
+  O << "    retlw  high(" << FunctionLabelBegin<< CurrentFnName << ".frame.)\n"; 
   O << CurrentFnName << ":\n";
 
 
@@ -131,7 +86,6 @@
       printBasicBlockLabel(I, true);
       O << '\n';
     }
-    CurBank = "";
     
     // For emitting line directives, we need to keep track of the current
     // source line. When it changes then only emit the line directive.
@@ -225,8 +179,7 @@
   DW->BeginModule(&M, MMI, O, this, TAI);
 
   EmitExternsAndGlobals (M);
-  EmitInitData (M);
-  EmitUnInitData(M);
+  EmitGlobalData(M);
   EmitRomData(M);
   return Result;
 }
@@ -245,13 +198,13 @@
 
     if (I->isDeclaration()) {
       O << "\textern " <<Name << "\n";
-      O << "\textern "  << FunctionLabelBegin << Name << ".retval\n";
-      O << "\textern " << FunctionLabelBegin << Name << ".args\n";
+      O << "\textern "  << FunctionLabelBegin << Name << ".ret.\n";
+      O << "\textern " << FunctionLabelBegin << Name << ".args.\n";
     }
     else if (I->hasExternalLinkage()) {
       O << "\tglobal " << Name << "\n";
-      O << "\tglobal " << FunctionLabelBegin << Name << ".retval\n";
-      O << "\tglobal " << FunctionLabelBegin<< Name << ".args\n";
+      O << "\tglobal " << FunctionLabelBegin << Name << ".ret.\n";
+      O << "\tglobal " << FunctionLabelBegin<< Name << ".args.\n";
     }
   }
 
@@ -274,35 +227,6 @@
   }
 }
 
-void PIC16AsmPrinter::EmitInitData (Module &M) {
-  SwitchToSection(TAI->getDataSection());
-  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
-       I != E; ++I) {
-    if (!I->hasInitializer())   // External global require no code.
-      continue;
-
-    Constant *C = I->getInitializer();
-    const PointerType *PtrTy = I->getType();
-    int AddrSpace = PtrTy->getAddressSpace();
-
-    if ((!C->isNullValue()) && (AddrSpace == PIC16ISD::RAM_SPACE)) {
-    
-      if (EmitSpecialLLVMGlobal(I)) 
-        continue;
-
-      // Any variables reaching here with "." in its name is a local scope
-      // variable and should not be printed in global data section.
-      std::string Name = Mang->getValueName(I);
-      if (isLocalName(Name))
-        continue;
-
-      I->setSection(TAI->getDataSection()->getName());
-      O << Name;
-      EmitGlobalConstant(C, AddrSpace);
-    }
-  }
-}
-
 void PIC16AsmPrinter::EmitRomData (Module &M)
 {
   SwitchToSection(TAI->getReadOnlySection());
@@ -335,39 +259,6 @@
   IsRomData = false;
 }
 
-void PIC16AsmPrinter::EmitUnInitData (Module &M)
-{
-  SwitchToSection(TAI->getBSSSection_());
-  const TargetData *TD = TM.getTargetData();
-
-  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
-       I != E; ++I) {
-    if (!I->hasInitializer())   // External global require no code.
-      continue;
-
-    Constant *C = I->getInitializer();
-    if (C->isNullValue()) {
-
-      if (EmitSpecialLLVMGlobal(I))
-        continue;
-
-      // Any variables reaching here with "." in its name is a local scope
-      // variable and should not be printed in global data section.
-      std::string name = Mang->getValueName(I);
-      if (name.find(".") != std::string::npos)
-        continue;
-
-      I->setSection(TAI->getBSSSection_()->getName());
-
-      const Type *Ty = C->getType();
-      unsigned Size = TD->getTypePaddedSize(Ty);
-
-      O << name << " " <<"RES"<< " " << Size ;
-      O << "\n";
-    }
-  }
-}
-
 bool PIC16AsmPrinter::doFinalization(Module &M) {
   O << "\t" << "END\n";
   bool Result = AsmPrinter::doFinalization(M);
@@ -390,7 +281,7 @@
   
 
   // Emit function frame label
-  O << FunctionLabelBegin << CurrentFnName << ".frame:\n";
+  O << FunctionLabelBegin << CurrentFnName << ".frame.:\n";
 
   const Type *RetType = F->getReturnType();
   unsigned RetSize = 0; 
@@ -399,10 +290,10 @@
   
   //Emit function return value space
   if(RetSize > 0)
-     O << FunctionLabelBegin << CurrentFnName << ".retval    RES  " << RetSize 
+     O << FunctionLabelBegin << CurrentFnName << ".ret.    RES  " << RetSize 
        << "\n";
   else
-     O << FunctionLabelBegin << CurrentFnName << ".retval:\n";
+     O << FunctionLabelBegin << CurrentFnName << ".ret.:\n";
    
   // Emit variable to hold the space for function arguments 
   unsigned ArgSize = 0;
@@ -411,13 +302,13 @@
     const Type *Ty = argi->getType();
     ArgSize += TD->getTypePaddedSize(Ty);
    }
-  O << FunctionLabelBegin << CurrentFnName << ".args      RES  " << ArgSize 
+  O << FunctionLabelBegin << CurrentFnName << ".args.      RES  " << ArgSize 
     << "\n";
 
   // Emit temporary space
   int TempSize = PTLI->GetTmpSize();
   if (TempSize > 0 )
-    O << FunctionLabelBegin << CurrentFnName << ".tmp       RES  " << TempSize 
+    O << FunctionLabelBegin << CurrentFnName << ".temp.       RES  " << TempSize 
       <<"\n";
 
   // Emit the section name for local variables.
@@ -454,5 +345,40 @@
     // Emit memory reserve directive.
     O << FunctionLabelBegin << VarName << "  RES  " << Size << "\n";
   }
+}
+
+void PIC16AsmPrinter::EmitGlobalData (Module &M)
+{
+  const PIC16TargetAsmInfo *PTAI = static_cast<const PIC16TargetAsmInfo *>(TAI);
+  const_cast<PIC16TargetAsmInfo *>(PTAI)->SetSectionForGVs(M);
+  const TargetData *TD = TM.getTargetData();
 
+  std::vector <PIC16Section *>IDATASections = PTAI->getIDATASections();
+  for (unsigned i = 0; i < IDATASections.size(); i++) {
+    SwitchToSection(IDATASections[i]->S_);
+    std::vector<const GlobalVariable*> Items = IDATASections[i]->Items;
+    for (unsigned j = 0; j < Items.size(); j++) {
+      std::string Name = Mang->getValueName(Items[j]);
+      Constant *C = Items[j]->getInitializer();
+      int AddrSpace = Items[j]->getType()->getAddressSpace();
+      O << Name;
+      EmitGlobalConstant(C, AddrSpace);
+    }
+  }
+
+  std::vector <PIC16Section *>BSSSections = PTAI->getBSSSections();
+  for (unsigned i = 0; i < BSSSections.size(); i++) {
+    SwitchToSection(BSSSections[i]->S_);
+    std::vector<const GlobalVariable*> Items = BSSSections[i]->Items;
+    for (unsigned j = 0; j < Items.size(); j++) {
+      std::string Name = Mang->getValueName(Items[j]);
+      Constant *C = Items[j]->getInitializer();
+      const Type *Ty = C->getType();
+      unsigned Size = TD->getTypePaddedSize(Ty);
+
+      O << Name << " " <<"RES"<< " " << Size ;
+      O << "\n";
+    }
+  }
 }
+

Modified: llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.h?rev=71073&r1=71072&r2=71073&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.h (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.h Wed May  6 03:02:01 2009
@@ -28,7 +28,6 @@
                              const TargetAsmInfo *T, CodeGenOpt::Level OL,
                              bool V)
       : AsmPrinter(O, TM, T, OL, V) {
-      CurBank = "";
       FunctionLabelBegin = '@';
       IsRomData = false;
       PTLI = TM.getTargetLowering();
@@ -44,8 +43,7 @@
     bool printInstruction(const MachineInstr *MI); // definition autogenerated.
     bool printMachineInstruction(const MachineInstr *MI);
     void EmitExternsAndGlobals (Module &M);
-    void EmitInitData (Module &M);
-    void EmitUnInitData (Module &M);
+    void EmitGlobalData (Module &M);
     void EmitRomData (Module &M);
     void emitFunctionData(MachineFunction &MF);
 
@@ -55,7 +53,6 @@
 
     private:
     PIC16TargetLowering *PTLI;
-    std::string CurBank;
     bool IsRomData;
     char FunctionLabelBegin;
   };

Modified: llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.cpp?rev=71073&r1=71072&r2=71073&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.cpp Wed May  6 03:02:01 2009
@@ -531,7 +531,7 @@
   unsigned FIndex = FR->getIndex();
   char *tmpName = new char [strlen(Name.c_str()) +  8];
   if (FIndex < ReservedFrameCount) {
-    sprintf(tmpName, "%s.frame", Name.c_str());
+    sprintf(tmpName, "%s.frame.", Name.c_str());
     ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8);
     Offset = 0;
     for (unsigned i=0; i<FIndex ; ++i) {
@@ -539,7 +539,7 @@
     }
   } else {
    // FrameIndex has been made for some temporary storage 
-    sprintf(tmpName, "%s.tmp", Name.c_str());
+    sprintf(tmpName, "%s.temp.", Name.c_str());
     ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8);
     Offset = GetTmpOffsetForFI(FIndex, MFI->getObjectSize(FIndex));
   }
@@ -850,7 +850,7 @@
   // Put the value on stack.
   // Get a stack slot index and convert to es.
   int FI = MF.getFrameInfo()->CreateStackObject(1, 1);
-  sprintf(tmpName, "%s.tmp", FuncName.c_str());
+  sprintf(tmpName, "%s.temp.", FuncName.c_str());
   SDValue ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8);
 
   // Store the value to ES.
@@ -1065,7 +1065,7 @@
   std::string FuncName = F->getName();
 
   char *tmpName = new char [strlen(FuncName.c_str()) +  8];
-  sprintf(tmpName, "%s.frame", FuncName.c_str());
+  sprintf(tmpName, "%s.frame.", FuncName.c_str());
   SDVTList VTs  = DAG.getVTList (MVT::i8, MVT::Other);
   SDValue ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8);
   SDValue BS = DAG.getConstant(1, MVT::i8);
@@ -1250,12 +1250,12 @@
 
        // Label for argument passing
        char *argFrame = new char [strlen(Name.c_str()) +  8];
-       sprintf(argFrame, "%s.args", Name.c_str());
+       sprintf(argFrame, "%s.args.", Name.c_str());
        ArgLabel = DAG.getTargetExternalSymbol(argFrame, MVT::i8);
 
        // Label for reading return value
        char *retName = new char [strlen(Name.c_str()) +  8];
-       sprintf(retName, "%s.retval", Name.c_str());
+       sprintf(retName, "%s.ret.", Name.c_str());
        RetLabel = DAG.getTargetExternalSymbol(retName, MVT::i8);
     } else {
        // if indirect call
@@ -1451,8 +1451,8 @@
   InitReservedFrameCount(F);
 
   // Create the <fname>.args external symbol.
-  char *tmpName = new char [strlen(FuncName.c_str()) +  6];
-  sprintf(tmpName, "%s.args", FuncName.c_str());
+  char *tmpName = new char [strlen(FuncName.c_str()) +  8];
+  sprintf(tmpName, "%s.args.", FuncName.c_str());
   SDValue ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8);
 
   // Load arg values from the label + offset.

Modified: llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.cpp?rev=71073&r1=71072&r2=71073&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.cpp Wed May  6 03:02:01 2009
@@ -76,8 +76,8 @@
   const Function *Func = MBB.getParent()->getFunction();
   const std::string FuncName = Func->getName();
 
-  char *tmpName = new char [strlen(FuncName.c_str()) +  6];
-  sprintf(tmpName, "%s.tmp", FuncName.c_str());
+  char *tmpName = new char [strlen(FuncName.c_str()) +  10];
+  sprintf(tmpName, "%s.temp.", FuncName.c_str());
 
   // On the order of operands here: think "movwf SrcReg, tmp_slot, offset".
   if (RC == PIC16::GPRRegisterClass) {
@@ -119,8 +119,8 @@
   const Function *Func = MBB.getParent()->getFunction();
   const std::string FuncName = Func->getName();
 
-  char *tmpName = new char [strlen(FuncName.c_str()) +  6];
-  sprintf(tmpName, "%s.tmp", FuncName.c_str());
+  char *tmpName = new char [strlen(FuncName.c_str()) +  10];
+  sprintf(tmpName, "%s.temp.", FuncName.c_str());
 
   // On the order of operands here: think "movf FrameIndex, W".
   if (RC == PIC16::GPRRegisterClass) {

Modified: llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.h?rev=71073&r1=71072&r2=71073&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.h (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.h Wed May  6 03:02:01 2009
@@ -64,6 +64,23 @@
                            unsigned &SrcReg, unsigned &DstReg,
                            unsigned &SrcSubIdx, unsigned &DstSubIdx) const;
 
+  static inline bool hasNoMemOperand (const MachineInstr &MI) {
+
+    if (MI.getNumOperands() == 0) return true;
+
+    switch (MI.getOpcode()) {
+    default: return false;  // Beware
+    case PIC16::movlw_lo_1:
+    case PIC16::movlw_hi_1:
+    case PIC16::movlw_lo_2:
+    case PIC16::movlw_hi_2:
+      return true;
+    }
+  }
+       
+   
+    
+
 };
 
 } // namespace llvm

Modified: llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.td?rev=71073&r1=71072&r2=71073&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.td (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.td Wed May  6 03:02:01 2009
@@ -470,13 +470,18 @@
 
 
 // Banksel.
-let isReMaterializable = 1 in {
 def banksel : 
-  Pseudo<(outs BSR:$dst),
+  Pseudo<(outs),
          (ins i8mem:$ptr),
          "banksel $ptr",
-         [(set BSR:$dst, (Banksel tglobaladdr:$ptr))]>;
-}
+         []>;
+
+def pagesel : 
+  Pseudo<(outs),
+         (ins i8mem:$ptr),
+         "movlp $ptr",
+         []>;
+
 
 // Return insn.
 def Return : 

Added: llvm/trunk/lib/Target/PIC16/PIC16MemSelOpt.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16MemSelOpt.cpp?rev=71073&view=auto

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16MemSelOpt.cpp (added)
+++ llvm/trunk/lib/Target/PIC16/PIC16MemSelOpt.cpp Wed May  6 03:02:01 2009
@@ -0,0 +1,163 @@
+//===-- PIC16MemSelOpt.cpp - PIC16 banksel optimizer  --------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the pass which optimizes the emitting of banksel 
+// instructions before accessing data memory. This currently works within
+// a basic block only and keep tracks of the last accessed memory bank.
+// If memory access continues to be in the same bank it just makes banksel
+// immediate, which is a part of the insn accessing the data memory, from 1
+// to zero. The asm printer emits a banksel only if that immediate is 1. 
+//
+// FIXME: this is not implemented yet.  The banksel pass only works on local
+// basic blocks.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "pic16-codegen"
+#include "PIC16.h"
+#include "PIC16InstrInfo.h"
+#include "PIC16TargetAsmInfo.h"
+#include "PIC16TargetMachine.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/GlobalValue.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Support/Compiler.h"
+
+using namespace llvm;
+
+namespace {
+  struct VISIBILITY_HIDDEN MemSelOpt : public MachineFunctionPass {
+    static char ID;
+    MemSelOpt() : MachineFunctionPass(&ID) {}
+
+    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+      AU.addPreservedID(MachineLoopInfoID);
+      AU.addPreservedID(MachineDominatorsID);
+      MachineFunctionPass::getAnalysisUsage(AU);
+    }
+
+    virtual bool runOnMachineFunction(MachineFunction &MF);
+
+    virtual const char *getPassName() const { 
+      return "PIC16 Memsel Optimizer"; 
+    }
+
+   bool processBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB);
+   bool processInstruction(MachineInstr *MI);
+
+  private:
+    const TargetInstrInfo *TII; // Machine instruction info.
+    MachineBasicBlock *MBB;     // Current basic block
+    std::string CurBank;
+
+  };
+  char MemSelOpt::ID = 0;
+}
+
+FunctionPass *llvm::createPIC16MemSelOptimizerPass() { 
+  return new MemSelOpt(); 
+}
+
+
+/// runOnMachineFunction - Loop over all of the basic blocks, transforming FP
+/// register references into FP stack references.
+///
+bool MemSelOpt::runOnMachineFunction(MachineFunction &MF) {
+  TII = MF.getTarget().getInstrInfo();
+  bool Changed = false;
+  for (MachineFunction::iterator I = MF.begin(), E = MF.end();
+       I != E; ++I) {
+    Changed |= processBasicBlock(MF, *I);
+  }
+
+  return Changed;
+}
+
+/// processBasicBlock - Loop over all of the instructions in the basic block,
+/// transforming FP instructions into their stack form.
+///
+bool MemSelOpt::processBasicBlock(MachineFunction &MF, MachineBasicBlock &BB) {
+  bool Changed = false;
+  MBB = &BB;
+
+  // Let us assume that when entering a basic block now bank is selected.
+  // Ideally we should look at the predecessors for this information.
+  CurBank=""; 
+
+  for (MachineBasicBlock::iterator I = BB.begin(); I != BB.end(); ++I) {
+    Changed |= processInstruction(I);
+  }
+  return Changed;
+}
+
+bool MemSelOpt::processInstruction(MachineInstr *MI) {
+  bool Changed = false;
+
+  unsigned NumOperands = MI->getNumOperands();
+  // If this insn has only one operand, probably it is not going to
+  // access any data memory.
+  if (PIC16InstrInfo::hasNoMemOperand(*MI)) return Changed;
+
+  // Scan for the memory address operand.
+  // FIXME: Should we use standard interfaces like memoperands_iterator,
+  // hasMemOperand() etc ?
+  int MemOpPos = -1;
+  for (unsigned i = 0; i < NumOperands; i++) {
+    MachineOperand Op = MI->getOperand(i);
+    if (Op.getType() ==  MachineOperand::MO_GlobalAddress ||
+        Op.getType() ==  MachineOperand::MO_ExternalSymbol) {
+      // We found one mem operand. Next one should be BS.
+      MemOpPos = i;
+      break;
+    }
+  }
+
+  // If we did not find an insn accessing memory. Continue.
+  if (MemOpPos == -1) return Changed;
+ 
+  // Get the MemOp.
+  MachineOperand &Op = MI->getOperand(MemOpPos);
+
+  // If this is a pagesel material, handle it first.
+  if (MI->getOpcode() == PIC16::CALL) {
+    DebugLoc dl = MI->getDebugLoc();
+    BuildMI(*MBB, MI, dl, TII->get(PIC16::pagesel)).
+      addOperand(Op);
+    return true;
+  }
+
+  // Get the section name(NewBank) for MemOp.
+  std::string NewBank = CurBank;
+  if (Op.getType() ==  MachineOperand::MO_GlobalAddress &&
+      Op.getGlobal()->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE) {
+    NewBank = Op.getGlobal()->getSection();
+  } else if (Op.getType() ==  MachineOperand::MO_ExternalSymbol) {
+    // External Symbol is generated for temp data and arguments. They are
+    // in fpdata.<functionname>.# section.
+    std::string Sym = Op.getSymbolName();
+    NewBank = getSectionNameForSym(Sym);
+  }
+ 
+  // If the previous and new section names are same, we don't need to
+  // emit banksel. 
+  if (NewBank.compare(CurBank) != 0 ) {
+    DebugLoc dl = MI->getDebugLoc();
+    BuildMI(*MBB, MI, dl, TII->get(PIC16::banksel)).
+      addOperand(Op);
+    Changed = true;
+    CurBank = NewBank;
+  }
+
+  return Changed;
+}
+

Modified: llvm/trunk/lib/Target/PIC16/PIC16TargetAsmInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16TargetAsmInfo.cpp?rev=71073&r1=71072&r2=71073&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16TargetAsmInfo.cpp (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16TargetAsmInfo.cpp Wed May  6 03:02:01 2009
@@ -14,6 +14,8 @@
 #include "PIC16TargetAsmInfo.h"
 #include "PIC16TargetMachine.h"
 #include "llvm/GlobalValue.h"
+#include "llvm/GlobalVariable.h"
+#include "llvm/DerivedTypes.h"
 
 using namespace llvm;
 
@@ -61,3 +63,204 @@
     return NULL;
 }
 
+const Section *
+PIC16TargetAsmInfo::getBSSSectionForGlobal(const GlobalVariable *GV) const {
+  assert (GV->hasInitializer() && "This global doesn't need space");
+  Constant *C = GV->getInitializer();
+  assert (C->isNullValue() && "Unitialized globals has non-zero initializer");
+
+  // Find how much space this global needs.
+  const TargetData *TD = TM.getTargetData();
+  const Type *Ty = C->getType(); 
+  unsigned ValSize = TD->getTypePaddedSize(Ty);
+ 
+  // Go through all BSS Sections and assign this variable
+  // to the first available section having enough space.
+  PIC16Section *FoundBSS = NULL;
+  for (unsigned i = 0; i < BSSSections.size(); i++) {
+    if (DataBankSize - BSSSections[i]->Size >= ValSize) {
+      FoundBSS = BSSSections[i];
+      break;
+    }
+  }
+
+  // No BSS section spacious enough was found. Crate a new one.
+  if (! FoundBSS) {
+    char *name = new char[32];
+    sprintf (name, "udata.%d.# UDATA", BSSSections.size());
+    const Section *NewSection = getNamedSection (name);
+
+    FoundBSS = new PIC16Section(NewSection);
+
+    // Add this newly created BSS section to the list of BSSSections.
+    BSSSections.push_back(FoundBSS);
+  }
+  
+  // Insert the GV into this BSS.
+  FoundBSS->Items.push_back(GV);
+  FoundBSS->Size += ValSize;
+
+  // We can't do this here because GV is const .
+  // const std::string SName = FoundBSS->S_->getName();
+  // GV->setSection(SName);
+
+  return FoundBSS->S_;
+} 
+
+const Section *
+PIC16TargetAsmInfo::getIDATASectionForGlobal(const GlobalVariable *GV) const {
+  assert (GV->hasInitializer() && "This global doesn't need space");
+  Constant *C = GV->getInitializer();
+  assert (!C->isNullValue() && "initialized globals has zero initializer");
+  assert (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE &&
+          "can split initialized RAM data only");
+
+  // Find how much space this global needs.
+  const TargetData *TD = TM.getTargetData();
+  const Type *Ty = C->getType(); 
+  unsigned ValSize = TD->getTypePaddedSize(Ty);
+ 
+  // Go through all IDATA Sections and assign this variable
+  // to the first available section having enough space.
+  PIC16Section *FoundIDATA = NULL;
+  for (unsigned i = 0; i < IDATASections.size(); i++) {
+    if ( DataBankSize - IDATASections[i]->Size >= ValSize) {
+      FoundIDATA = IDATASections[i]; 
+      break;
+    }
+  }
+
+  // No IDATA section spacious enough was found. Crate a new one.
+  if (! FoundIDATA) {
+    char *name = new char[32];
+    sprintf (name, "idata.%d.# IDATA", IDATASections.size());
+    const Section *NewSection = getNamedSection (name);
+
+    FoundIDATA = new PIC16Section(NewSection);
+
+    // Add this newly created IDATA section to the list of IDATASections.
+    IDATASections.push_back(FoundIDATA);
+  }
+  
+  // Insert the GV into this IDATA.
+  FoundIDATA->Items.push_back(GV);
+  FoundIDATA->Size += ValSize;
+
+  // We can't do this here because GV is const .
+  // GV->setSection(FoundIDATA->S->getName());
+
+  return FoundIDATA->S_;
+} 
+
+// Override default implementation to put the true globals into
+// multiple data sections if required.
+const Section*
+PIC16TargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV1) const {
+  // We select the section based on the initializer here, so it really
+  // has to be a GlobalVariable.
+  if (!isa<GlobalVariable>(GV1))
+    return TargetAsmInfo::SelectSectionForGlobal(GV1);
+
+  const GlobalVariable *GV = dyn_cast<GlobalVariable>(GV1); 
+  // We are only dealing with true globals here. So names with a "."
+  // are local globals. Also declarations are not entertained.
+  std::string name = GV->getName();
+  if (name.find(".auto.") != std::string::npos
+      || name.find(".arg.") != std::string::npos || !GV->hasInitializer())
+    return TargetAsmInfo::SelectSectionForGlobal(GV);
+
+  const Constant *C = GV->getInitializer();
+  // See if this is an uninitialized global.
+  if (C->isNullValue()) 
+    return getBSSSectionForGlobal(GV); 
+
+  // This is initialized data. We only deal with initialized data in RAM.
+  if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE) 
+    return getIDATASectionForGlobal(GV);
+
+  // Else let the default implementation take care of it.
+  return TargetAsmInfo::SelectSectionForGlobal(GV);
+}
+
+void PIC16TargetAsmInfo::SetSectionForGVs(Module &M) {
+  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
+       I != E; ++I) {
+    if (!I->hasInitializer())   // External global require no code.
+      continue;
+
+    // Any variables reaching here with "." in its name is a local scope
+    // variable and should not be printed in global data section.
+    std::string name = I->getName();
+    if (name.find(".auto.") != std::string::npos
+      || name.find(".arg.") != std::string::npos)
+      continue;
+    int AddrSpace = I->getType()->getAddressSpace();
+
+    if (AddrSpace == PIC16ISD::RAM_SPACE)
+      I->setSection(SectionForGlobal(I)->getName());
+  }
+}
+
+
+// Helper routine.
+// Func name starts after prefix and followed by a .
+static std::string getFuncNameForSym(const std::string &Sym, 
+                                      PIC16ABINames::IDs PrefixType) {
+
+  const char *prefix = getIDName (PIC16ABINames::PREFIX_SYMBOL);
+
+  // This name may or may not start with prefix;
+  // Func names start after prfix in that case.
+  size_t func_name_start = 0;
+  if (Sym.find(prefix, 0, strlen(prefix)) != std::string::npos)
+    func_name_start = strlen(prefix);
+
+  // Position of the . after func name.
+  size_t func_name_end = Sym.find ('.', func_name_start);
+
+  return Sym.substr (func_name_start, func_name_end);
+}
+
+// Helper routine to create a section name given the section prefix
+// and func name.
+static std::string
+getSectionNameForFunc (const std::string &Fname,
+                       const PIC16ABINames::IDs sec_id) {
+  std::string sec_id_string = getIDName (sec_id);
+  return sec_id_string + "." + Fname + ".#";
+}
+
+
+// Get the section for the given external symbol names.
+// This function is meant for only mangled external symbol names.
+std::string 
+llvm::getSectionNameForSym(const std::string &Sym) {
+  std::string SectionName;
+
+  PIC16ABINames::IDs id = getID (Sym);
+  std::string Fname = getFuncNameForSym (Sym, id);
+
+  switch (id) {
+    default : assert (0 && "Could not determine external symbol type");
+    case PIC16ABINames::FUNC_FRAME: 
+    case PIC16ABINames::FUNC_RET: 
+    case PIC16ABINames::FUNC_TEMPS: 
+    case PIC16ABINames::FUNC_ARGS:  {
+      return getSectionNameForFunc (Fname, PIC16ABINames::FRAME_SECTION);
+    }
+    case PIC16ABINames::FUNC_AUTOS: { 
+      return getSectionNameForFunc (Fname, PIC16ABINames::AUTOS_SECTION);
+    }
+  }
+}
+
+PIC16TargetAsmInfo::~PIC16TargetAsmInfo() {
+  
+  for (unsigned i = 0; i < BSSSections.size(); i++) {
+      delete BSSSections[i]; 
+  }
+
+  for (unsigned i = 0; i < IDATASections.size(); i++) {
+      delete IDATASections[i]; 
+  }
+}

Modified: llvm/trunk/lib/Target/PIC16/PIC16TargetAsmInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16TargetAsmInfo.h?rev=71073&r1=71072&r2=71073&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16TargetAsmInfo.h (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16TargetAsmInfo.h Wed May  6 03:02:01 2009
@@ -14,21 +14,54 @@
 #ifndef PIC16TARGETASMINFO_H
 #define PIC16TARGETASMINFO_H
 
+#include "PIC16.h"
 #include "llvm/Target/TargetAsmInfo.h"
-
+#include <vector>
+#include "llvm/Module.h"
+#define DataBankSize 80
 namespace llvm {
 
   // Forward declaration.
   class PIC16TargetMachine;
+  class GlobalVariable;
 
+  // PIC16 Splits the global data into mulitple udata and idata sections.
+  // Each udata and idata section needs to contain a list of globals that
+  // they contain, in order to avoid scanning over all the global values 
+  // again and printing only those that match the current section. 
+  // Keeping values inside the sections make printing a section much easier.
+  struct PIC16Section {
+      const Section *S_; // Connection to actual Section.
+      unsigned Size;  // Total size of the objects contained.
+      std::vector<const GlobalVariable*> Items;
+     
+      PIC16Section (const Section *s) { S_ = s; Size = 0; }
+  };
+      
   struct PIC16TargetAsmInfo : public TargetAsmInfo {
+    std::string getSectionNameForSym(const std::string &Sym) const;
     PIC16TargetAsmInfo(const PIC16TargetMachine &TM);
+    virtual ~PIC16TargetAsmInfo();
     private:
+    mutable std::vector<PIC16Section *> BSSSections;
+    mutable std::vector<PIC16Section *> IDATASections;
+    
     const char *RomData8bitsDirective;
     const char *RomData16bitsDirective;
     const char *RomData32bitsDirective;
     const char *getRomDirective(unsigned size) const;
     virtual const char *getASDirective(unsigned size, unsigned AS) const;
+    const Section *getBSSSectionForGlobal(const GlobalVariable *GV) const;
+    const Section *getIDATASectionForGlobal(const GlobalVariable *GV) const;
+    virtual const Section *SelectSectionForGlobal(const GlobalValue *GV) const;
+    public:
+    void SetSectionForGVs(Module &M);
+    std::vector<PIC16Section *> getBSSSections() const {
+      return BSSSections;
+    }
+    std::vector<PIC16Section *> getIDATASections()  const {
+      return IDATASections;
+    }
   };
 
 } // namespace llvm

Modified: llvm/trunk/lib/Target/PIC16/PIC16TargetMachine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16TargetMachine.cpp?rev=71073&r1=71072&r2=71073&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16TargetMachine.cpp (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16TargetMachine.cpp Wed May  6 03:02:01 2009
@@ -70,4 +70,10 @@
   return false;
 }
 
+bool PIC16TargetMachine::addPostRegAlloc(PassManagerBase &PM, 
+                                         CodeGenOpt::Level OptLevel) {
+  PM.add(createPIC16MemSelOptimizerPass());
+  return true;  // -print-machineinstr should print after this.
+}
+
 

Modified: llvm/trunk/lib/Target/PIC16/PIC16TargetMachine.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16TargetMachine.h?rev=71073&r1=71072&r2=71073&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16TargetMachine.h (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16TargetMachine.h Wed May  6 03:02:01 2009
@@ -62,6 +62,7 @@
   virtual bool addAssemblyEmitter(PassManagerBase &PM,
                                   CodeGenOpt::Level OptLevel,
                                   bool Verbose, raw_ostream &Out);
+  virtual bool addPostRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel);
 }; // PIC16TargetMachine.
 
 /// CooperTargetMachine





More information about the llvm-commits mailing list