[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