diff options
Diffstat (limited to 'lib/Target/XCore')
43 files changed, 1836 insertions, 770 deletions
diff --git a/lib/Target/XCore/CMakeLists.txt b/lib/Target/XCore/CMakeLists.txt index 3fa3b34245d7f..5ad07544ef8c4 100644 --- a/lib/Target/XCore/CMakeLists.txt +++ b/lib/Target/XCore/CMakeLists.txt @@ -24,10 +24,9 @@ add_llvm_target(XCoreCodeGen XCoreTargetObjectFile.cpp XCoreTargetTransformInfo.cpp XCoreSelectionDAGInfo.cpp + XCoreFrameToArgsOffsetElim.cpp ) -add_dependencies(LLVMXCoreCodeGen XCoreCommonTableGen intrinsics_gen) - add_subdirectory(Disassembler) add_subdirectory(InstPrinter) add_subdirectory(TargetInfo) diff --git a/lib/Target/XCore/Disassembler/CMakeLists.txt b/lib/Target/XCore/Disassembler/CMakeLists.txt index cdc5d993b8bfe..1ed10c02c356e 100644 --- a/lib/Target/XCore/Disassembler/CMakeLists.txt +++ b/lib/Target/XCore/Disassembler/CMakeLists.txt @@ -1,5 +1,3 @@ add_llvm_library(LLVMXCoreDisassembler XCoreDisassembler.cpp ) - -add_dependencies(LLVMXCoreDisassembler XCoreCommonTableGen) diff --git a/lib/Target/XCore/Disassembler/XCoreDisassembler.cpp b/lib/Target/XCore/Disassembler/XCoreDisassembler.cpp index 9c20abd4c6c70..7fef7960a8ff1 100644 --- a/lib/Target/XCore/Disassembler/XCoreDisassembler.cpp +++ b/lib/Target/XCore/Disassembler/XCoreDisassembler.cpp @@ -14,6 +14,7 @@ #include "XCore.h" #include "XCoreRegisterInfo.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCDisassembler.h" #include "llvm/MC/MCFixedLenDisassembler.h" #include "llvm/MC/MCInst.h" @@ -23,16 +24,17 @@ using namespace llvm; +#define DEBUG_TYPE "xcore-disassembler" + typedef MCDisassembler::DecodeStatus DecodeStatus; namespace { /// \brief A disassembler class for XCore. class XCoreDisassembler : public MCDisassembler { - OwningPtr<const MCRegisterInfo> RegInfo; public: - XCoreDisassembler(const MCSubtargetInfo &STI, const MCRegisterInfo *Info) : - MCDisassembler(STI), RegInfo(Info) {} + XCoreDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx) : + MCDisassembler(STI, Ctx) {} /// \brief See MCDisassembler. virtual DecodeStatus getInstruction(MCInst &instr, @@ -40,9 +42,8 @@ public: const MemoryObject ®ion, uint64_t address, raw_ostream &vStream, - raw_ostream &cStream) const; + raw_ostream &cStream) const override; - const MCRegisterInfo *getRegInfo() const { return RegInfo.get(); } }; } @@ -81,7 +82,8 @@ static bool readInstruction32(const MemoryObject ®ion, static unsigned getReg(const void *D, unsigned RC, unsigned RegNo) { const XCoreDisassembler *Dis = static_cast<const XCoreDisassembler*>(D); - return *(Dis->getRegInfo()->getRegClass(RC).begin() + RegNo); + const MCRegisterInfo *RegInfo = Dis->getContext().getRegisterInfo(); + return *(RegInfo->getRegClass(RC).begin() + RegNo); } static DecodeStatus DecodeGRRegsRegisterClass(MCInst &Inst, @@ -788,8 +790,9 @@ namespace llvm { } static MCDisassembler *createXCoreDisassembler(const Target &T, - const MCSubtargetInfo &STI) { - return new XCoreDisassembler(STI, T.createMCRegInfo("")); + const MCSubtargetInfo &STI, + MCContext &Ctx) { + return new XCoreDisassembler(STI, Ctx); } extern "C" void LLVMInitializeXCoreDisassembler() { diff --git a/lib/Target/XCore/InstPrinter/CMakeLists.txt b/lib/Target/XCore/InstPrinter/CMakeLists.txt index 930e733cd7f1c..53cf84da7be98 100644 --- a/lib/Target/XCore/InstPrinter/CMakeLists.txt +++ b/lib/Target/XCore/InstPrinter/CMakeLists.txt @@ -1,7 +1,3 @@ -include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) - add_llvm_library(LLVMXCoreAsmPrinter XCoreInstPrinter.cpp ) - -add_dependencies(LLVMXCoreAsmPrinter XCoreCommonTableGen) diff --git a/lib/Target/XCore/InstPrinter/XCoreInstPrinter.cpp b/lib/Target/XCore/InstPrinter/XCoreInstPrinter.cpp index 9ae8c0d08860a..215fe89bda1bc 100644 --- a/lib/Target/XCore/InstPrinter/XCoreInstPrinter.cpp +++ b/lib/Target/XCore/InstPrinter/XCoreInstPrinter.cpp @@ -11,7 +11,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "asm-printer" #include "XCoreInstPrinter.h" #include "llvm/ADT/StringExtras.h" #include "llvm/MC/MCExpr.h" @@ -22,6 +21,8 @@ #include "llvm/Support/raw_ostream.h" using namespace llvm; +#define DEBUG_TYPE "asm-printer" + #include "XCoreGenAsmWriter.inc" void XCoreInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { diff --git a/lib/Target/XCore/InstPrinter/XCoreInstPrinter.h b/lib/Target/XCore/InstPrinter/XCoreInstPrinter.h index 772c515b5c9ed..98e7c98653f83 100644 --- a/lib/Target/XCore/InstPrinter/XCoreInstPrinter.h +++ b/lib/Target/XCore/InstPrinter/XCoreInstPrinter.h @@ -31,8 +31,8 @@ public: void printInstruction(const MCInst *MI, raw_ostream &O); static const char *getRegisterName(unsigned RegNo); - virtual void printRegName(raw_ostream &OS, unsigned RegNo) const; - virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot); + void printRegName(raw_ostream &OS, unsigned RegNo) const override; + void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot) override; private: void printInlineJT(const MCInst *MI, int opNum, raw_ostream &O); void printInlineJT32(const MCInst *MI, int opNum, raw_ostream &O); diff --git a/lib/Target/XCore/LLVMBuild.txt b/lib/Target/XCore/LLVMBuild.txt index 59e64ad0855c6..0504e8ab8f0c2 100644 --- a/lib/Target/XCore/LLVMBuild.txt +++ b/lib/Target/XCore/LLVMBuild.txt @@ -29,5 +29,5 @@ has_disassembler = 1 type = Library name = XCoreCodeGen parent = XCore -required_libraries = AsmPrinter CodeGen Core MC SelectionDAG Support Target XCoreDesc XCoreInfo +required_libraries = Analysis AsmPrinter CodeGen Core MC SelectionDAG Support Target TransformUtils XCoreAsmPrinter XCoreDesc XCoreInfo add_to_library_groups = XCore diff --git a/lib/Target/XCore/MCTargetDesc/CMakeLists.txt b/lib/Target/XCore/MCTargetDesc/CMakeLists.txt index 3a3f5b4cc63ee..a14cf5ce2ac14 100644 --- a/lib/Target/XCore/MCTargetDesc/CMakeLists.txt +++ b/lib/Target/XCore/MCTargetDesc/CMakeLists.txt @@ -2,8 +2,3 @@ add_llvm_library(LLVMXCoreDesc XCoreMCTargetDesc.cpp XCoreMCAsmInfo.cpp ) - -add_dependencies(LLVMXCoreDesc XCoreCommonTableGen) - -# Hack: we need to include 'main' target directory to grab private headers -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_BINARY_DIR}/..) diff --git a/lib/Target/XCore/MCTargetDesc/LLVMBuild.txt b/lib/Target/XCore/MCTargetDesc/LLVMBuild.txt index 8213f9e428830..6d390d2727487 100644 --- a/lib/Target/XCore/MCTargetDesc/LLVMBuild.txt +++ b/lib/Target/XCore/MCTargetDesc/LLVMBuild.txt @@ -19,5 +19,5 @@ type = Library name = XCoreDesc parent = XCore -required_libraries = MC XCoreAsmPrinter XCoreInfo +required_libraries = MC Support XCoreAsmPrinter XCoreInfo add_to_library_groups = XCore diff --git a/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.cpp b/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.cpp index 3d1c4745d6ac8..56659117afc7e 100644 --- a/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.cpp +++ b/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.cpp @@ -17,11 +17,10 @@ XCoreMCAsmInfo::XCoreMCAsmInfo(StringRef TT) { SupportsDebugInformation = true; Data16bitsDirective = "\t.short\t"; Data32bitsDirective = "\t.long\t"; - Data64bitsDirective = 0; + Data64bitsDirective = nullptr; ZeroDirective = "\t.space\t"; CommentString = "#"; - - PrivateGlobalPrefix = ".L"; + AscizDirective = ".asciiz"; HiddenVisibilityAttr = MCSA_Invalid; diff --git a/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.h b/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.h index e53c96b8f7455..da2689a6400ca 100644 --- a/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.h +++ b/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.h @@ -21,7 +21,7 @@ namespace llvm { class Target; class XCoreMCAsmInfo : public MCAsmInfoELF { - virtual void anchor(); + void anchor() override; public: explicit XCoreMCAsmInfo(StringRef TT); }; diff --git a/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp b/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp index 10bb6dfa928a3..d54e94fb7d97b 100644 --- a/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp +++ b/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp @@ -14,13 +14,17 @@ #include "XCoreMCTargetDesc.h" #include "InstPrinter/XCoreInstPrinter.h" #include "XCoreMCAsmInfo.h" +#include "XCoreTargetStreamer.h" #include "llvm/MC/MCCodeGenInfo.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" #include "llvm/Support/TargetRegistry.h" +using namespace llvm; + #define GET_INSTRINFO_MC_DESC #include "XCoreGenInstrInfo.inc" @@ -30,8 +34,6 @@ #define GET_REGINFO_MC_DESC #include "XCoreGenRegisterInfo.inc" -using namespace llvm; - static MCInstrInfo *createXCoreMCInstrInfo() { MCInstrInfo *X = new MCInstrInfo(); InitXCoreMCInstrInfo(X); @@ -56,7 +58,7 @@ static MCAsmInfo *createXCoreMCAsmInfo(const MCRegisterInfo &MRI, MCAsmInfo *MAI = new XCoreMCAsmInfo(TT); // Initial state of the frame pointer is SP. - MCCFIInstruction Inst = MCCFIInstruction::createDefCfa(0, XCore::SP, 0); + MCCFIInstruction Inst = MCCFIInstruction::createDefCfa(nullptr, XCore::SP, 0); MAI->addInitialFrameState(Inst); return MAI; @@ -69,6 +71,12 @@ static MCCodeGenInfo *createXCoreMCCodeGenInfo(StringRef TT, Reloc::Model RM, if (RM == Reloc::Default) { RM = Reloc::Static; } + if (CM == CodeModel::Default) { + CM = CodeModel::Small; + } + if (CM != CodeModel::Small && CM != CodeModel::Large) + report_fatal_error("Target only supports CodeModel Small or Large"); + X->InitMCCodeGenInfo(RM, CM, OL); return X; } @@ -82,6 +90,53 @@ static MCInstPrinter *createXCoreMCInstPrinter(const Target &T, return new XCoreInstPrinter(MAI, MII, MRI); } +XCoreTargetStreamer::XCoreTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {} +XCoreTargetStreamer::~XCoreTargetStreamer() {} + +namespace { + +class XCoreTargetAsmStreamer : public XCoreTargetStreamer { + formatted_raw_ostream &OS; +public: + XCoreTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS); + virtual void emitCCTopData(StringRef Name) override; + virtual void emitCCTopFunction(StringRef Name) override; + virtual void emitCCBottomData(StringRef Name) override; + virtual void emitCCBottomFunction(StringRef Name) override; +}; + +XCoreTargetAsmStreamer::XCoreTargetAsmStreamer(MCStreamer &S, + formatted_raw_ostream &OS) + : XCoreTargetStreamer(S), OS(OS) {} + +void XCoreTargetAsmStreamer::emitCCTopData(StringRef Name) { + OS << "\t.cc_top " << Name << ".data," << Name << '\n'; +} + +void XCoreTargetAsmStreamer::emitCCTopFunction(StringRef Name) { + OS << "\t.cc_top " << Name << ".function," << Name << '\n'; +} + +void XCoreTargetAsmStreamer::emitCCBottomData(StringRef Name) { + OS << "\t.cc_bottom " << Name << ".data\n"; +} + +void XCoreTargetAsmStreamer::emitCCBottomFunction(StringRef Name) { + OS << "\t.cc_bottom " << Name << ".function\n"; +} +} + +static MCStreamer * +createXCoreMCAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, + bool isVerboseAsm, bool useDwarfDirectory, + MCInstPrinter *InstPrint, MCCodeEmitter *CE, + MCAsmBackend *TAB, bool ShowInst) { + MCStreamer *S = llvm::createAsmStreamer( + Ctx, OS, isVerboseAsm, useDwarfDirectory, InstPrint, CE, TAB, ShowInst); + new XCoreTargetAsmStreamer(*S, OS); + return S; +} + // Force static initialization. extern "C" void LLVMInitializeXCoreTargetMC() { // Register the MC asm info. @@ -104,4 +159,6 @@ extern "C" void LLVMInitializeXCoreTargetMC() { // Register the MCInstPrinter TargetRegistry::RegisterMCInstPrinter(TheXCoreTarget, createXCoreMCInstPrinter); + + TargetRegistry::RegisterAsmStreamer(TheXCoreTarget, createXCoreMCAsmStreamer); } diff --git a/lib/Target/XCore/TargetInfo/CMakeLists.txt b/lib/Target/XCore/TargetInfo/CMakeLists.txt index 2c34b8730c85a..462f2d405304b 100644 --- a/lib/Target/XCore/TargetInfo/CMakeLists.txt +++ b/lib/Target/XCore/TargetInfo/CMakeLists.txt @@ -1,7 +1,3 @@ -include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) - add_llvm_library(LLVMXCoreInfo XCoreTargetInfo.cpp ) - -add_dependencies(LLVMXCoreInfo XCoreCommonTableGen) diff --git a/lib/Target/XCore/TargetInfo/LLVMBuild.txt b/lib/Target/XCore/TargetInfo/LLVMBuild.txt index 770ba87e4a390..45ff75f14359e 100644 --- a/lib/Target/XCore/TargetInfo/LLVMBuild.txt +++ b/lib/Target/XCore/TargetInfo/LLVMBuild.txt @@ -19,5 +19,5 @@ type = Library name = XCoreInfo parent = XCore -required_libraries = MC Support Target +required_libraries = Support add_to_library_groups = XCore diff --git a/lib/Target/XCore/XCore.h b/lib/Target/XCore/XCore.h index 73c310be03442..d707edc8735f1 100644 --- a/lib/Target/XCore/XCore.h +++ b/lib/Target/XCore/XCore.h @@ -27,6 +27,7 @@ namespace llvm { void initializeXCoreLowerThreadLocalPass(PassRegistry &p); + FunctionPass *createXCoreFrameToArgsOffsetEliminationPass(); FunctionPass *createXCoreISelDag(XCoreTargetMachine &TM, CodeGenOpt::Level OptLevel); ModulePass *createXCoreLowerThreadLocalPass(); diff --git a/lib/Target/XCore/XCore.td b/lib/Target/XCore/XCore.td index e9a6d88fd68eb..04a1dd5e95bec 100644 --- a/lib/Target/XCore/XCore.td +++ b/lib/Target/XCore/XCore.td @@ -41,13 +41,7 @@ def : Proc<"xs1b-generic", []>; // Declare the target which we are implementing //===----------------------------------------------------------------------===// -def XCoreAsmWriter : AsmWriter { - string AsmWriterClassName = "InstPrinter"; - bit isMCAsmWriter = 1; -} - def XCore : Target { // Pull in Instruction Info: let InstructionSet = XCoreInstrInfo; - let AssemblyWriters = [XCoreAsmWriter]; } diff --git a/lib/Target/XCore/XCoreAsmPrinter.cpp b/lib/Target/XCore/XCoreAsmPrinter.cpp index c03dfe61504e5..e98d4f933dfbd 100644 --- a/lib/Target/XCore/XCoreAsmPrinter.cpp +++ b/lib/Target/XCore/XCoreAsmPrinter.cpp @@ -12,13 +12,13 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "asm-printer" #include "XCore.h" #include "InstPrinter/XCoreInstPrinter.h" #include "XCoreInstrInfo.h" #include "XCoreMCInstLower.h" #include "XCoreSubtarget.h" #include "XCoreTargetMachine.h" +#include "XCoreTargetStreamer.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/CodeGen/AsmPrinter.h" @@ -27,35 +27,39 @@ #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/DebugInfo.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCExpr.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Target/Mangler.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include <algorithm> #include <cctype> using namespace llvm; +#define DEBUG_TYPE "asm-printer" + namespace { class XCoreAsmPrinter : public AsmPrinter { const XCoreSubtarget &Subtarget; XCoreMCInstLower MCInstLowering; + XCoreTargetStreamer &getTargetStreamer(); + public: explicit XCoreAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) : AsmPrinter(TM, Streamer), Subtarget(TM.getSubtarget<XCoreSubtarget>()), MCInstLowering(*this) {} - virtual const char *getPassName() const { + const char *getPassName() const override { return "XCore Assembly Printer"; } @@ -67,22 +71,29 @@ namespace { void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, const char *ExtraCode, - raw_ostream &O); + raw_ostream &O) override; + bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O) override; void emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV); - virtual void EmitGlobalVariable(const GlobalVariable *GV); + void EmitGlobalVariable(const GlobalVariable *GV) override; - void EmitFunctionEntryLabel(); - void EmitInstruction(const MachineInstr *MI); - void EmitFunctionBodyStart(); - void EmitFunctionBodyEnd(); + void EmitFunctionEntryLabel() override; + void EmitInstruction(const MachineInstr *MI) override; + void EmitFunctionBodyStart() override; + void EmitFunctionBodyEnd() override; }; } // end of anonymous namespace +XCoreTargetStreamer &XCoreAsmPrinter::getTargetStreamer() { + return static_cast<XCoreTargetStreamer&>(*OutStreamer.getTargetStreamer()); +} + void XCoreAsmPrinter::emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV) { - assert(((GV->hasExternalLinkage() || - GV->hasWeakLinkage()) || - GV->hasLinkOnceLinkage()) && "Unexpected linkage"); + assert( ( GV->hasExternalLinkage() || GV->hasWeakLinkage() || + GV->hasLinkOnceLinkage() || GV->hasCommonLinkage() ) && + "Unexpected linkage"); if (ArrayType *ATy = dyn_cast<ArrayType>( cast<PointerType>(GV->getType())->getElementType())) { @@ -92,7 +103,8 @@ void XCoreAsmPrinter::emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV) { OutStreamer.EmitAssignment(SymGlob, MCConstantExpr::Create(ATy->getNumElements(), OutContext)); - if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) { + if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() || + GV->hasCommonLinkage()) { // TODO Use COMDAT groups for LinkOnceLinkage OutStreamer.EmitSymbolAttribute(SymGlob, MCSA_Weak); } @@ -106,16 +118,15 @@ void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { return; const DataLayout *TD = TM.getDataLayout(); - OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GV, Mang,TM)); + OutStreamer.SwitchSection( + getObjFileLowering().SectionForGlobal(GV, *Mang, TM)); - MCSymbol *GVSym = getSymbol(GV); const Constant *C = GV->getInitializer(); unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType()); // Mark the start of the global - OutStreamer.EmitRawText("\t.cc_top " + Twine(GVSym->getName()) + ".data," + - GVSym->getName()); + getTargetStreamer().emitCCTopData(GVSym->getName()); switch (GV->getLinkage()) { case GlobalValue::AppendingLinkage: @@ -125,20 +136,18 @@ void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { case GlobalValue::WeakAnyLinkage: case GlobalValue::WeakODRLinkage: case GlobalValue::ExternalLinkage: + case GlobalValue::CommonLinkage: emitArrayBound(GVSym, GV); OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); // TODO Use COMDAT groups for LinkOnceLinkage - if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) + if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() || + GV->hasCommonLinkage()) OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak); // FALL THROUGH case GlobalValue::InternalLinkage: case GlobalValue::PrivateLinkage: break; - case GlobalValue::DLLImportLinkage: - llvm_unreachable("DLLImport linkage is not supported by this target!"); - case GlobalValue::DLLExportLinkage: - llvm_unreachable("DLLExport linkage is not supported by this target!"); default: llvm_unreachable("Unknown linkage type!"); } @@ -151,8 +160,7 @@ void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { unsigned Size = TD->getTypeAllocSize(C->getType()); if (MAI->hasDotTypeDotSizeDirective()) { OutStreamer.EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject); - OutStreamer.EmitRawText("\t.size " + Twine(GVSym->getName()) + "," + - Twine(Size)); + OutStreamer.EmitELFSize(GVSym, MCConstantExpr::Create(Size, OutContext)); } OutStreamer.EmitLabel(GVSym); @@ -163,7 +171,7 @@ void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { OutStreamer.EmitZeros(4 - Size); // Mark the end of the global - OutStreamer.EmitRawText("\t.cc_bottom " + Twine(GVSym->getName()) + ".data"); + getTargetStreamer().emitCCBottomData(GVSym->getName()); } void XCoreAsmPrinter::EmitFunctionBodyStart() { @@ -174,14 +182,12 @@ void XCoreAsmPrinter::EmitFunctionBodyStart() { /// the last basic block in the function. void XCoreAsmPrinter::EmitFunctionBodyEnd() { // Emit function end directives - OutStreamer.EmitRawText("\t.cc_bottom " + Twine(CurrentFnSym->getName()) + - ".function"); + getTargetStreamer().emitCCBottomFunction(CurrentFnSym->getName()); } void XCoreAsmPrinter::EmitFunctionEntryLabel() { // Mark the start of the function - OutStreamer.EmitRawText("\t.cc_top " + Twine(CurrentFnSym->getName()) + - ".function," + CurrentFnSym->getName()); + getTargetStreamer().emitCCTopFunction(CurrentFnSym->getName()); OutStreamer.EmitLabel(CurrentFnSym); } @@ -204,6 +210,7 @@ printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O, void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum, raw_ostream &O) { + const DataLayout *DL = TM.getDataLayout(); const MachineOperand &MO = MI->getOperand(opNum); switch (MO.getType()) { case MachineOperand::MO_Register: @@ -218,15 +225,8 @@ void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum, case MachineOperand::MO_GlobalAddress: O << *getSymbol(MO.getGlobal()); break; - case MachineOperand::MO_ExternalSymbol: - O << MO.getSymbolName(); - break; case MachineOperand::MO_ConstantPoolIndex: - O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() - << '_' << MO.getIndex(); - break; - case MachineOperand::MO_JumpTableIndex: - O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + O << DL->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' << MO.getIndex(); break; case MachineOperand::MO_BlockAddress: @@ -252,6 +252,20 @@ bool XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O); } +bool XCoreAsmPrinter:: +PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O) { + if (ExtraCode && ExtraCode[0]) { + return true; // Unknown modifier. + } + printOperand(MI, OpNum, O); + O << '['; + printOperand(MI, OpNum + 1, O); + O << ']'; + return false; +} + void XCoreAsmPrinter::EmitInstruction(const MachineInstr *MI) { SmallString<128> Str; raw_svector_ostream O(Str); @@ -284,7 +298,7 @@ void XCoreAsmPrinter::EmitInstruction(const MachineInstr *MI) { MCInst TmpInst; MCInstLowering.Lower(MI, TmpInst); - OutStreamer.EmitInstruction(TmpInst); + EmitToStreamer(OutStreamer, TmpInst); } // Force static initialization. diff --git a/lib/Target/XCore/XCoreCallingConv.td b/lib/Target/XCore/XCoreCallingConv.td index b20d71f49cfd6..e149e6d9ec20b 100644 --- a/lib/Target/XCore/XCoreCallingConv.td +++ b/lib/Target/XCore/XCoreCallingConv.td @@ -14,7 +14,11 @@ //===----------------------------------------------------------------------===// def RetCC_XCore : CallingConv<[ // i32 are returned in registers R0, R1, R2, R3 - CCIfType<[i32], CCAssignToReg<[R0, R1, R2, R3]>> + CCIfType<[i32], CCAssignToReg<[R0, R1, R2, R3]>>, + + // Integer values get stored in stack slots that are 4 bytes in + // size and 4-byte aligned. + CCIfType<[i32], CCAssignToStack<4, 4>> ]>; //===----------------------------------------------------------------------===// diff --git a/lib/Target/XCore/XCoreFrameLowering.cpp b/lib/Target/XCore/XCoreFrameLowering.cpp index c34b35c140f96..e6947369c2d7a 100644 --- a/lib/Target/XCore/XCoreFrameLowering.cpp +++ b/lib/Target/XCore/XCoreFrameLowering.cpp @@ -25,10 +25,15 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetOptions.h" +#include <algorithm> // std::sort using namespace llvm; +static const unsigned FramePtr = XCore::R10; +static const int MaxImmU16 = (1<<16) - 1; + // helper functions. FIXME: Eliminate. static inline bool isImmU6(unsigned val) { return val < (1 << 6); @@ -38,37 +43,168 @@ static inline bool isImmU16(unsigned val) { return val < (1 << 16); } -static void loadFromStack(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - unsigned DstReg, int Offset, DebugLoc dl, - const TargetInstrInfo &TII) { - assert(Offset%4 == 0 && "Misaligned stack offset"); - Offset/=4; - bool isU6 = isImmU6(Offset); - if (!isU6 && !isImmU16(Offset)) - report_fatal_error("loadFromStack offset too big " + Twine(Offset)); - int Opcode = isU6 ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6; - BuildMI(MBB, I, dl, TII.get(Opcode), DstReg) - .addImm(Offset); +// Helper structure with compare function for handling stack slots. +namespace { +struct StackSlotInfo { + int FI; + int Offset; + unsigned Reg; + StackSlotInfo(int f, int o, int r) : FI(f), Offset(o), Reg(r){}; +}; +} // end anonymous namespace + +static bool CompareSSIOffset(const StackSlotInfo& a, const StackSlotInfo& b) { + return a.Offset < b.Offset; +} + + +static void EmitDefCfaRegister(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, DebugLoc dl, + const TargetInstrInfo &TII, + MachineModuleInfo *MMI, unsigned DRegNum) { + unsigned CFIIndex = MMI->addFrameInst( + MCCFIInstruction::createDefCfaRegister(nullptr, DRegNum)); + BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex); +} + +static void EmitDefCfaOffset(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, DebugLoc dl, + const TargetInstrInfo &TII, + MachineModuleInfo *MMI, int Offset) { + unsigned CFIIndex = + MMI->addFrameInst(MCCFIInstruction::createDefCfaOffset(nullptr, -Offset)); + BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex); +} + +static void EmitCfiOffset(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, DebugLoc dl, + const TargetInstrInfo &TII, MachineModuleInfo *MMI, + unsigned DRegNum, int Offset) { + unsigned CFIIndex = MMI->addFrameInst( + MCCFIInstruction::createOffset(nullptr, DRegNum, Offset)); + BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex); +} + +/// The SP register is moved in steps of 'MaxImmU16' towards the bottom of the +/// frame. During these steps, it may be necessary to spill registers. +/// IfNeededExtSP emits the necessary EXTSP instructions to move the SP only +/// as far as to make 'OffsetFromBottom' reachable using an STWSP_lru6. +/// \param OffsetFromTop the spill offset from the top of the frame. +/// \param [in,out] Adjusted the current SP offset from the top of the frame. +static void IfNeededExtSP(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, DebugLoc dl, + const TargetInstrInfo &TII, MachineModuleInfo *MMI, + int OffsetFromTop, int &Adjusted, int FrameSize, + bool emitFrameMoves) { + while (OffsetFromTop > Adjusted) { + assert(Adjusted < FrameSize && "OffsetFromTop is beyond FrameSize"); + int remaining = FrameSize - Adjusted; + int OpImm = (remaining > MaxImmU16) ? MaxImmU16 : remaining; + int Opcode = isImmU6(OpImm) ? XCore::EXTSP_u6 : XCore::EXTSP_lu6; + BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(OpImm); + Adjusted += OpImm; + if (emitFrameMoves) + EmitDefCfaOffset(MBB, MBBI, dl, TII, MMI, Adjusted*4); + } +} + +/// The SP register is moved in steps of 'MaxImmU16' towards the top of the +/// frame. During these steps, it may be necessary to re-load registers. +/// IfNeededLDAWSP emits the necessary LDAWSP instructions to move the SP only +/// as far as to make 'OffsetFromTop' reachable using an LDAWSP_lru6. +/// \param OffsetFromTop the spill offset from the top of the frame. +/// \param [in,out] RemainingAdj the current SP offset from the top of the +/// frame. +static void IfNeededLDAWSP(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, DebugLoc dl, + const TargetInstrInfo &TII, int OffsetFromTop, + int &RemainingAdj) { + while (OffsetFromTop < RemainingAdj - MaxImmU16) { + assert(RemainingAdj && "OffsetFromTop is beyond FrameSize"); + int OpImm = (RemainingAdj > MaxImmU16) ? MaxImmU16 : RemainingAdj; + int Opcode = isImmU6(OpImm) ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6; + BuildMI(MBB, MBBI, dl, TII.get(Opcode), XCore::SP).addImm(OpImm); + RemainingAdj -= OpImm; + } +} + +/// Creates an ordered list of registers that are spilled +/// during the emitPrologue/emitEpilogue. +/// Registers are ordered according to their frame offset. +/// As offsets are negative, the largest offsets will be first. +static void GetSpillList(SmallVectorImpl<StackSlotInfo> &SpillList, + MachineFrameInfo *MFI, XCoreFunctionInfo *XFI, + bool fetchLR, bool fetchFP) { + if (fetchLR) { + int Offset = MFI->getObjectOffset(XFI->getLRSpillSlot()); + SpillList.push_back(StackSlotInfo(XFI->getLRSpillSlot(), + Offset, + XCore::LR)); + } + if (fetchFP) { + int Offset = MFI->getObjectOffset(XFI->getFPSpillSlot()); + SpillList.push_back(StackSlotInfo(XFI->getFPSpillSlot(), + Offset, + FramePtr)); + } + std::sort(SpillList.begin(), SpillList.end(), CompareSSIOffset); +} + +/// Creates an ordered list of EH info register 'spills'. +/// These slots are only used by the unwinder and calls to llvm.eh.return(). +/// Registers are ordered according to their frame offset. +/// As offsets are negative, the largest offsets will be first. +static void GetEHSpillList(SmallVectorImpl<StackSlotInfo> &SpillList, + MachineFrameInfo *MFI, XCoreFunctionInfo *XFI, + const TargetLowering *TL) { + assert(XFI->hasEHSpillSlot() && "There are no EH register spill slots"); + const int* EHSlot = XFI->getEHSpillSlot(); + SpillList.push_back(StackSlotInfo(EHSlot[0], + MFI->getObjectOffset(EHSlot[0]), + TL->getExceptionPointerRegister())); + SpillList.push_back(StackSlotInfo(EHSlot[0], + MFI->getObjectOffset(EHSlot[1]), + TL->getExceptionSelectorRegister())); + std::sort(SpillList.begin(), SpillList.end(), CompareSSIOffset); } -static void storeToStack(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - unsigned SrcReg, int Offset, DebugLoc dl, - const TargetInstrInfo &TII) { - assert(Offset%4 == 0 && "Misaligned stack offset"); - Offset/=4; - bool isU6 = isImmU6(Offset); - if (!isU6 && !isImmU16(Offset)) - report_fatal_error("storeToStack offset too big " + Twine(Offset)); - int Opcode = isU6 ? XCore::STWSP_ru6 : XCore::STWSP_lru6; - BuildMI(MBB, I, dl, TII.get(Opcode)) - .addReg(SrcReg) - .addImm(Offset); +static MachineMemOperand * +getFrameIndexMMO(MachineBasicBlock &MBB, int FrameIndex, unsigned flags) { + MachineFunction *MF = MBB.getParent(); + const MachineFrameInfo &MFI = *MF->getFrameInfo(); + MachineMemOperand *MMO = + MF->getMachineMemOperand(MachinePointerInfo::getFixedStack(FrameIndex), + flags, MFI.getObjectSize(FrameIndex), + MFI.getObjectAlignment(FrameIndex)); + return MMO; } +/// Restore clobbered registers with their spill slot value. +/// The SP will be adjusted at the same time, thus the SpillList must be ordered +/// with the largest (negative) offsets first. +static void +RestoreSpillList(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + DebugLoc dl, const TargetInstrInfo &TII, int &RemainingAdj, + SmallVectorImpl<StackSlotInfo> &SpillList) { + for (unsigned i = 0, e = SpillList.size(); i != e; ++i) { + assert(SpillList[i].Offset % 4 == 0 && "Misaligned stack offset"); + assert(SpillList[i].Offset <= 0 && "Unexpected positive stack offset"); + int OffsetFromTop = - SpillList[i].Offset/4; + IfNeededLDAWSP(MBB, MBBI, dl, TII, OffsetFromTop, RemainingAdj); + int Offset = RemainingAdj - OffsetFromTop; + int Opcode = isImmU6(Offset) ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6; + BuildMI(MBB, MBBI, dl, TII.get(Opcode), SpillList[i].Reg) + .addImm(Offset) + .addMemOperand(getFrameIndexMMO(MBB, SpillList[i].FI, + MachineMemOperand::MOLoad)); + } +} + //===----------------------------------------------------------------------===// // XCoreFrameLowering: //===----------------------------------------------------------------------===// @@ -80,7 +216,7 @@ XCoreFrameLowering::XCoreFrameLowering(const XCoreSubtarget &sti) bool XCoreFrameLowering::hasFP(const MachineFunction &MF) const { return MF.getTarget().Options.DisableFramePointerElim(MF) || - MF.getFrameInfo()->hasVarSizedObjects(); + MF.getFrameInfo()->hasVarSizedObjects(); } void XCoreFrameLowering::emitPrologue(MachineFunction &MF) const { @@ -92,219 +228,225 @@ void XCoreFrameLowering::emitPrologue(MachineFunction &MF) const { const XCoreInstrInfo &TII = *static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo()); XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); - DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); + // Debug location must be unknown since the first debug location is used + // to determine the end of the prologue. + DebugLoc dl; if (MFI->getMaxAlignment() > getStackAlignment()) report_fatal_error("emitPrologue unsupported alignment: " + Twine(MFI->getMaxAlignment())); - bool FP = hasFP(MF); const AttributeSet &PAL = MF.getFunction()->getAttributes(); - if (PAL.hasAttrSomewhere(Attribute::Nest)) - loadFromStack(MBB, MBBI, XCore::R11, 0, dl, TII); + BuildMI(MBB, MBBI, dl, TII.get(XCore::LDWSP_ru6), XCore::R11).addImm(0); + // FIX: Needs addMemOperand() but can't use getFixedStack() or getStack(). // Work out frame sizes. - int FrameSize = MFI->getStackSize(); - assert(FrameSize%4 == 0 && "Misaligned frame size"); - FrameSize/=4; + // We will adjust the SP in stages towards the final FrameSize. + assert(MFI->getStackSize()%4 == 0 && "Misaligned frame size"); + const int FrameSize = MFI->getStackSize() / 4; + int Adjusted = 0; - bool isU6 = isImmU6(FrameSize); - - if (!isU6 && !isImmU16(FrameSize)) { - // FIXME could emit multiple instructions. - report_fatal_error("emitPrologue Frame size too big: " + Twine(FrameSize)); - } + bool saveLR = XFI->hasLRSpillSlot(); + bool UseENTSP = saveLR && FrameSize + && (MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0); + if (UseENTSP) + saveLR = false; + bool FP = hasFP(MF); bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(MF); - bool saveLR = XFI->getUsesLR(); - // Do we need to allocate space on the stack? - if (FrameSize) { - bool LRSavedOnEntry = false; - int Opcode; - if (saveLR && (MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0)) { - Opcode = (isU6) ? XCore::ENTSP_u6 : XCore::ENTSP_lu6; - MBB.addLiveIn(XCore::LR); - saveLR = false; - LRSavedOnEntry = true; - } else { - Opcode = (isU6) ? XCore::EXTSP_u6 : XCore::EXTSP_lu6; - } - BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(FrameSize); - + if (UseENTSP) { + // Allocate space on the stack at the same time as saving LR. + Adjusted = (FrameSize > MaxImmU16) ? MaxImmU16 : FrameSize; + int Opcode = isImmU6(Adjusted) ? XCore::ENTSP_u6 : XCore::ENTSP_lu6; + MBB.addLiveIn(XCore::LR); + MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opcode)); + MIB.addImm(Adjusted); + MIB->addRegisterKilled(XCore::LR, MF.getTarget().getRegisterInfo(), true); if (emitFrameMoves) { - // Show update of SP. - MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol(); - BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(FrameLabel); - MMI->addFrameInst(MCCFIInstruction::createDefCfaOffset(FrameLabel, - -FrameSize*4)); - if (LRSavedOnEntry) { - unsigned Reg = MRI->getDwarfRegNum(XCore::LR, true); - MMI->addFrameInst(MCCFIInstruction::createOffset(FrameLabel, Reg, 0)); - } + EmitDefCfaOffset(MBB, MBBI, dl, TII, MMI, Adjusted*4); + unsigned DRegNum = MRI->getDwarfRegNum(XCore::LR, true); + EmitCfiOffset(MBB, MBBI, dl, TII, MMI, DRegNum, 0); } } - if (saveLR) { - int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot()); - storeToStack(MBB, MBBI, XCore::LR, LRSpillOffset + FrameSize*4, dl, TII); - MBB.addLiveIn(XCore::LR); + // If necessary, save LR and FP to the stack, as we EXTSP. + SmallVector<StackSlotInfo,2> SpillList; + GetSpillList(SpillList, MFI, XFI, saveLR, FP); + // We want the nearest (negative) offsets first, so reverse list. + std::reverse(SpillList.begin(), SpillList.end()); + for (unsigned i = 0, e = SpillList.size(); i != e; ++i) { + assert(SpillList[i].Offset % 4 == 0 && "Misaligned stack offset"); + assert(SpillList[i].Offset <= 0 && "Unexpected positive stack offset"); + int OffsetFromTop = - SpillList[i].Offset/4; + IfNeededExtSP(MBB, MBBI, dl, TII, MMI, OffsetFromTop, Adjusted, FrameSize, + emitFrameMoves); + int Offset = Adjusted - OffsetFromTop; + int Opcode = isImmU6(Offset) ? XCore::STWSP_ru6 : XCore::STWSP_lru6; + MBB.addLiveIn(SpillList[i].Reg); + BuildMI(MBB, MBBI, dl, TII.get(Opcode)) + .addReg(SpillList[i].Reg, RegState::Kill) + .addImm(Offset) + .addMemOperand(getFrameIndexMMO(MBB, SpillList[i].FI, + MachineMemOperand::MOStore)); if (emitFrameMoves) { - MCSymbol *SaveLRLabel = MMI->getContext().CreateTempSymbol(); - BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(SaveLRLabel); - unsigned Reg = MRI->getDwarfRegNum(XCore::LR, true); - MMI->addFrameInst(MCCFIInstruction::createOffset(SaveLRLabel, Reg, - LRSpillOffset)); + unsigned DRegNum = MRI->getDwarfRegNum(SpillList[i].Reg, true); + EmitCfiOffset(MBB, MBBI, dl, TII, MMI, DRegNum, SpillList[i].Offset); } } + // Complete any remaining Stack adjustment. + IfNeededExtSP(MBB, MBBI, dl, TII, MMI, FrameSize, Adjusted, FrameSize, + emitFrameMoves); + assert(Adjusted==FrameSize && "IfNeededExtSP has not completed adjustment"); + if (FP) { - // Save R10 to the stack. - int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot()); - storeToStack(MBB, MBBI, XCore::R10, FPSpillOffset + FrameSize*4, dl, TII); - // R10 is live-in. It is killed at the spill. - MBB.addLiveIn(XCore::R10); - if (emitFrameMoves) { - MCSymbol *SaveR10Label = MMI->getContext().CreateTempSymbol(); - BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(SaveR10Label); - unsigned Reg = MRI->getDwarfRegNum(XCore::R10, true); - MMI->addFrameInst(MCCFIInstruction::createOffset(SaveR10Label, Reg, - FPSpillOffset)); - } // Set the FP from the SP. - unsigned FramePtr = XCore::R10; BuildMI(MBB, MBBI, dl, TII.get(XCore::LDAWSP_ru6), FramePtr).addImm(0); - if (emitFrameMoves) { - // Show FP is now valid. - MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol(); - BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(FrameLabel); - unsigned Reg = MRI->getDwarfRegNum(FramePtr, true); - MMI->addFrameInst(MCCFIInstruction::createDefCfaRegister(FrameLabel, - Reg)); - } + if (emitFrameMoves) + EmitDefCfaRegister(MBB, MBBI, dl, TII, MMI, + MRI->getDwarfRegNum(FramePtr, true)); } if (emitFrameMoves) { // Frame moves for callee saved. - std::vector<std::pair<MCSymbol*, CalleeSavedInfo> >&SpillLabels = - XFI->getSpillLabels(); + auto SpillLabels = XFI->getSpillLabels(); for (unsigned I = 0, E = SpillLabels.size(); I != E; ++I) { - MCSymbol *SpillLabel = SpillLabels[I].first; + MachineBasicBlock::iterator Pos = SpillLabels[I].first; + ++Pos; CalleeSavedInfo &CSI = SpillLabels[I].second; int Offset = MFI->getObjectOffset(CSI.getFrameIdx()); - unsigned Reg = MRI->getDwarfRegNum(CSI.getReg(), true); - MMI->addFrameInst(MCCFIInstruction::createOffset(SpillLabel, Reg, - Offset)); + unsigned DRegNum = MRI->getDwarfRegNum(CSI.getReg(), true); + EmitCfiOffset(MBB, Pos, dl, TII, MMI, DRegNum, Offset); + } + if (XFI->hasEHSpillSlot()) { + // The unwinder requires stack slot & CFI offsets for the exception info. + // We do not save/spill these registers. + SmallVector<StackSlotInfo,2> SpillList; + GetEHSpillList(SpillList, MFI, XFI, MF.getTarget().getTargetLowering()); + assert(SpillList.size()==2 && "Unexpected SpillList size"); + EmitCfiOffset(MBB, MBBI, dl, TII, MMI, + MRI->getDwarfRegNum(SpillList[0].Reg, true), + SpillList[0].Offset); + EmitCfiOffset(MBB, MBBI, dl, TII, MMI, + MRI->getDwarfRegNum(SpillList[1].Reg, true), + SpillList[1].Offset); } } } void XCoreFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { - MachineFrameInfo *MFI = MF.getFrameInfo(); + MachineFrameInfo *MFI = MF.getFrameInfo(); MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); const XCoreInstrInfo &TII = *static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo()); XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); DebugLoc dl = MBBI->getDebugLoc(); - - bool FP = hasFP(MF); - if (FP) { - // Restore the stack pointer. - unsigned FramePtr = XCore::R10; - BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r)) - .addReg(FramePtr); - } + unsigned RetOpcode = MBBI->getOpcode(); // Work out frame sizes. - int FrameSize = MFI->getStackSize(); + // We will adjust the SP in stages towards the final FrameSize. + int RemainingAdj = MFI->getStackSize(); + assert(RemainingAdj%4 == 0 && "Misaligned frame size"); + RemainingAdj /= 4; - assert(FrameSize%4 == 0 && "Misaligned frame size"); + if (RetOpcode == XCore::EH_RETURN) { + // 'Restore' the exception info the unwinder has placed into the stack + // slots. + SmallVector<StackSlotInfo,2> SpillList; + GetEHSpillList(SpillList, MFI, XFI, MF.getTarget().getTargetLowering()); + RestoreSpillList(MBB, MBBI, dl, TII, RemainingAdj, SpillList); - FrameSize/=4; - - bool isU6 = isImmU6(FrameSize); - - if (!isU6 && !isImmU16(FrameSize)) { - // FIXME could emit multiple instructions. - report_fatal_error("emitEpilogue Frame size too big: " + Twine(FrameSize)); - } - - if (FP) { - // Restore R10 - int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot()); - FPSpillOffset += FrameSize*4; - loadFromStack(MBB, MBBI, XCore::R10, FPSpillOffset, dl, TII); + // Return to the landing pad. + unsigned EhStackReg = MBBI->getOperand(0).getReg(); + unsigned EhHandlerReg = MBBI->getOperand(1).getReg(); + BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r)).addReg(EhStackReg); + BuildMI(MBB, MBBI, dl, TII.get(XCore::BAU_1r)).addReg(EhHandlerReg); + MBB.erase(MBBI); // Erase the previous return instruction. + return; } - bool restoreLR = XFI->getUsesLR(); - if (restoreLR && - (FrameSize == 0 || MFI->getObjectOffset(XFI->getLRSpillSlot()) != 0)) { - int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot()); - LRSpillOffset += FrameSize*4; - loadFromStack(MBB, MBBI, XCore::LR, LRSpillOffset, dl, TII); + bool restoreLR = XFI->hasLRSpillSlot(); + bool UseRETSP = restoreLR && RemainingAdj + && (MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0); + if (UseRETSP) restoreLR = false; - } + bool FP = hasFP(MF); + + if (FP) // Restore the stack pointer. + BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r)).addReg(FramePtr); + + // If necessary, restore LR and FP from the stack, as we EXTSP. + SmallVector<StackSlotInfo,2> SpillList; + GetSpillList(SpillList, MFI, XFI, restoreLR, FP); + RestoreSpillList(MBB, MBBI, dl, TII, RemainingAdj, SpillList); - if (FrameSize) { - if (restoreLR) { + if (RemainingAdj) { + // Complete all but one of the remaining Stack adjustments. + IfNeededLDAWSP(MBB, MBBI, dl, TII, 0, RemainingAdj); + if (UseRETSP) { // Fold prologue into return instruction - assert(MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0); - assert(MBBI->getOpcode() == XCore::RETSP_u6 - || MBBI->getOpcode() == XCore::RETSP_lu6); - int Opcode = (isU6) ? XCore::RETSP_u6 : XCore::RETSP_lu6; - MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(FrameSize); + assert(RetOpcode == XCore::RETSP_u6 + || RetOpcode == XCore::RETSP_lu6); + int Opcode = isImmU6(RemainingAdj) ? XCore::RETSP_u6 : XCore::RETSP_lu6; + MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opcode)) + .addImm(RemainingAdj); for (unsigned i = 3, e = MBBI->getNumOperands(); i < e; ++i) MIB->addOperand(MBBI->getOperand(i)); // copy any variadic operands - MBB.erase(MBBI); + MBB.erase(MBBI); // Erase the previous return instruction. } else { - int Opcode = (isU6) ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6; - BuildMI(MBB, MBBI, dl, TII.get(Opcode), XCore::SP).addImm(FrameSize); + int Opcode = isImmU6(RemainingAdj) ? XCore::LDAWSP_ru6 : + XCore::LDAWSP_lru6; + BuildMI(MBB, MBBI, dl, TII.get(Opcode), XCore::SP).addImm(RemainingAdj); + // Don't erase the return instruction. } - } + } // else Don't erase the return instruction. } -bool XCoreFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector<CalleeSavedInfo> &CSI, - const TargetRegisterInfo *TRI) const { +bool XCoreFrameLowering:: +spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector<CalleeSavedInfo> &CSI, + const TargetRegisterInfo *TRI) const { if (CSI.empty()) return true; MachineFunction *MF = MBB.getParent(); const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); - XCoreFunctionInfo *XFI = MF->getInfo<XCoreFunctionInfo>(); bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(*MF); DebugLoc DL; - if (MI != MBB.end()) DL = MI->getDebugLoc(); + if (MI != MBB.end() && !MI->isDebugValue()) + DL = MI->getDebugLoc(); for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin(); it != CSI.end(); ++it) { - // Add the callee-saved register as live-in. It's killed at the spill. - MBB.addLiveIn(it->getReg()); - unsigned Reg = it->getReg(); + assert(Reg != XCore::LR && !(Reg == XCore::R10 && hasFP(*MF)) && + "LR & FP are always handled in emitPrologue"); + + // Add the callee-saved register as live-in. It's killed at the spill. + MBB.addLiveIn(Reg); const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); - TII.storeRegToStackSlot(MBB, MI, Reg, true, - it->getFrameIdx(), RC, TRI); + TII.storeRegToStackSlot(MBB, MI, Reg, true, it->getFrameIdx(), RC, TRI); if (emitFrameMoves) { - MCSymbol *SaveLabel = MF->getContext().CreateTempSymbol(); - BuildMI(MBB, MI, DL, TII.get(XCore::PROLOG_LABEL)).addSym(SaveLabel); - XFI->getSpillLabels().push_back(std::make_pair(SaveLabel, *it)); + auto Store = MI; + --Store; + XFI->getSpillLabels().push_back(std::make_pair(Store, *it)); } } return true; } -bool XCoreFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector<CalleeSavedInfo> &CSI, - const TargetRegisterInfo *TRI) const{ +bool XCoreFrameLowering:: +restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector<CalleeSavedInfo> &CSI, + const TargetRegisterInfo *TRI) const{ MachineFunction *MF = MBB.getParent(); const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); - bool AtStart = MI == MBB.begin(); MachineBasicBlock::iterator BeforeI = MI; if (!AtStart) @@ -312,9 +454,11 @@ bool XCoreFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin(); it != CSI.end(); ++it) { unsigned Reg = it->getReg(); + assert(Reg != XCore::LR && !(Reg == XCore::R10 && hasFP(*MF)) && + "LR & FP are always handled in emitEpilogue"); + const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); - TII.loadRegFromStackSlot(MBB, MI, it->getReg(), it->getFrameIdx(), - RC, TRI); + TII.loadRegFromStackSlot(MBB, MI, Reg, it->getFrameIdx(), RC, TRI); assert(MI != MBB.begin() && "loadRegFromStackSlot didn't insert any code!"); // Insert in reverse order. loadRegFromStackSlot can insert multiple @@ -358,7 +502,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, errs() << "eliminateCallFramePseudoInstr size too big: " << Amount << "\n"; #endif - llvm_unreachable(0); + llvm_unreachable(nullptr); } MachineInstr *New; @@ -377,44 +521,62 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MBB.insert(I, New); } } - + MBB.erase(I); } -void -XCoreFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF, - RegScavenger *RS) const { - MachineFrameInfo *MFI = MF.getFrameInfo(); - const TargetRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo(); - bool LRUsed = MF.getRegInfo().isPhysRegUsed(XCore::LR); - const TargetRegisterClass *RC = &XCore::GRRegsRegClass; +void XCoreFrameLowering:: +processFunctionBeforeCalleeSavedScan(MachineFunction &MF, + RegScavenger *RS) const { XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); + + bool LRUsed = MF.getRegInfo().isPhysRegUsed(XCore::LR); + + if (!LRUsed && !MF.getFunction()->isVarArg() && + MF.getFrameInfo()->estimateStackSize(MF)) + // If we need to extend the stack it is more efficient to use entsp / retsp. + // We force the LR to be saved so these instructions are used. + LRUsed = true; + + if (MF.getMMI().callsUnwindInit() || MF.getMMI().callsEHReturn()) { + // The unwinder expects to find spill slots for the exception info regs R0 + // & R1. These are used during llvm.eh.return() to 'restore' the exception + // info. N.B. we do not spill or restore R0, R1 during normal operation. + XFI->createEHSpillSlot(MF); + // As we will have a stack, we force the LR to be saved. + LRUsed = true; + } + if (LRUsed) { + // We will handle the LR in the prologue/epilogue + // and allocate space on the stack ourselves. MF.getRegInfo().setPhysRegUnused(XCore::LR); - - bool isVarArg = MF.getFunction()->isVarArg(); - int FrameIdx; - if (! isVarArg) { - // A fixed offset of 0 allows us to save / restore LR using entsp / retsp. - FrameIdx = MFI->CreateFixedObject(RC->getSize(), 0, true); - } else { - FrameIdx = MFI->CreateStackObject(RC->getSize(), RC->getAlignment(), - false); - } - XFI->setUsesLR(FrameIdx); - XFI->setLRSpillSlot(FrameIdx); + XFI->createLRSpillSlot(MF); } - if (RegInfo->requiresRegisterScavenging(MF)) { - // Reserve a slot close to SP or frame pointer. + + if (hasFP(MF)) + // A callee save register is used to hold the FP. + // This needs saving / restoring in the epilogue / prologue. + XFI->createFPSpillSlot(MF); +} + +void XCoreFrameLowering:: +processFunctionBeforeFrameFinalized(MachineFunction &MF, + RegScavenger *RS) const { + assert(RS && "requiresRegisterScavenging failed"); + MachineFrameInfo *MFI = MF.getFrameInfo(); + const TargetRegisterClass *RC = &XCore::GRRegsRegClass; + XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); + // Reserve slots close to SP or frame pointer for Scavenging spills. + // When using SP for small frames, we don't need any scratch registers. + // When using SP for large frames, we may need 2 scratch registers. + // When using FP, for large or small frames, we may need 1 scratch register. + if (XFI->isLargeFrame(MF) || hasFP(MF)) + RS->addScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(), + RC->getAlignment(), + false)); + if (XFI->isLargeFrame(MF) && !hasFP(MF)) RS->addScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(), RC->getAlignment(), false)); - } - if (hasFP(MF)) { - // A callee save register is used to hold the FP. - // This needs saving / restoring in the epilogue / prologue. - XFI->setFPSpillSlot(MFI->CreateStackObject(RC->getSize(), - RC->getAlignment(), - false)); - } } diff --git a/lib/Target/XCore/XCoreFrameLowering.h b/lib/Target/XCore/XCoreFrameLowering.h index ebad62f2fa53a..e4f806a4520c9 100644 --- a/lib/Target/XCore/XCoreFrameLowering.h +++ b/lib/Target/XCore/XCoreFrameLowering.h @@ -27,26 +27,30 @@ namespace llvm { /// emitProlog/emitEpilog - These methods insert prolog and epilog code into /// the function. - void emitPrologue(MachineFunction &MF) const; - void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; + void emitPrologue(MachineFunction &MF) const override; + void emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const override; bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector<CalleeSavedInfo> &CSI, - const TargetRegisterInfo *TRI) const; + MachineBasicBlock::iterator MI, + const std::vector<CalleeSavedInfo> &CSI, + const TargetRegisterInfo *TRI) const override; bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector<CalleeSavedInfo> &CSI, - const TargetRegisterInfo *TRI) const; + MachineBasicBlock::iterator MI, + const std::vector<CalleeSavedInfo> &CSI, + const TargetRegisterInfo *TRI) const override; void eliminateCallFramePseudoInstr(MachineFunction &MF, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const; + MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const override; - bool hasFP(const MachineFunction &MF) const; + bool hasFP(const MachineFunction &MF) const override; void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, - RegScavenger *RS = NULL) const; + RegScavenger *RS = nullptr) const override; + + void processFunctionBeforeFrameFinalized(MachineFunction &MF, + RegScavenger *RS = nullptr) const override; //! Stack slot size (4 bytes) static int stackSlotSize() { diff --git a/lib/Target/XCore/XCoreFrameToArgsOffsetElim.cpp b/lib/Target/XCore/XCoreFrameToArgsOffsetElim.cpp new file mode 100644 index 0000000000000..30c7b59098dd7 --- /dev/null +++ b/lib/Target/XCore/XCoreFrameToArgsOffsetElim.cpp @@ -0,0 +1,62 @@ +//===-- XCoreFrameToArgsOffsetElim.cpp ----------------------------*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Replace Pseudo FRAME_TO_ARGS_OFFSET with the appropriate real offset. +// +//===----------------------------------------------------------------------===// + +#include "XCore.h" +#include "XCoreInstrInfo.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetMachine.h" +using namespace llvm; + +namespace { + struct XCoreFTAOElim : public MachineFunctionPass { + static char ID; + XCoreFTAOElim() : MachineFunctionPass(ID) {} + + bool runOnMachineFunction(MachineFunction &Fn) override; + + const char *getPassName() const override { + return "XCore FRAME_TO_ARGS_OFFSET Elimination"; + } + }; + char XCoreFTAOElim::ID = 0; +} + +/// createXCoreFrameToArgsOffsetEliminationPass - returns an instance of the +/// Frame to args offset elimination pass +FunctionPass *llvm::createXCoreFrameToArgsOffsetEliminationPass() { + return new XCoreFTAOElim(); +} + +bool XCoreFTAOElim::runOnMachineFunction(MachineFunction &MF) { + const XCoreInstrInfo &TII = + *static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo()); + unsigned StackSize = MF.getFrameInfo()->getStackSize(); + for (MachineFunction::iterator MFI = MF.begin(), E = MF.end(); MFI != E; + ++MFI) { + MachineBasicBlock &MBB = *MFI; + for (MachineBasicBlock::iterator MBBI = MBB.begin(), EE = MBB.end(); + MBBI != EE; ++MBBI) { + if (MBBI->getOpcode() == XCore::FRAME_TO_ARGS_OFFSET) { + MachineInstr *OldInst = MBBI; + unsigned Reg = OldInst->getOperand(0).getReg(); + MBBI = TII.loadImmediate(MBB, MBBI, Reg, StackSize); + OldInst->eraseFromParent(); + } + } + } + return true; +} diff --git a/lib/Target/XCore/XCoreISelDAGToDAG.cpp b/lib/Target/XCore/XCoreISelDAGToDAG.cpp index e28f84fec2a98..86bc6f27ca539 100644 --- a/lib/Target/XCore/XCoreISelDAGToDAG.cpp +++ b/lib/Target/XCore/XCoreISelDAGToDAG.cpp @@ -44,7 +44,7 @@ namespace { : SelectionDAGISel(TM, OptLevel), Subtarget(*TM.getSubtargetImpl()) { } - SDNode *Select(SDNode *N); + SDNode *Select(SDNode *N) override; SDNode *SelectBRIND(SDNode *N); /// getI32Imm - Return a target constant with the specified value, of type @@ -66,8 +66,11 @@ namespace { // Complex Pattern Selectors. bool SelectADDRspii(SDValue Addr, SDValue &Base, SDValue &Offset); - - virtual const char *getPassName() const { + + bool SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, + std::vector<SDValue> &OutOps) override; + + const char *getPassName() const override { return "XCore DAG->DAG Pattern Instruction Selection"; } @@ -86,14 +89,14 @@ FunctionPass *llvm::createXCoreISelDag(XCoreTargetMachine &TM, bool XCoreDAGToDAGISel::SelectADDRspii(SDValue Addr, SDValue &Base, SDValue &Offset) { - FrameIndexSDNode *FIN = 0; + FrameIndexSDNode *FIN = nullptr; if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) { Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); Offset = CurDAG->getTargetConstant(0, MVT::i32); return true; } if (Addr.getOpcode() == ISD::ADD) { - ConstantSDNode *CN = 0; + ConstantSDNode *CN = nullptr; if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) && (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) { @@ -106,6 +109,28 @@ bool XCoreDAGToDAGISel::SelectADDRspii(SDValue Addr, SDValue &Base, return false; } +bool XCoreDAGToDAGISel:: +SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, + std::vector<SDValue> &OutOps) { + SDValue Reg; + switch (ConstraintCode) { + default: return true; + case 'm': // Memory. + switch (Op.getOpcode()) { + default: return true; + case XCoreISD::CPRelativeWrapper: + Reg = CurDAG->getRegister(XCore::CP, MVT::i32); + break; + case XCoreISD::DPRelativeWrapper: + Reg = CurDAG->getRegister(XCore::DP, MVT::i32); + break; + } + } + OutOps.push_back(Reg); + OutOps.push_back(Op.getOperand(0)); + return false; +} + SDNode *XCoreDAGToDAGISel::Select(SDNode *N) { SDLoc dl(N); switch (N->getOpcode()) { @@ -202,8 +227,7 @@ replaceInChain(SelectionDAG *CurDAG, SDValue Chain, SDValue Old, SDValue New) } if (!found) return SDValue(); - return CurDAG->getNode(ISD::TokenFactor, SDLoc(Chain), MVT::Other, - &Ops[0], Ops.size()); + return CurDAG->getNode(ISD::TokenFactor, SDLoc(Chain), MVT::Other, Ops); } SDNode *XCoreDAGToDAGISel::SelectBRIND(SDNode *N) { @@ -212,10 +236,10 @@ SDNode *XCoreDAGToDAGISel::SelectBRIND(SDNode *N) { SDValue Chain = N->getOperand(0); SDValue Addr = N->getOperand(1); if (Addr->getOpcode() != ISD::INTRINSIC_W_CHAIN) - return 0; + return nullptr; unsigned IntNo = cast<ConstantSDNode>(Addr->getOperand(1))->getZExtValue(); if (IntNo != Intrinsic::xcore_checkevent) - return 0; + return nullptr; SDValue nextAddr = Addr->getOperand(2); SDValue CheckEventChainOut(Addr.getNode(), 1); if (!CheckEventChainOut.use_empty()) { @@ -227,7 +251,7 @@ SDNode *XCoreDAGToDAGISel::SelectBRIND(SDNode *N) { SDValue NewChain = replaceInChain(CurDAG, Chain, CheckEventChainOut, CheckEventChainIn); if (!NewChain.getNode()) - return 0; + return nullptr; Chain = NewChain; } // Enable events on the thread using setsr 1 and then disable them immediately diff --git a/lib/Target/XCore/XCoreISelLowering.cpp b/lib/Target/XCore/XCoreISelLowering.cpp index 89ad27daec133..be7ef64201936 100644 --- a/lib/Target/XCore/XCoreISelLowering.cpp +++ b/lib/Target/XCore/XCoreISelLowering.cpp @@ -11,8 +11,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "xcore-lower" - #include "XCoreISelLowering.h" #include "XCore.h" #include "XCoreMachineFunctionInfo.h" @@ -28,6 +26,7 @@ #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/IR/CallingConv.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalAlias.h" @@ -40,6 +39,8 @@ using namespace llvm; +#define DEBUG_TYPE "xcore-lower" + const char *XCoreTargetLowering:: getTargetNodeName(unsigned Opcode) const { @@ -49,6 +50,7 @@ getTargetNodeName(unsigned Opcode) const case XCoreISD::PCRelativeWrapper : return "XCoreISD::PCRelativeWrapper"; case XCoreISD::DPRelativeWrapper : return "XCoreISD::DPRelativeWrapper"; case XCoreISD::CPRelativeWrapper : return "XCoreISD::CPRelativeWrapper"; + case XCoreISD::LDWSP : return "XCoreISD::LDWSP"; case XCoreISD::STWSP : return "XCoreISD::STWSP"; case XCoreISD::RETSP : return "XCoreISD::RETSP"; case XCoreISD::LADD : return "XCoreISD::LADD"; @@ -59,15 +61,16 @@ getTargetNodeName(unsigned Opcode) const case XCoreISD::CRC8 : return "XCoreISD::CRC8"; case XCoreISD::BR_JT : return "XCoreISD::BR_JT"; case XCoreISD::BR_JT32 : return "XCoreISD::BR_JT32"; + case XCoreISD::FRAME_TO_ARGS_OFFSET : return "XCoreISD::FRAME_TO_ARGS_OFFSET"; + case XCoreISD::EH_RETURN : return "XCoreISD::EH_RETURN"; case XCoreISD::MEMBARRIER : return "XCoreISD::MEMBARRIER"; - default : return NULL; + default : return nullptr; } } -XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM) - : TargetLowering(XTM, new XCoreTargetObjectFile()), - TM(XTM), - Subtarget(*XTM.getSubtargetImpl()) { +XCoreTargetLowering::XCoreTargetLowering(const TargetMachine &TM) + : TargetLowering(TM, new XCoreTargetObjectFile()), TM(TM), + Subtarget(TM.getSubtarget<XCoreSubtarget>()) { // Set up the register classes. addRegisterClass(MVT::i32, &XCore::GRRegsRegClass); @@ -88,15 +91,12 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM) // XCore does not have the NodeTypes below. setOperationAction(ISD::BR_CC, MVT::i32, Expand); - setOperationAction(ISD::SELECT_CC, MVT::i32, Custom); + setOperationAction(ISD::SELECT_CC, MVT::i32, Expand); setOperationAction(ISD::ADDC, MVT::i32, Expand); setOperationAction(ISD::ADDE, MVT::i32, Expand); setOperationAction(ISD::SUBC, MVT::i32, Expand); setOperationAction(ISD::SUBE, MVT::i32, Expand); - // Stop the combiner recombining select and set_cc - setOperationAction(ISD::SELECT_CC, MVT::Other, Expand); - // 64bit setOperationAction(ISD::ADD, MVT::i64, Custom); setOperationAction(ISD::SUB, MVT::i64, Custom); @@ -150,11 +150,18 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM) setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand); // Exception handling + setOperationAction(ISD::EH_RETURN, MVT::Other, Custom); setExceptionPointerRegister(XCore::R0); setExceptionSelectorRegister(XCore::R1); + setOperationAction(ISD::FRAME_TO_ARGS_OFFSET, MVT::i32, Custom); // Atomic operations + // We request a fence for ATOMIC_* instructions, to reduce them to Monotonic. + // As we are always Sequential Consistent, an ATOMIC_FENCE becomes a no OP. + setInsertFencesForAtomic(true); setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); + setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Custom); + setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Custom); // TRAMPOLINE is custom lowered. setOperationAction(ISD::INIT_TRAMPOLINE, MVT::Other, Custom); @@ -170,8 +177,11 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM) // We have target-specific dag combine patterns for the following nodes: setTargetDAGCombine(ISD::STORE); setTargetDAGCombine(ISD::ADD); + setTargetDAGCombine(ISD::INTRINSIC_VOID); + setTargetDAGCombine(ISD::INTRINSIC_W_CHAIN); setMinFunctionAlignment(1); + setPrefFunctionAlignment(2); } bool XCoreTargetLowering::isZExtFree(SDValue Val, EVT VT2) const { @@ -196,13 +206,13 @@ SDValue XCoreTargetLowering:: LowerOperation(SDValue Op, SelectionDAG &DAG) const { switch (Op.getOpcode()) { + case ISD::EH_RETURN: return LowerEH_RETURN(Op, DAG); case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); case ISD::ConstantPool: return LowerConstantPool(Op, DAG); case ISD::BR_JT: return LowerBR_JT(Op, DAG); case ISD::LOAD: return LowerLOAD(Op, DAG); case ISD::STORE: return LowerSTORE(Op, DAG); - case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); case ISD::VAARG: return LowerVAARG(Op, DAG); case ISD::VASTART: return LowerVASTART(Op, DAG); case ISD::SMUL_LOHI: return LowerSMUL_LOHI(Op, DAG); @@ -211,10 +221,14 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const { case ISD::ADD: case ISD::SUB: return ExpandADDSUB(Op.getNode(), DAG); case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); + case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG); + case ISD::FRAME_TO_ARGS_OFFSET: return LowerFRAME_TO_ARGS_OFFSET(Op, DAG); case ISD::INIT_TRAMPOLINE: return LowerINIT_TRAMPOLINE(Op, DAG); case ISD::ADJUST_TRAMPOLINE: return LowerADJUST_TRAMPOLINE(Op, DAG); case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG); case ISD::ATOMIC_FENCE: return LowerATOMIC_FENCE(Op, DAG); + case ISD::ATOMIC_LOAD: return LowerATOMIC_LOAD(Op, DAG); + case ISD::ATOMIC_STORE: return LowerATOMIC_STORE(Op, DAG); default: llvm_unreachable("unimplemented operand"); } @@ -239,51 +253,64 @@ void XCoreTargetLowering::ReplaceNodeResults(SDNode *N, // Misc Lower Operation implementation //===----------------------------------------------------------------------===// -SDValue XCoreTargetLowering:: -LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const -{ - SDLoc dl(Op); - SDValue Cond = DAG.getNode(ISD::SETCC, dl, MVT::i32, Op.getOperand(2), - Op.getOperand(3), Op.getOperand(4)); - return DAG.getNode(ISD::SELECT, dl, MVT::i32, Cond, Op.getOperand(0), - Op.getOperand(1)); -} - -SDValue XCoreTargetLowering:: -getGlobalAddressWrapper(SDValue GA, const GlobalValue *GV, - SelectionDAG &DAG) const -{ +SDValue XCoreTargetLowering::getGlobalAddressWrapper(SDValue GA, + const GlobalValue *GV, + SelectionDAG &DAG) const { // FIXME there is no actual debug info here SDLoc dl(GA); - const GlobalValue *UnderlyingGV = GV; - // If GV is an alias then use the aliasee to determine the wrapper type - if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV)) - UnderlyingGV = GA->resolveAliasedGlobal(); - if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(UnderlyingGV)) { - if (GVar->isConstant()) - return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, GA); - return DAG.getNode(XCoreISD::DPRelativeWrapper, dl, MVT::i32, GA); - } - return DAG.getNode(XCoreISD::PCRelativeWrapper, dl, MVT::i32, GA); + + if (GV->getType()->getElementType()->isFunctionTy()) + return DAG.getNode(XCoreISD::PCRelativeWrapper, dl, MVT::i32, GA); + + const auto *GVar = dyn_cast<GlobalVariable>(GV); + if ((GV->hasSection() && StringRef(GV->getSection()).startswith(".cp.")) || + (GVar && GVar->isConstant() && GV->hasLocalLinkage())) + return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, GA); + + return DAG.getNode(XCoreISD::DPRelativeWrapper, dl, MVT::i32, GA); +} + +static bool IsSmallObject(const GlobalValue *GV, const XCoreTargetLowering &XTL) { + if (XTL.getTargetMachine().getCodeModel() == CodeModel::Small) + return true; + + Type *ObjType = GV->getType()->getPointerElementType(); + if (!ObjType->isSized()) + return false; + + unsigned ObjSize = XTL.getDataLayout()->getTypeAllocSize(ObjType); + return ObjSize < CodeModelLargeSize && ObjSize != 0; } SDValue XCoreTargetLowering:: LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const { - SDLoc DL(Op); const GlobalAddressSDNode *GN = cast<GlobalAddressSDNode>(Op); const GlobalValue *GV = GN->getGlobal(); + SDLoc DL(GN); int64_t Offset = GN->getOffset(); - // We can only fold positive offsets that are a multiple of the word size. - int64_t FoldedOffset = std::max(Offset & ~3, (int64_t)0); - SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, FoldedOffset); - GA = getGlobalAddressWrapper(GA, GV, DAG); - // Handle the rest of the offset. - if (Offset != FoldedOffset) { - SDValue Remaining = DAG.getConstant(Offset - FoldedOffset, MVT::i32); - GA = DAG.getNode(ISD::ADD, DL, MVT::i32, GA, Remaining); + if (IsSmallObject(GV, *this)) { + // We can only fold positive offsets that are a multiple of the word size. + int64_t FoldedOffset = std::max(Offset & ~3, (int64_t)0); + SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, FoldedOffset); + GA = getGlobalAddressWrapper(GA, GV, DAG); + // Handle the rest of the offset. + if (Offset != FoldedOffset) { + SDValue Remaining = DAG.getConstant(Offset - FoldedOffset, MVT::i32); + GA = DAG.getNode(ISD::ADD, DL, MVT::i32, GA, Remaining); + } + return GA; + } else { + // Ideally we would not fold in offset with an index <= 11. + Type *Ty = Type::getInt8PtrTy(*DAG.getContext()); + Constant *GA = ConstantExpr::getBitCast(const_cast<GlobalValue*>(GV), Ty); + Ty = Type::getInt32Ty(*DAG.getContext()); + Constant *Idx = ConstantInt::get(Ty, Offset); + Constant *GAI = ConstantExpr::getGetElementPtr(GA, Idx); + SDValue CP = DAG.getConstantPool(GAI, MVT::i32); + return DAG.getLoad(getPointerTy(), DL, DAG.getEntryNode(), CP, + MachinePointerInfo(), false, false, false, 0); } - return GA; } SDValue XCoreTargetLowering:: @@ -307,10 +334,10 @@ LowerConstantPool(SDValue Op, SelectionDAG &DAG) const SDValue Res; if (CP->isMachineConstantPoolEntry()) { Res = DAG.getTargetConstantPool(CP->getMachineCPVal(), PtrVT, - CP->getAlignment()); + CP->getAlignment(), CP->getOffset()); } else { Res = DAG.getTargetConstantPool(CP->getConstVal(), PtrVT, - CP->getAlignment()); + CP->getAlignment(), CP->getOffset()); } return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, Res); } @@ -382,13 +409,13 @@ lowerLoadWordFromAlignedBasePlusOffset(SDLoc DL, SDValue Chain, SDValue Base, Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Low.getValue(1), High.getValue(1)); SDValue Ops[] = { Result, Chain }; - return DAG.getMergeValues(Ops, 2, DL); + return DAG.getMergeValues(Ops, DL); } static bool isWordAligned(SDValue Value, SelectionDAG &DAG) { APInt KnownZero, KnownOne; - DAG.ComputeMaskedBits(Value, KnownZero, KnownOne); + DAG.computeKnownBits(Value, KnownZero, KnownOne); return KnownZero.countTrailingOnes() >= 2; } @@ -448,7 +475,7 @@ LowerLOAD(SDValue Op, SelectionDAG &DAG) const { Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Low.getValue(1), High.getValue(1)); SDValue Ops[] = { Result, Chain }; - return DAG.getMergeValues(Ops, 2, DL); + return DAG.getMergeValues(Ops, DL); } // Lower to a call to __misaligned_load(BasePtr). @@ -460,17 +487,15 @@ LowerLOAD(SDValue Op, SelectionDAG &DAG) const { Entry.Node = BasePtr; Args.push_back(Entry); - TargetLowering::CallLoweringInfo CLI(Chain, IntPtrTy, false, false, - false, false, 0, CallingConv::C, /*isTailCall=*/false, - /*doesNotRet=*/false, /*isReturnValueUsed=*/true, - DAG.getExternalSymbol("__misaligned_load", getPointerTy()), - Args, DAG, DL); - std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI); - - SDValue Ops[] = - { CallResult.first, CallResult.second }; + TargetLowering::CallLoweringInfo CLI(DAG); + CLI.setDebugLoc(DL).setChain(Chain) + .setCallee(CallingConv::C, IntPtrTy, + DAG.getExternalSymbol("__misaligned_load", getPointerTy()), + std::move(Args), 0); - return DAG.getMergeValues(Ops, 2, DL); + std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI); + SDValue Ops[] = { CallResult.first, CallResult.second }; + return DAG.getMergeValues(Ops, DL); } SDValue XCoreTargetLowering:: @@ -522,14 +547,13 @@ LowerSTORE(SDValue Op, SelectionDAG &DAG) const Entry.Node = Value; Args.push_back(Entry); - TargetLowering::CallLoweringInfo CLI(Chain, - Type::getVoidTy(*DAG.getContext()), false, false, - false, false, 0, CallingConv::C, /*isTailCall=*/false, - /*doesNotRet=*/false, /*isReturnValueUsed=*/true, - DAG.getExternalSymbol("__misaligned_store", getPointerTy()), - Args, DAG, dl); - std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI); + TargetLowering::CallLoweringInfo CLI(DAG); + CLI.setDebugLoc(dl).setChain(Chain) + .setCallee(CallingConv::C, Type::getVoidTy(*DAG.getContext()), + DAG.getExternalSymbol("__misaligned_store", getPointerTy()), + std::move(Args), 0); + std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI); return CallResult.second; } @@ -547,7 +571,7 @@ LowerSMUL_LOHI(SDValue Op, SelectionDAG &DAG) const LHS, RHS); SDValue Lo(Hi.getNode(), 1); SDValue Ops[] = { Lo, Hi }; - return DAG.getMergeValues(Ops, 2, dl); + return DAG.getMergeValues(Ops, dl); } SDValue XCoreTargetLowering:: @@ -564,7 +588,7 @@ LowerUMUL_LOHI(SDValue Op, SelectionDAG &DAG) const Zero, Zero); SDValue Lo(Hi.getNode(), 1); SDValue Ops[] = { Lo, Hi }; - return DAG.getMergeValues(Ops, 2, dl); + return DAG.getMergeValues(Ops, dl); } /// isADDADDMUL - Return whether Op is in a form that is equivalent to @@ -695,7 +719,7 @@ ExpandADDSUB(SDNode *N, SelectionDAG &DAG) const if (N->getOpcode() == ISD::ADD) { SDValue Result = TryExpandADDWithMul(N, DAG); - if (Result.getNode() != 0) + if (Result.getNode()) return Result; } @@ -767,18 +791,88 @@ LowerVASTART(SDValue Op, SelectionDAG &DAG) const SDValue XCoreTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { - SDLoc dl(Op); + // This nodes represent llvm.frameaddress on the DAG. + // It takes one operand, the index of the frame address to return. + // An index of zero corresponds to the current function's frame address. + // An index of one to the parent's frame address, and so on. // Depths > 0 not supported yet! if (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() > 0) return SDValue(); MachineFunction &MF = DAG.getMachineFunction(); const TargetRegisterInfo *RegInfo = getTargetMachine().getRegisterInfo(); - return DAG.getCopyFromReg(DAG.getEntryNode(), dl, + return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op), RegInfo->getFrameRegister(MF), MVT::i32); } SDValue XCoreTargetLowering:: +LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const { + // This nodes represent llvm.returnaddress on the DAG. + // It takes one operand, the index of the return address to return. + // An index of zero corresponds to the current function's return address. + // An index of one to the parent's return address, and so on. + // Depths > 0 not supported yet! + if (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() > 0) + return SDValue(); + + MachineFunction &MF = DAG.getMachineFunction(); + XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); + int FI = XFI->createLRSpillSlot(MF); + SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); + return DAG.getLoad(getPointerTy(), SDLoc(Op), DAG.getEntryNode(), FIN, + MachinePointerInfo::getFixedStack(FI), false, false, + false, 0); +} + +SDValue XCoreTargetLowering:: +LowerFRAME_TO_ARGS_OFFSET(SDValue Op, SelectionDAG &DAG) const { + // This node represents offset from frame pointer to first on-stack argument. + // This is needed for correct stack adjustment during unwind. + // However, we don't know the offset until after the frame has be finalised. + // This is done during the XCoreFTAOElim pass. + return DAG.getNode(XCoreISD::FRAME_TO_ARGS_OFFSET, SDLoc(Op), MVT::i32); +} + +SDValue XCoreTargetLowering:: +LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const { + // OUTCHAIN = EH_RETURN(INCHAIN, OFFSET, HANDLER) + // This node represents 'eh_return' gcc dwarf builtin, which is used to + // return from exception. The general meaning is: adjust stack by OFFSET and + // pass execution to HANDLER. + MachineFunction &MF = DAG.getMachineFunction(); + SDValue Chain = Op.getOperand(0); + SDValue Offset = Op.getOperand(1); + SDValue Handler = Op.getOperand(2); + SDLoc dl(Op); + + // Absolute SP = (FP + FrameToArgs) + Offset + const TargetRegisterInfo *RegInfo = getTargetMachine().getRegisterInfo(); + SDValue Stack = DAG.getCopyFromReg(DAG.getEntryNode(), dl, + RegInfo->getFrameRegister(MF), MVT::i32); + SDValue FrameToArgs = DAG.getNode(XCoreISD::FRAME_TO_ARGS_OFFSET, dl, + MVT::i32); + Stack = DAG.getNode(ISD::ADD, dl, MVT::i32, Stack, FrameToArgs); + Stack = DAG.getNode(ISD::ADD, dl, MVT::i32, Stack, Offset); + + // R0=ExceptionPointerRegister R1=ExceptionSelectorRegister + // which leaves 2 caller saved registers, R2 & R3 for us to use. + unsigned StackReg = XCore::R2; + unsigned HandlerReg = XCore::R3; + + SDValue OutChains[] = { + DAG.getCopyToReg(Chain, dl, StackReg, Stack), + DAG.getCopyToReg(Chain, dl, HandlerReg, Handler) + }; + + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains); + + return DAG.getNode(XCoreISD::EH_RETURN, dl, MVT::Other, Chain, + DAG.getRegister(StackReg, MVT::i32), + DAG.getRegister(HandlerReg, MVT::i32)); + +} + +SDValue XCoreTargetLowering:: LowerADJUST_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const { return Op.getOperand(0); } @@ -836,7 +930,7 @@ LowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const { MachinePointerInfo(TrmpAddr, 16), false, false, 0); - return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains, 5); + return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains); } SDValue XCoreTargetLowering:: @@ -851,7 +945,7 @@ LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const { Op.getOperand(1), Op.getOperand(2) , Op.getOperand(3)); SDValue Crc(Data.getNode(), 1); SDValue Results[] = { Crc, Data }; - return DAG.getMergeValues(Results, 2, DL); + return DAG.getMergeValues(Results, DL); } return SDValue(); } @@ -862,6 +956,67 @@ LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) const { return DAG.getNode(XCoreISD::MEMBARRIER, DL, MVT::Other, Op.getOperand(0)); } +SDValue XCoreTargetLowering:: +LowerATOMIC_LOAD(SDValue Op, SelectionDAG &DAG) const { + AtomicSDNode *N = cast<AtomicSDNode>(Op); + assert(N->getOpcode() == ISD::ATOMIC_LOAD && "Bad Atomic OP"); + assert(N->getOrdering() <= Monotonic && + "setInsertFencesForAtomic(true) and yet greater than Monotonic"); + if (N->getMemoryVT() == MVT::i32) { + if (N->getAlignment() < 4) + report_fatal_error("atomic load must be aligned"); + return DAG.getLoad(getPointerTy(), SDLoc(Op), N->getChain(), + N->getBasePtr(), N->getPointerInfo(), + N->isVolatile(), N->isNonTemporal(), + N->isInvariant(), N->getAlignment(), + N->getTBAAInfo(), N->getRanges()); + } + if (N->getMemoryVT() == MVT::i16) { + if (N->getAlignment() < 2) + report_fatal_error("atomic load must be aligned"); + return DAG.getExtLoad(ISD::EXTLOAD, SDLoc(Op), MVT::i32, N->getChain(), + N->getBasePtr(), N->getPointerInfo(), MVT::i16, + N->isVolatile(), N->isNonTemporal(), + N->getAlignment(), N->getTBAAInfo()); + } + if (N->getMemoryVT() == MVT::i8) + return DAG.getExtLoad(ISD::EXTLOAD, SDLoc(Op), MVT::i32, N->getChain(), + N->getBasePtr(), N->getPointerInfo(), MVT::i8, + N->isVolatile(), N->isNonTemporal(), + N->getAlignment(), N->getTBAAInfo()); + return SDValue(); +} + +SDValue XCoreTargetLowering:: +LowerATOMIC_STORE(SDValue Op, SelectionDAG &DAG) const { + AtomicSDNode *N = cast<AtomicSDNode>(Op); + assert(N->getOpcode() == ISD::ATOMIC_STORE && "Bad Atomic OP"); + assert(N->getOrdering() <= Monotonic && + "setInsertFencesForAtomic(true) and yet greater than Monotonic"); + if (N->getMemoryVT() == MVT::i32) { + if (N->getAlignment() < 4) + report_fatal_error("atomic store must be aligned"); + return DAG.getStore(N->getChain(), SDLoc(Op), N->getVal(), + N->getBasePtr(), N->getPointerInfo(), + N->isVolatile(), N->isNonTemporal(), + N->getAlignment(), N->getTBAAInfo()); + } + if (N->getMemoryVT() == MVT::i16) { + if (N->getAlignment() < 2) + report_fatal_error("atomic store must be aligned"); + return DAG.getTruncStore(N->getChain(), SDLoc(Op), N->getVal(), + N->getBasePtr(), N->getPointerInfo(), MVT::i16, + N->isVolatile(), N->isNonTemporal(), + N->getAlignment(), N->getTBAAInfo()); + } + if (N->getMemoryVT() == MVT::i8) + return DAG.getTruncStore(N->getChain(), SDLoc(Op), N->getVal(), + N->getBasePtr(), N->getPointerInfo(), MVT::i8, + N->isVolatile(), N->isNonTemporal(), + N->getAlignment(), N->getTBAAInfo()); + return SDValue(); +} + //===----------------------------------------------------------------------===// // Calling Convention Implementation //===----------------------------------------------------------------------===// @@ -902,6 +1057,51 @@ XCoreTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, } } +/// LowerCallResult - Lower the result values of a call into the +/// appropriate copies out of appropriate physical registers / memory locations. +static SDValue +LowerCallResult(SDValue Chain, SDValue InFlag, + const SmallVectorImpl<CCValAssign> &RVLocs, + SDLoc dl, SelectionDAG &DAG, + SmallVectorImpl<SDValue> &InVals) { + SmallVector<std::pair<int, unsigned>, 4> ResultMemLocs; + // Copy results out of physical registers. + for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { + const CCValAssign &VA = RVLocs[i]; + if (VA.isRegLoc()) { + Chain = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getValVT(), + InFlag).getValue(1); + InFlag = Chain.getValue(2); + InVals.push_back(Chain.getValue(0)); + } else { + assert(VA.isMemLoc()); + ResultMemLocs.push_back(std::make_pair(VA.getLocMemOffset(), + InVals.size())); + // Reserve space for this result. + InVals.push_back(SDValue()); + } + } + + // Copy results out of memory. + SmallVector<SDValue, 4> MemOpChains; + for (unsigned i = 0, e = ResultMemLocs.size(); i != e; ++i) { + int offset = ResultMemLocs[i].first; + unsigned index = ResultMemLocs[i].second; + SDVTList VTs = DAG.getVTList(MVT::i32, MVT::Other); + SDValue Ops[] = { Chain, DAG.getConstant(offset / 4, MVT::i32) }; + SDValue load = DAG.getNode(XCoreISD::LDWSP, dl, VTs, Ops); + InVals[index] = load; + MemOpChains.push_back(load.getValue(1)); + } + + // Transform all loads nodes into one single node because + // all load nodes are independent of each other. + if (!MemOpChains.empty()) + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains); + + return Chain; +} + /// LowerCCCCallTo - functions arguments are copied from virtual /// regs to (physical regs)/(stack frame), CALLSEQ_START and /// CALLSEQ_END are emitted. @@ -927,8 +1127,15 @@ XCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee, CCInfo.AnalyzeCallOperands(Outs, CC_XCore); + SmallVector<CCValAssign, 16> RVLocs; + // Analyze return values to determine the number of bytes of stack required. + CCState RetCCInfo(CallConv, isVarArg, DAG.getMachineFunction(), + getTargetMachine(), RVLocs, *DAG.getContext()); + RetCCInfo.AllocateStack(CCInfo.getNextStackOffset(), 4); + RetCCInfo.AnalyzeCallResult(Ins, RetCC_XCore); + // Get a count of how many bytes are to be pushed on the stack. - unsigned NumBytes = CCInfo.getNextStackOffset(); + unsigned NumBytes = RetCCInfo.getNextStackOffset(); Chain = DAG.getCALLSEQ_START(Chain,DAG.getConstant(NumBytes, getPointerTy(), true), dl); @@ -974,8 +1181,7 @@ XCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee, // Transform all store nodes into one single node because // all store nodes are independent of each other. if (!MemOpChains.empty()) - Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, - &MemOpChains[0], MemOpChains.size()); + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains); // Build a sequence of copy-to-reg nodes chained together with token // chain and flag operands which copy the outgoing args into registers. @@ -1014,7 +1220,7 @@ XCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee, if (InFlag.getNode()) Ops.push_back(InFlag); - Chain = DAG.getNode(XCoreISD::BL, dl, NodeTys, &Ops[0], Ops.size()); + Chain = DAG.getNode(XCoreISD::BL, dl, NodeTys, Ops); InFlag = Chain.getValue(1); // Create the CALLSEQ_END node. @@ -1026,35 +1232,7 @@ XCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee, // Handle result values, copying them out of physregs into vregs that we // return. - return LowerCallResult(Chain, InFlag, CallConv, isVarArg, - Ins, dl, DAG, InVals); -} - -/// LowerCallResult - Lower the result values of a call into the -/// appropriate copies out of appropriate physical registers. -SDValue -XCoreTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, - CallingConv::ID CallConv, bool isVarArg, - const SmallVectorImpl<ISD::InputArg> &Ins, - SDLoc dl, SelectionDAG &DAG, - SmallVectorImpl<SDValue> &InVals) const { - - // Assign locations to each value returned by this call. - SmallVector<CCValAssign, 16> RVLocs; - CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), - getTargetMachine(), RVLocs, *DAG.getContext()); - - CCInfo.AnalyzeCallResult(Ins, RetCC_XCore); - - // Copy all of the result registers out of their specified physreg. - for (unsigned i = 0; i != RVLocs.size(); ++i) { - Chain = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(), - RVLocs[i].getValVT(), InFlag).getValue(1); - InFlag = Chain.getValue(2); - InVals.push_back(Chain.getValue(0)); - } - - return Chain; + return LowerCallResult(Chain, InFlag, RVLocs, dl, DAG, InVals); } //===----------------------------------------------------------------------===// @@ -1102,6 +1280,7 @@ XCoreTargetLowering::LowerCCCArguments(SDValue Chain, MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); + XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); // Assign locations to all of the incoming arguments. SmallVector<CCValAssign, 16> ArgLocs; @@ -1114,6 +1293,9 @@ XCoreTargetLowering::LowerCCCArguments(SDValue Chain, unsigned LRSaveSize = StackSlotSize; + if (!isVarArg) + XFI->setReturnStackOffset(CCInfo.getNextStackOffset() + LRSaveSize); + // All getCopyFromReg ops must precede any getMemcpys to prevent the // scheduler clobbering a register before it has been copied. // The stages are: @@ -1141,7 +1323,7 @@ XCoreTargetLowering::LowerCCCArguments(SDValue Chain, errs() << "LowerFormalArguments Unhandled argument type: " << RegVT.getSimpleVT().SimpleTy << "\n"; #endif - llvm_unreachable(0); + llvm_unreachable(nullptr); } case MVT::i32: unsigned VReg = RegInfo.createVirtualRegister(&XCore::GRRegsRegClass); @@ -1178,7 +1360,7 @@ XCoreTargetLowering::LowerCCCArguments(SDValue Chain, // 1b. CopyFromReg vararg registers. if (isVarArg) { // Argument registers - static const uint16_t ArgRegs[] = { + static const MCPhysReg ArgRegs[] = { XCore::R0, XCore::R1, XCore::R2, XCore::R3 }; XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); @@ -1216,8 +1398,7 @@ XCoreTargetLowering::LowerCCCArguments(SDValue Chain, // 2. chain CopyFromReg nodes into a TokenFactor. if (!CFRegNode.empty()) - Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &CFRegNode[0], - CFRegNode.size()); + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, CFRegNode); // 3. Memcpy 'byVal' args & push final InVals. // Aggregates passed "byVal" need to be copied by the callee. @@ -1230,7 +1411,7 @@ XCoreTargetLowering::LowerCCCArguments(SDValue Chain, unsigned Size = ArgDI->Flags.getByValSize(); unsigned Align = std::max(StackSlotSize, ArgDI->Flags.getByValAlign()); // Create a new object on the stack and copy the pointee into it. - int FI = MFI->CreateStackObject(Size, Align, false, false); + int FI = MFI->CreateStackObject(Size, Align, false); SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); InVals.push_back(FIN); MemOps.push_back(DAG.getMemcpy(Chain, dl, FIN, ArgDI->SDV, @@ -1246,8 +1427,7 @@ XCoreTargetLowering::LowerCCCArguments(SDValue Chain, // 4, chain mem ops nodes into a TokenFactor. if (!MemOps.empty()) { MemOps.push_back(Chain); - Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &MemOps[0], - MemOps.size()); + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOps); } return Chain; @@ -1264,7 +1444,11 @@ CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, LLVMContext &Context) const { SmallVector<CCValAssign, 16> RVLocs; CCState CCInfo(CallConv, isVarArg, MF, getTargetMachine(), RVLocs, Context); - return CCInfo.CheckReturn(Outs, RetCC_XCore); + if (!CCInfo.CheckReturn(Outs, RetCC_XCore)) + return false; + if (CCInfo.getNextStackOffset() != 0 && isVarArg) + return false; + return true; } SDValue @@ -1274,6 +1458,10 @@ XCoreTargetLowering::LowerReturn(SDValue Chain, const SmallVectorImpl<SDValue> &OutVals, SDLoc dl, SelectionDAG &DAG) const { + XCoreFunctionInfo *XFI = + DAG.getMachineFunction().getInfo<XCoreFunctionInfo>(); + MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); + // CCValAssign - represent the assignment of // the return value to a location SmallVector<CCValAssign, 16> RVLocs; @@ -1283,6 +1471,9 @@ XCoreTargetLowering::LowerReturn(SDValue Chain, getTargetMachine(), RVLocs, *DAG.getContext()); // Analyze return values. + if (!isVarArg) + CCInfo.AllocateStack(XFI->getReturnStackOffset(), 4); + CCInfo.AnalyzeReturn(Outs, RetCC_XCore); SDValue Flag; @@ -1291,13 +1482,42 @@ XCoreTargetLowering::LowerReturn(SDValue Chain, // Return on XCore is always a "retsp 0" RetOps.push_back(DAG.getConstant(0, MVT::i32)); - // Copy the result values into the output registers. - for (unsigned i = 0; i != RVLocs.size(); ++i) { + SmallVector<SDValue, 4> MemOpChains; + // Handle return values that must be copied to memory. + for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { CCValAssign &VA = RVLocs[i]; - assert(VA.isRegLoc() && "Can only return in registers!"); + if (VA.isRegLoc()) + continue; + assert(VA.isMemLoc()); + if (isVarArg) { + report_fatal_error("Can't return value from vararg function in memory"); + } + + int Offset = VA.getLocMemOffset(); + unsigned ObjSize = VA.getLocVT().getSizeInBits() / 8; + // Create the frame index object for the memory location. + int FI = MFI->CreateFixedObject(ObjSize, Offset, false); + + // Create a SelectionDAG node corresponding to a store + // to this memory location. + SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); + MemOpChains.push_back(DAG.getStore(Chain, dl, OutVals[i], FIN, + MachinePointerInfo::getFixedStack(FI), false, false, + 0)); + } - Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), - OutVals[i], Flag); + // Transform all store nodes into one single node because + // all stores are independent of each other. + if (!MemOpChains.empty()) + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains); + + // Now handle return values copied to registers. + for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { + CCValAssign &VA = RVLocs[i]; + if (!VA.isRegLoc()) + continue; + // Copy the result values into the output registers. + Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Flag); // guarantee that all emitted copies are // stuck together, avoiding something bad @@ -1311,8 +1531,7 @@ XCoreTargetLowering::LowerReturn(SDValue Chain, if (Flag.getNode()) RetOps.push_back(Flag); - return DAG.getNode(XCoreISD::RETSP, dl, MVT::Other, - &RetOps[0], RetOps.size()); + return DAG.getNode(XCoreISD::RETSP, dl, MVT::Other, RetOps); } //===----------------------------------------------------------------------===// @@ -1350,8 +1569,7 @@ XCoreTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, // Transfer the remainder of BB and its successor edges to sinkMBB. sinkMBB->splice(sinkMBB->begin(), BB, - llvm::next(MachineBasicBlock::iterator(MI)), - BB->end()); + std::next(MachineBasicBlock::iterator(MI)), BB->end()); sinkMBB->transferSuccessorsAndUpdatePHIs(BB); // Next, add the true and fallthrough blocks as its successors. @@ -1392,6 +1610,46 @@ SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N, SDLoc dl(N); switch (N->getOpcode()) { default: break; + case ISD::INTRINSIC_VOID: + switch (cast<ConstantSDNode>(N->getOperand(1))->getZExtValue()) { + case Intrinsic::xcore_outt: + case Intrinsic::xcore_outct: + case Intrinsic::xcore_chkct: { + SDValue OutVal = N->getOperand(3); + // These instructions ignore the high bits. + if (OutVal.hasOneUse()) { + unsigned BitWidth = OutVal.getValueSizeInBits(); + APInt DemandedMask = APInt::getLowBitsSet(BitWidth, 8); + APInt KnownZero, KnownOne; + TargetLowering::TargetLoweringOpt TLO(DAG, !DCI.isBeforeLegalize(), + !DCI.isBeforeLegalizeOps()); + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + if (TLO.ShrinkDemandedConstant(OutVal, DemandedMask) || + TLI.SimplifyDemandedBits(OutVal, DemandedMask, KnownZero, KnownOne, + TLO)) + DCI.CommitTargetLoweringOpt(TLO); + } + break; + } + case Intrinsic::xcore_setpt: { + SDValue Time = N->getOperand(3); + // This instruction ignores the high bits. + if (Time.hasOneUse()) { + unsigned BitWidth = Time.getValueSizeInBits(); + APInt DemandedMask = APInt::getLowBitsSet(BitWidth, 16); + APInt KnownZero, KnownOne; + TargetLowering::TargetLoweringOpt TLO(DAG, !DCI.isBeforeLegalize(), + !DCI.isBeforeLegalizeOps()); + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + if (TLO.ShrinkDemandedConstant(Time, DemandedMask) || + TLI.SimplifyDemandedBits(Time, DemandedMask, KnownZero, KnownOne, + TLO)) + DCI.CommitTargetLoweringOpt(TLO); + } + break; + } + } + break; case XCoreISD::LADD: { SDValue N0 = N->getOperand(0); SDValue N1 = N->getOperand(1); @@ -1410,7 +1668,7 @@ SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N, SDValue Result = DAG.getNode(ISD::AND, dl, VT, N2, DAG.getConstant(1, VT)); SDValue Ops[] = { Result, Carry }; - return DAG.getMergeValues(Ops, 2, dl); + return DAG.getMergeValues(Ops, dl); } // fold (ladd x, 0, y) -> 0, add x, y iff carry is unused and y has only the @@ -1419,12 +1677,12 @@ SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N, APInt KnownZero, KnownOne; APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), VT.getSizeInBits() - 1); - DAG.ComputeMaskedBits(N2, KnownZero, KnownOne); + DAG.computeKnownBits(N2, KnownZero, KnownOne); if ((KnownZero & Mask) == Mask) { SDValue Carry = DAG.getConstant(0, VT); SDValue Result = DAG.getNode(ISD::ADD, dl, VT, N0, N2); SDValue Ops[] = { Result, Carry }; - return DAG.getMergeValues(Ops, 2, dl); + return DAG.getMergeValues(Ops, dl); } } } @@ -1442,13 +1700,13 @@ SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N, APInt KnownZero, KnownOne; APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), VT.getSizeInBits() - 1); - DAG.ComputeMaskedBits(N2, KnownZero, KnownOne); + DAG.computeKnownBits(N2, KnownZero, KnownOne); if ((KnownZero & Mask) == Mask) { SDValue Borrow = N2; SDValue Result = DAG.getNode(ISD::SUB, dl, VT, DAG.getConstant(0, VT), N2); SDValue Ops[] = { Result, Borrow }; - return DAG.getMergeValues(Ops, 2, dl); + return DAG.getMergeValues(Ops, dl); } } @@ -1458,12 +1716,12 @@ SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N, APInt KnownZero, KnownOne; APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), VT.getSizeInBits() - 1); - DAG.ComputeMaskedBits(N2, KnownZero, KnownOne); + DAG.computeKnownBits(N2, KnownZero, KnownOne); if ((KnownZero & Mask) == Mask) { SDValue Borrow = DAG.getConstant(0, VT); SDValue Result = DAG.getNode(ISD::SUB, dl, VT, N0, N2); SDValue Ops[] = { Result, Borrow }; - return DAG.getMergeValues(Ops, 2, dl); + return DAG.getMergeValues(Ops, dl); } } } @@ -1489,14 +1747,14 @@ SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N, if (N->hasNUsesOfValue(0, 0)) { SDValue Lo = DAG.getNode(ISD::ADD, dl, VT, N2, N3); SDValue Ops[] = { Lo, Lo }; - return DAG.getMergeValues(Ops, 2, dl); + return DAG.getMergeValues(Ops, dl); } // Otherwise fold to ladd(a, b, 0) SDValue Result = DAG.getNode(XCoreISD::LADD, dl, DAG.getVTList(VT, VT), N2, N3, N1); SDValue Carry(Result.getNode(), 1); SDValue Ops[] = { Carry, Result }; - return DAG.getMergeValues(Ops, 2, dl); + return DAG.getMergeValues(Ops, dl); } } break; @@ -1580,11 +1838,11 @@ SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N, return SDValue(); } -void XCoreTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op, - APInt &KnownZero, - APInt &KnownOne, - const SelectionDAG &DAG, - unsigned Depth) const { +void XCoreTargetLowering::computeKnownBitsForTargetNode(const SDValue Op, + APInt &KnownZero, + APInt &KnownOne, + const SelectionDAG &DAG, + unsigned Depth) const { KnownZero = KnownOne = APInt(KnownZero.getBitWidth(), 0); switch (Op.getOpcode()) { default: break; @@ -1596,6 +1854,34 @@ void XCoreTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op, KnownZero.getBitWidth() - 1); } break; + case ISD::INTRINSIC_W_CHAIN: + { + unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue(); + switch (IntNo) { + case Intrinsic::xcore_getts: + // High bits are known to be zero. + KnownZero = APInt::getHighBitsSet(KnownZero.getBitWidth(), + KnownZero.getBitWidth() - 16); + break; + case Intrinsic::xcore_int: + case Intrinsic::xcore_inct: + // High bits are known to be zero. + KnownZero = APInt::getHighBitsSet(KnownZero.getBitWidth(), + KnownZero.getBitWidth() - 8); + break; + case Intrinsic::xcore_testct: + // Result is either 0 or 1. + KnownZero = APInt::getHighBitsSet(KnownZero.getBitWidth(), + KnownZero.getBitWidth() - 1); + break; + case Intrinsic::xcore_testwct: + // Result is in the range 0 - 4. + KnownZero = APInt::getHighBitsSet(KnownZero.getBitWidth(), + KnownZero.getBitWidth() - 3); + break; + } + } + break; } } diff --git a/lib/Target/XCore/XCoreISelLowering.h b/lib/Target/XCore/XCoreISelLowering.h index bc08497b12ed7..62b89c348dc7a 100644 --- a/lib/Target/XCore/XCoreISelLowering.h +++ b/lib/Target/XCore/XCoreISelLowering.h @@ -42,6 +42,9 @@ namespace llvm { // cp relative address CPRelativeWrapper, + // Load word from stack + LDWSP, + // Store word to stack STWSP, @@ -72,6 +75,13 @@ namespace llvm { // Jumptable branch using long branches for each entry. BR_JT32, + // Offset from frame pointer to the first (possible) on-stack argument + FRAME_TO_ARGS_OFFSET, + + // Exception handler return. The stack is restored to the first + // followed by a jump to the second argument. + EH_RETURN, + // Memory barrier. MEMBARRIER }; @@ -84,37 +94,36 @@ namespace llvm { { public: - explicit XCoreTargetLowering(XCoreTargetMachine &TM); + explicit XCoreTargetLowering(const TargetMachine &TM); using TargetLowering::isZExtFree; - virtual bool isZExtFree(SDValue Val, EVT VT2) const; + bool isZExtFree(SDValue Val, EVT VT2) const override; - virtual unsigned getJumpTableEncoding() const; - virtual MVT getScalarShiftAmountTy(EVT LHSTy) const { return MVT::i32; } + unsigned getJumpTableEncoding() const override; + MVT getScalarShiftAmountTy(EVT LHSTy) const override { return MVT::i32; } /// LowerOperation - Provide custom lowering hooks for some operations. - virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; /// ReplaceNodeResults - Replace the results of node with an illegal result /// type with new values built out of custom code. /// - virtual void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue>&Results, - SelectionDAG &DAG) const; + void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue>&Results, + SelectionDAG &DAG) const override; /// getTargetNodeName - This method returns the name of a target specific // DAG node. - virtual const char *getTargetNodeName(unsigned Opcode) const; + const char *getTargetNodeName(unsigned Opcode) const override; - virtual MachineBasicBlock * + MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr *MI, - MachineBasicBlock *MBB) const; + MachineBasicBlock *MBB) const override; - virtual bool isLegalAddressingMode(const AddrMode &AM, - Type *Ty) const; + bool isLegalAddressingMode(const AddrMode &AM, Type *Ty) const override; private: - const XCoreTargetMachine &TM; + const TargetMachine &TM; const XCoreSubtarget &Subtarget; // Lower Operand helpers @@ -132,11 +141,6 @@ namespace llvm { const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const; - SDValue LowerCallResult(SDValue Chain, SDValue InFlag, - CallingConv::ID CallConv, bool isVarArg, - const SmallVectorImpl<ISD::InputArg> &Ins, - SDLoc dl, SelectionDAG &DAG, - SmallVectorImpl<SDValue> &InVals) const; SDValue getReturnAddressFrameIndex(SelectionDAG &DAG) const; SDValue getGlobalAddressWrapper(SDValue GA, const GlobalValue *GV, SelectionDAG &DAG) const; @@ -147,63 +151,67 @@ namespace llvm { // Lower Operand specifics SDValue LowerLOAD(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSTORE(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const; SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const; SDValue LowerBR_JT(SDValue Op, SelectionDAG &DAG) const; - SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const; SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) const; SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const; SDValue LowerUMUL_LOHI(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSMUL_LOHI(SDValue Op, SelectionDAG &DAG) const; SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerFRAME_TO_ARGS_OFFSET(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; SDValue LowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const; SDValue LowerADJUST_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const; SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const; SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerATOMIC_LOAD(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerATOMIC_STORE(SDValue Op, SelectionDAG &DAG) const; // Inline asm support std::pair<unsigned, const TargetRegisterClass*> getRegForInlineAsmConstraint(const std::string &Constraint, - MVT VT) const; + MVT VT) const override; // Expand specifics SDValue TryExpandADDWithMul(SDNode *Op, SelectionDAG &DAG) const; SDValue ExpandADDSUB(SDNode *Op, SelectionDAG &DAG) const; - virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; + SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override; - virtual void computeMaskedBitsForTargetNode(const SDValue Op, - APInt &KnownZero, - APInt &KnownOne, - const SelectionDAG &DAG, - unsigned Depth = 0) const; + void computeKnownBitsForTargetNode(const SDValue Op, + APInt &KnownZero, + APInt &KnownOne, + const SelectionDAG &DAG, + unsigned Depth = 0) const override; - virtual SDValue + SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc dl, SelectionDAG &DAG, - SmallVectorImpl<SDValue> &InVals) const; + SmallVectorImpl<SDValue> &InVals) const override; - virtual SDValue + SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, - SmallVectorImpl<SDValue> &InVals) const; + SmallVectorImpl<SDValue> &InVals) const override; - virtual SDValue + SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, - SDLoc dl, SelectionDAG &DAG) const; + SDLoc dl, SelectionDAG &DAG) const override; - virtual bool + bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg, const SmallVectorImpl<ISD::OutputArg> &ArgsFlags, - LLVMContext &Context) const; + LLVMContext &Context) const override; }; } diff --git a/lib/Target/XCore/XCoreInstrInfo.cpp b/lib/Target/XCore/XCoreInstrInfo.cpp index 33c7f31be7613..36ea9a087da5d 100644 --- a/lib/Target/XCore/XCoreInstrInfo.cpp +++ b/lib/Target/XCore/XCoreInstrInfo.cpp @@ -15,13 +15,19 @@ #include "XCore.h" #include "XCoreMachineFunctionInfo.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Function.h" #include "llvm/MC/MCContext.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TargetRegistry.h" +using namespace llvm; + #define GET_INSTRINFO_CTOR_DTOR #include "XCoreGenInstrInfo.inc" @@ -37,9 +43,6 @@ namespace XCore { } } -using namespace llvm; - - // Pin the vtable to this file. void XCoreInstrInfo::anchor() {} @@ -285,7 +288,7 @@ XCoreInstrInfo::InsertBranch(MachineBasicBlock &MBB,MachineBasicBlock *TBB, assert((Cond.size() == 2 || Cond.size() == 0) && "Unexpected number of components!"); - if (FBB == 0) { // One way branch. + if (!FBB) { // One way branch. if (Cond.empty()) { // Unconditional branch BuildMI(&MBB, DL, get(XCore::BRFU_lu6)).addMBB(TBB); @@ -370,11 +373,20 @@ void XCoreInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, const TargetRegisterInfo *TRI) const { DebugLoc DL; - if (I != MBB.end()) DL = I->getDebugLoc(); + if (I != MBB.end() && !I->isDebugValue()) + DL = I->getDebugLoc(); + MachineFunction *MF = MBB.getParent(); + const MachineFrameInfo &MFI = *MF->getFrameInfo(); + MachineMemOperand *MMO = + MF->getMachineMemOperand(MachinePointerInfo::getFixedStack(FrameIndex), + MachineMemOperand::MOStore, + MFI.getObjectSize(FrameIndex), + MFI.getObjectAlignment(FrameIndex)); BuildMI(MBB, I, DL, get(XCore::STWFI)) .addReg(SrcReg, getKillRegState(isKill)) .addFrameIndex(FrameIndex) - .addImm(0); + .addImm(0) + .addMemOperand(MMO); } void XCoreInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, @@ -384,10 +396,19 @@ void XCoreInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, const TargetRegisterInfo *TRI) const { DebugLoc DL; - if (I != MBB.end()) DL = I->getDebugLoc(); + if (I != MBB.end() && !I->isDebugValue()) + DL = I->getDebugLoc(); + MachineFunction *MF = MBB.getParent(); + const MachineFrameInfo &MFI = *MF->getFrameInfo(); + MachineMemOperand *MMO = + MF->getMachineMemOperand(MachinePointerInfo::getFixedStack(FrameIndex), + MachineMemOperand::MOLoad, + MFI.getObjectSize(FrameIndex), + MFI.getObjectAlignment(FrameIndex)); BuildMI(MBB, I, DL, get(XCore::LDWFI), DestReg) .addFrameIndex(FrameIndex) - .addImm(0); + .addImm(0) + .addMemOperand(MMO); } /// ReverseBranchCondition - Return the inverse opcode of the @@ -399,3 +420,42 @@ ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const { Cond[0].setImm(GetOppositeBranchCondition((XCore::CondCode)Cond[0].getImm())); return false; } + +static inline bool isImmU6(unsigned val) { + return val < (1 << 6); +} + +static inline bool isImmU16(unsigned val) { + return val < (1 << 16); +} + +static bool isImmMskBitp(unsigned val) { + if (!isMask_32(val)) { + return false; + } + int N = Log2_32(val) + 1; + return (N >= 1 && N <= 8) || N == 16 || N == 24 || N == 32; +} + +MachineBasicBlock::iterator XCoreInstrInfo::loadImmediate( + MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned Reg, uint64_t Value) const { + DebugLoc dl; + if (MI != MBB.end() && !MI->isDebugValue()) + dl = MI->getDebugLoc(); + if (isImmMskBitp(Value)) { + int N = Log2_32(Value) + 1; + return BuildMI(MBB, MI, dl, get(XCore::MKMSK_rus), Reg).addImm(N); + } + if (isImmU16(Value)) { + int Opcode = isImmU6(Value) ? XCore::LDC_ru6 : XCore::LDC_lru6; + return BuildMI(MBB, MI, dl, get(Opcode), Reg).addImm(Value); + } + MachineConstantPool *ConstantPool = MBB.getParent()->getConstantPool(); + const Constant *C = ConstantInt::get( + Type::getInt32Ty(MBB.getParent()->getFunction()->getContext()), Value); + unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4); + return BuildMI(MBB, MI, dl, get(XCore::LDWCP_lru6), Reg) + .addConstantPoolIndex(Idx); +} diff --git a/lib/Target/XCore/XCoreInstrInfo.h b/lib/Target/XCore/XCoreInstrInfo.h index 4429b07e41ed5..e0be96b6ad4d5 100644 --- a/lib/Target/XCore/XCoreInstrInfo.h +++ b/lib/Target/XCore/XCoreInstrInfo.h @@ -32,55 +32,61 @@ public: /// such, whenever a client has an instance of instruction info, it should /// always be able to get register info as well (through this method). /// - virtual const TargetRegisterInfo &getRegisterInfo() const { return RI; } + const TargetRegisterInfo &getRegisterInfo() const { return RI; } /// isLoadFromStackSlot - If the specified machine instruction is a direct /// load from a stack slot, return the virtual or physical register number of /// the destination along with the FrameIndex of the loaded stack slot. If /// not, return 0. This predicate must return 0 if the instruction has /// any side effects other than loading from the stack slot. - virtual unsigned isLoadFromStackSlot(const MachineInstr *MI, - int &FrameIndex) const; - + unsigned isLoadFromStackSlot(const MachineInstr *MI, + int &FrameIndex) const override; + /// isStoreToStackSlot - If the specified machine instruction is a direct /// store to a stack slot, return the virtual or physical register number of /// the source reg along with the FrameIndex of the loaded stack slot. If /// not, return 0. This predicate must return 0 if the instruction has /// any side effects other than storing to the stack slot. - virtual unsigned isStoreToStackSlot(const MachineInstr *MI, - int &FrameIndex) const; - - virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, - MachineBasicBlock *&FBB, - SmallVectorImpl<MachineOperand> &Cond, - bool AllowModify) const; - - virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, - MachineBasicBlock *FBB, - const SmallVectorImpl<MachineOperand> &Cond, - DebugLoc DL) const; - - virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const; + unsigned isStoreToStackSlot(const MachineInstr *MI, + int &FrameIndex) const override; + + bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl<MachineOperand> &Cond, + bool AllowModify) const override; + + unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const SmallVectorImpl<MachineOperand> &Cond, + DebugLoc DL) const override; + + unsigned RemoveBranch(MachineBasicBlock &MBB) const override; + + void copyPhysReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, DebugLoc DL, + unsigned DestReg, unsigned SrcReg, + bool KillSrc) const override; - virtual void copyPhysReg(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, DebugLoc DL, - unsigned DestReg, unsigned SrcReg, - bool KillSrc) const; + void storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned SrcReg, bool isKill, int FrameIndex, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const override; - virtual void storeRegToStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - unsigned SrcReg, bool isKill, int FrameIndex, - const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI) const; + void loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, int FrameIndex, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const override; - virtual void loadRegFromStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - unsigned DestReg, int FrameIndex, - const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI) const; + bool ReverseBranchCondition( + SmallVectorImpl<MachineOperand> &Cond) const override; - virtual bool ReverseBranchCondition( - SmallVectorImpl<MachineOperand> &Cond) const; + // Emit code before MBBI to load immediate value into physical register Reg. + // Returns an iterator to the new instruction. + MachineBasicBlock::iterator loadImmediate(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned Reg, uint64_t Value) const; }; } diff --git a/lib/Target/XCore/XCoreInstrInfo.td b/lib/Target/XCore/XCoreInstrInfo.td index 934a707e785b9..00cb705c8d3b9 100644 --- a/lib/Target/XCore/XCoreInstrInfo.td +++ b/lib/Target/XCore/XCoreInstrInfo.td @@ -35,6 +35,11 @@ def XCoreBranchLink : SDNode<"XCoreISD::BL",SDT_XCoreBranchLink, def XCoreRetsp : SDNode<"XCoreISD::RETSP", SDTBrind, [SDNPHasChain, SDNPOptInGlue, SDNPMayLoad, SDNPVariadic]>; +def SDT_XCoreEhRet : SDTypeProfile<0, 2, + [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>; +def XCoreEhRet : SDNode<"XCoreISD::EH_RETURN", SDT_XCoreEhRet, + [SDNPHasChain, SDNPOptInGlue]>; + def SDT_XCoreBR_JT : SDTypeProfile<0, 2, [SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; @@ -56,10 +61,17 @@ def dprelwrapper : SDNode<"XCoreISD::DPRelativeWrapper", SDT_XCoreAddress, def cprelwrapper : SDNode<"XCoreISD::CPRelativeWrapper", SDT_XCoreAddress, []>; +def frametoargsoffset : SDNode<"XCoreISD::FRAME_TO_ARGS_OFFSET", SDTIntLeaf, + []>; + def SDT_XCoreStwsp : SDTypeProfile<0, 2, [SDTCisInt<1>]>; def XCoreStwsp : SDNode<"XCoreISD::STWSP", SDT_XCoreStwsp, [SDNPHasChain, SDNPMayStore]>; +def SDT_XCoreLdwsp : SDTypeProfile<1, 1, [SDTCisInt<1>]>; +def XCoreLdwsp : SDNode<"XCoreISD::LDWSP", SDT_XCoreLdwsp, + [SDNPHasChain, SDNPMayLoad]>; + // These are target-independent nodes, but have target-specific formats. def SDT_XCoreCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32> ]>; def SDT_XCoreCallSeqEnd : SDCallSeqEnd<[ SDTCisVT<0, i32>, @@ -326,6 +338,16 @@ def ADJCALLSTACKUP : PseudoInstXCore<(outs), (ins i32imm:$amt1, i32imm:$amt2), [(callseq_end timm:$amt1, timm:$amt2)]>; } +let isReMaterializable = 1 in +def FRAME_TO_ARGS_OFFSET : PseudoInstXCore<(outs GRRegs:$dst), (ins), + "# FRAME_TO_ARGS_OFFSET $dst", + [(set GRRegs:$dst, (frametoargsoffset))]>; + +let isReturn = 1, isTerminator = 1, isBarrier = 1 in +def EH_RETURN : PseudoInstXCore<(outs), (ins GRRegs:$s, GRRegs:$handler), + "# EH_RETURN $s, $handler", + [(XCoreEhRet GRRegs:$s, GRRegs:$handler)]>; + def LDWFI : PseudoInstXCore<(outs GRRegs:$dst), (ins MEMii:$addr), "# LDWFI $dst, $addr", [(set GRRegs:$dst, (load ADDRspii:$addr))]>; @@ -563,10 +585,12 @@ def STWSP_lru6 : _FLRU6<0b010101, (outs), (ins RRegs:$a, i32imm:$b), let mayLoad=1 in { def LDWSP_ru6 : _FRU6<0b010111, (outs RRegs:$a), (ins i32imm:$b), - "ldw $a, sp[$b]", []>; + "ldw $a, sp[$b]", + [(set RRegs:$a, (XCoreLdwsp immU6:$b))]>; def LDWSP_lru6 : _FLRU6<0b010111, (outs RRegs:$a), (ins i32imm:$b), - "ldw $a, sp[$b]", []>; + "ldw $a, sp[$b]", + [(set RRegs:$a, (XCoreLdwsp immU16:$b))]>; } let neverHasSideEffects = 1 in { @@ -694,10 +718,10 @@ def BLACP_u10 : _FU10<0b111000, (outs), (ins i32imm:$a), "bla cp[$a]", []>; def BLACP_lu10 : _FLU10<0b111000, (outs), (ins i32imm:$a), "bla cp[$a]", []>; def BLRF_u10 : _FU10<0b110100, (outs), (ins pcrel_imm:$a), "bl $a", - [(XCoreBranchLink immU10:$a)]>; + []>; def BLRF_lu10 : _FLU10<0b110100, (outs), (ins pcrel_imm:$a), "bl $a", - [(XCoreBranchLink immU20:$a)]>; + [(XCoreBranchLink tglobaladdr:$a)]>; def BLRB_u10 : _FU10<0b110101, (outs), (ins pcrel_imm_neg:$a), "bl $a", []>; @@ -995,7 +1019,8 @@ def SETEV_1r : _F1R<0b001111, (outs), (ins GRRegs:$a), def DGETREG_1r : _F1R<0b001110, (outs GRRegs:$a), (ins), "dgetreg $a", []>; -def EDU_1r : _F1R<0b000000, (outs), (ins GRRegs:$a), "edu res[$a]", []>; +def EDU_1r : _F1R<0b000000, (outs), (ins GRRegs:$a), "edu res[$a]", + [(int_xcore_edu GRRegs:$a)]>; def EEU_1r : _F1R<0b000001, (outs), (ins GRRegs:$a), "eeu res[$a]", @@ -1009,7 +1034,8 @@ def WAITET_1R : _F1R<0b000010, (outs), (ins GRRegs:$a), "waitet $a", []>; def TSTART_1R : _F1R<0b000110, (outs), (ins GRRegs:$a), "start t[$a]", []>; -def CLRPT_1R : _F1R<0b100000, (outs), (ins GRRegs:$a), "clrpt res[$a]", []>; +def CLRPT_1R : _F1R<0b100000, (outs), (ins GRRegs:$a), "clrpt res[$a]", + [(int_xcore_clrpt GRRegs:$a)]>; // Zero operand short @@ -1087,7 +1113,6 @@ def WAITEU_0R : _F0R<0b0000001100, (outs), (ins), // Non-Instruction Patterns //===----------------------------------------------------------------------===// -def : Pat<(XCoreBranchLink tglobaladdr:$addr), (BLRF_lu10 tglobaladdr:$addr)>; def : Pat<(XCoreBranchLink texternalsym:$addr), (BLRF_lu10 texternalsym:$addr)>; /// sext_inreg @@ -1286,3 +1311,9 @@ def : Pat<(setgt GRRegs:$lhs, -1), def : Pat<(sra (shl GRRegs:$src, immBpwSubBitp:$imm), immBpwSubBitp:$imm), (SEXT_rus GRRegs:$src, (bpwsub_xform immBpwSubBitp:$imm))>; + +def : Pat<(load (cprelwrapper tconstpool:$b)), + (LDWCP_lru6 tconstpool:$b)>; + +def : Pat<(cprelwrapper tconstpool:$b), + (LDAWCP_lu6 tconstpool:$b)>; diff --git a/lib/Target/XCore/XCoreLowerThreadLocal.cpp b/lib/Target/XCore/XCoreLowerThreadLocal.cpp index afce753dec5c9..ac3bae577b3b4 100644 --- a/lib/Target/XCore/XCoreLowerThreadLocal.cpp +++ b/lib/Target/XCore/XCoreLowerThreadLocal.cpp @@ -17,13 +17,13 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/GlobalVariable.h" -#include "llvm/IR/Intrinsics.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/IR/Module.h" +#include "llvm/IR/NoFolder.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/NoFolder.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #define DEBUG_TYPE "xcore-lower-thread-local" @@ -48,7 +48,7 @@ namespace { bool lowerGlobal(GlobalVariable *GV); - bool runOnModule(Module &M); + bool runOnModule(Module &M) override; }; } @@ -127,10 +127,7 @@ createReplacementInstr(ConstantExpr *CE, Instruction *Instr) { static bool replaceConstantExprOp(ConstantExpr *CE, Pass *P) { do { - SmallVector<WeakVH,8> WUsers; - for (Value::use_iterator I = CE->use_begin(), E = CE->use_end(); - I != E; ++I) - WUsers.push_back(WeakVH(*I)); + SmallVector<WeakVH,8> WUsers(CE->user_begin(), CE->user_end()); std::sort(WUsers.begin(), WUsers.end()); WUsers.erase(std::unique(WUsers.begin(), WUsers.end()), WUsers.end()); while (!WUsers.empty()) @@ -154,17 +151,17 @@ static bool replaceConstantExprOp(ConstantExpr *CE, Pass *P) { return false; } } - } while (CE->hasNUsesOrMore(1)); // We need to check becasue a recursive - // sibbling may have used 'CE' when createReplacementInstr was called. + } while (CE->hasNUsesOrMore(1)); // We need to check because a recursive + // sibling may have used 'CE' when createReplacementInstr was called. CE->destroyConstant(); return true; } static bool rewriteNonInstructionUses(GlobalVariable *GV, Pass *P) { SmallVector<WeakVH,8> WUsers; - for (Value::use_iterator I = GV->use_begin(), E = GV->use_end(); I != E; ++I) - if (!isa<Instruction>(*I)) - WUsers.push_back(WeakVH(*I)); + for (User *U : GV->users()) + if (!isa<Instruction>(U)) + WUsers.push_back(WeakVH(U)); while (!WUsers.empty()) if (WeakVH WU = WUsers.pop_back_val()) { ConstantExpr *CE = dyn_cast<ConstantExpr>(WU); @@ -192,18 +189,19 @@ bool XCoreLowerThreadLocal::lowerGlobal(GlobalVariable *GV) { // Create replacement global. ArrayType *NewType = createLoweredType(GV->getType()->getElementType()); - Constant *NewInitializer = 0; + Constant *NewInitializer = nullptr; if (GV->hasInitializer()) NewInitializer = createLoweredInitializer(NewType, GV->getInitializer()); GlobalVariable *NewGV = new GlobalVariable(*M, NewType, GV->isConstant(), GV->getLinkage(), - NewInitializer, "", 0, GlobalVariable::NotThreadLocal, + NewInitializer, "", nullptr, + GlobalVariable::NotThreadLocal, GV->getType()->getAddressSpace(), GV->isExternallyInitialized()); // Update uses. - SmallVector<User *, 16> Users(GV->use_begin(), GV->use_end()); + SmallVector<User *, 16> Users(GV->user_begin(), GV->user_end()); for (unsigned I = 0, E = Users.size(); I != E; ++I) { User *U = Users[I]; Instruction *Inst = cast<Instruction>(U); diff --git a/lib/Target/XCore/XCoreMCInstLower.cpp b/lib/Target/XCore/XCoreMCInstLower.cpp index def2673fa5655..dfdadcf3fe516 100644 --- a/lib/Target/XCore/XCoreMCInstLower.cpp +++ b/lib/Target/XCore/XCoreMCInstLower.cpp @@ -17,10 +17,10 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineOperand.h" +#include "llvm/IR/Mangler.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" -#include "llvm/Target/Mangler.h" using namespace llvm; diff --git a/lib/Target/XCore/XCoreMachineFunctionInfo.cpp b/lib/Target/XCore/XCoreMachineFunctionInfo.cpp index 7ca06729120ef..9ef9752d0a5b0 100644 --- a/lib/Target/XCore/XCoreMachineFunctionInfo.cpp +++ b/lib/Target/XCore/XCoreMachineFunctionInfo.cpp @@ -8,7 +8,65 @@ //===----------------------------------------------------------------------===// #include "XCoreMachineFunctionInfo.h" +#include "XCoreInstrInfo.h" +#include "llvm/IR/Function.h" using namespace llvm; void XCoreFunctionInfo::anchor() { } + +bool XCoreFunctionInfo::isLargeFrame(const MachineFunction &MF) const { + if (CachedEStackSize == -1) { + CachedEStackSize = MF.getFrameInfo()->estimateStackSize(MF); + } + // isLargeFrame() is used when deciding if spill slots should be added to + // allow eliminateFrameIndex() to scavenge registers. + // This is only required when there is no FP and offsets are greater than + // ~256KB (~64Kwords). Thus only for code run on the emulator! + // + // The arbitrary value of 0xf000 allows frames of up to ~240KB before spill + // slots are added for the use of eliminateFrameIndex() register scavenging. + // For frames less than 240KB, it is assumed that there will be less than + // 16KB of function arguments. + return CachedEStackSize > 0xf000; +} + +int XCoreFunctionInfo::createLRSpillSlot(MachineFunction &MF) { + if (LRSpillSlotSet) { + return LRSpillSlot; + } + const TargetRegisterClass *RC = &XCore::GRRegsRegClass; + MachineFrameInfo *MFI = MF.getFrameInfo(); + if (! MF.getFunction()->isVarArg()) { + // A fixed offset of 0 allows us to save / restore LR using entsp / retsp. + LRSpillSlot = MFI->CreateFixedObject(RC->getSize(), 0, true); + } else { + LRSpillSlot = MFI->CreateStackObject(RC->getSize(), RC->getAlignment(), true); + } + LRSpillSlotSet = true; + return LRSpillSlot; +} + +int XCoreFunctionInfo::createFPSpillSlot(MachineFunction &MF) { + if (FPSpillSlotSet) { + return FPSpillSlot; + } + const TargetRegisterClass *RC = &XCore::GRRegsRegClass; + MachineFrameInfo *MFI = MF.getFrameInfo(); + FPSpillSlot = MFI->CreateStackObject(RC->getSize(), RC->getAlignment(), true); + FPSpillSlotSet = true; + return FPSpillSlot; +} + +const int* XCoreFunctionInfo::createEHSpillSlot(MachineFunction &MF) { + if (EHSpillSlotSet) { + return EHSpillSlot; + } + const TargetRegisterClass *RC = &XCore::GRRegsRegClass; + MachineFrameInfo *MFI = MF.getFrameInfo(); + EHSpillSlot[0] = MFI->CreateStackObject(RC->getSize(), RC->getAlignment(), true); + EHSpillSlot[1] = MFI->CreateStackObject(RC->getSize(), RC->getAlignment(), true); + EHSpillSlotSet = true; + return EHSpillSlot; +} + diff --git a/lib/Target/XCore/XCoreMachineFunctionInfo.h b/lib/Target/XCore/XCoreMachineFunctionInfo.h index 69d5de3e03ad4..212a5cfecc301 100644 --- a/lib/Target/XCore/XCoreMachineFunctionInfo.h +++ b/lib/Target/XCore/XCoreMachineFunctionInfo.h @@ -27,40 +27,77 @@ class Function; /// XCore target-specific information for each MachineFunction. class XCoreFunctionInfo : public MachineFunctionInfo { virtual void anchor(); - bool UsesLR; + bool LRSpillSlotSet; int LRSpillSlot; + bool FPSpillSlotSet; int FPSpillSlot; + bool EHSpillSlotSet; + int EHSpillSlot[2]; + unsigned ReturnStackOffset; + bool ReturnStackOffsetSet; int VarArgsFrameIndex; - std::vector<std::pair<MCSymbol*, CalleeSavedInfo> > SpillLabels; + mutable int CachedEStackSize; + std::vector<std::pair<MachineBasicBlock::iterator, CalleeSavedInfo>> + SpillLabels; public: XCoreFunctionInfo() : - UsesLR(false), - LRSpillSlot(0), - FPSpillSlot(0), - VarArgsFrameIndex(0) {} + LRSpillSlotSet(false), + FPSpillSlotSet(false), + EHSpillSlotSet(false), + ReturnStackOffsetSet(false), + VarArgsFrameIndex(0), + CachedEStackSize(-1) {} explicit XCoreFunctionInfo(MachineFunction &MF) : - UsesLR(false), - LRSpillSlot(0), - FPSpillSlot(0), - VarArgsFrameIndex(0) {} + LRSpillSlotSet(false), + FPSpillSlotSet(false), + EHSpillSlotSet(false), + ReturnStackOffsetSet(false), + VarArgsFrameIndex(0), + CachedEStackSize(-1) {} ~XCoreFunctionInfo() {} void setVarArgsFrameIndex(int off) { VarArgsFrameIndex = off; } int getVarArgsFrameIndex() const { return VarArgsFrameIndex; } - - void setUsesLR(bool val) { UsesLR = val; } - bool getUsesLR() const { return UsesLR; } - - void setLRSpillSlot(int off) { LRSpillSlot = off; } - int getLRSpillSlot() const { return LRSpillSlot; } - - void setFPSpillSlot(int off) { FPSpillSlot = off; } - int getFPSpillSlot() const { return FPSpillSlot; } - - std::vector<std::pair<MCSymbol*, CalleeSavedInfo> > &getSpillLabels() { + + int createLRSpillSlot(MachineFunction &MF); + bool hasLRSpillSlot() { return LRSpillSlotSet; } + int getLRSpillSlot() const { + assert(LRSpillSlotSet && "LR Spill slot not set"); + return LRSpillSlot; + } + + int createFPSpillSlot(MachineFunction &MF); + bool hasFPSpillSlot() { return FPSpillSlotSet; } + int getFPSpillSlot() const { + assert(FPSpillSlotSet && "FP Spill slot not set"); + return FPSpillSlot; + } + + const int* createEHSpillSlot(MachineFunction &MF); + bool hasEHSpillSlot() { return EHSpillSlotSet; } + const int* getEHSpillSlot() const { + assert(EHSpillSlotSet && "EH Spill slot not set"); + return EHSpillSlot; + } + + void setReturnStackOffset(unsigned value) { + assert(!ReturnStackOffsetSet && "Return stack offset set twice"); + ReturnStackOffset = value; + ReturnStackOffsetSet = true; + } + + unsigned getReturnStackOffset() const { + assert(ReturnStackOffsetSet && "Return stack offset not set"); + return ReturnStackOffset; + } + + bool isLargeFrame(const MachineFunction &MF) const; + + std::vector<std::pair<MachineBasicBlock::iterator, CalleeSavedInfo>> & + getSpillLabels() { return SpillLabels; } }; diff --git a/lib/Target/XCore/XCoreRegisterInfo.cpp b/lib/Target/XCore/XCoreRegisterInfo.cpp index dbd2f52a5b1ae..316c82c66a470 100644 --- a/lib/Target/XCore/XCoreRegisterInfo.cpp +++ b/lib/Target/XCore/XCoreRegisterInfo.cpp @@ -13,6 +13,7 @@ #include "XCoreRegisterInfo.h" #include "XCore.h" +#include "XCoreInstrInfo.h" #include "XCoreMachineFunctionInfo.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" @@ -26,17 +27,19 @@ #include "llvm/IR/Type.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetFrameLowering.h" -#include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" +using namespace llvm; + +#define DEBUG_TYPE "xcore-reg-info" + #define GET_REGINFO_TARGET_DESC #include "XCoreGenRegisterInfo.inc" -using namespace llvm; - XCoreRegisterInfo::XCoreRegisterInfo() : XCoreGenRegisterInfo(XCore::LR) { } @@ -54,18 +57,173 @@ static inline bool isImmU16(unsigned val) { return val < (1 << 16); } + +static void InsertFPImmInst(MachineBasicBlock::iterator II, + const XCoreInstrInfo &TII, + unsigned Reg, unsigned FrameReg, int Offset ) { + MachineInstr &MI = *II; + MachineBasicBlock &MBB = *MI.getParent(); + DebugLoc dl = MI.getDebugLoc(); + + switch (MI.getOpcode()) { + case XCore::LDWFI: + BuildMI(MBB, II, dl, TII.get(XCore::LDW_2rus), Reg) + .addReg(FrameReg) + .addImm(Offset) + .addMemOperand(*MI.memoperands_begin()); + break; + case XCore::STWFI: + BuildMI(MBB, II, dl, TII.get(XCore::STW_2rus)) + .addReg(Reg, getKillRegState(MI.getOperand(0).isKill())) + .addReg(FrameReg) + .addImm(Offset) + .addMemOperand(*MI.memoperands_begin()); + break; + case XCore::LDAWFI: + BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l2rus), Reg) + .addReg(FrameReg) + .addImm(Offset); + break; + default: + llvm_unreachable("Unexpected Opcode"); + } +} + +static void InsertFPConstInst(MachineBasicBlock::iterator II, + const XCoreInstrInfo &TII, + unsigned Reg, unsigned FrameReg, + int Offset, RegScavenger *RS ) { + assert(RS && "requiresRegisterScavenging failed"); + MachineInstr &MI = *II; + MachineBasicBlock &MBB = *MI.getParent(); + DebugLoc dl = MI.getDebugLoc(); + unsigned ScratchOffset = RS->scavengeRegister(&XCore::GRRegsRegClass, II, 0); + RS->setUsed(ScratchOffset); + TII.loadImmediate(MBB, II, ScratchOffset, Offset); + + switch (MI.getOpcode()) { + case XCore::LDWFI: + BuildMI(MBB, II, dl, TII.get(XCore::LDW_3r), Reg) + .addReg(FrameReg) + .addReg(ScratchOffset, RegState::Kill) + .addMemOperand(*MI.memoperands_begin()); + break; + case XCore::STWFI: + BuildMI(MBB, II, dl, TII.get(XCore::STW_l3r)) + .addReg(Reg, getKillRegState(MI.getOperand(0).isKill())) + .addReg(FrameReg) + .addReg(ScratchOffset, RegState::Kill) + .addMemOperand(*MI.memoperands_begin()); + break; + case XCore::LDAWFI: + BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l3r), Reg) + .addReg(FrameReg) + .addReg(ScratchOffset, RegState::Kill); + break; + default: + llvm_unreachable("Unexpected Opcode"); + } +} + +static void InsertSPImmInst(MachineBasicBlock::iterator II, + const XCoreInstrInfo &TII, + unsigned Reg, int Offset) { + MachineInstr &MI = *II; + MachineBasicBlock &MBB = *MI.getParent(); + DebugLoc dl = MI.getDebugLoc(); + bool isU6 = isImmU6(Offset); + + switch (MI.getOpcode()) { + int NewOpcode; + case XCore::LDWFI: + NewOpcode = (isU6) ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6; + BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg) + .addImm(Offset) + .addMemOperand(*MI.memoperands_begin()); + break; + case XCore::STWFI: + NewOpcode = (isU6) ? XCore::STWSP_ru6 : XCore::STWSP_lru6; + BuildMI(MBB, II, dl, TII.get(NewOpcode)) + .addReg(Reg, getKillRegState(MI.getOperand(0).isKill())) + .addImm(Offset) + .addMemOperand(*MI.memoperands_begin()); + break; + case XCore::LDAWFI: + NewOpcode = (isU6) ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6; + BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg) + .addImm(Offset); + break; + default: + llvm_unreachable("Unexpected Opcode"); + } +} + +static void InsertSPConstInst(MachineBasicBlock::iterator II, + const XCoreInstrInfo &TII, + unsigned Reg, int Offset, RegScavenger *RS ) { + assert(RS && "requiresRegisterScavenging failed"); + MachineInstr &MI = *II; + MachineBasicBlock &MBB = *MI.getParent(); + DebugLoc dl = MI.getDebugLoc(); + unsigned OpCode = MI.getOpcode(); + + unsigned ScratchBase; + if (OpCode==XCore::STWFI) { + ScratchBase = RS->scavengeRegister(&XCore::GRRegsRegClass, II, 0); + RS->setUsed(ScratchBase); + } else + ScratchBase = Reg; + BuildMI(MBB, II, dl, TII.get(XCore::LDAWSP_ru6), ScratchBase).addImm(0); + unsigned ScratchOffset = RS->scavengeRegister(&XCore::GRRegsRegClass, II, 0); + RS->setUsed(ScratchOffset); + TII.loadImmediate(MBB, II, ScratchOffset, Offset); + + switch (OpCode) { + case XCore::LDWFI: + BuildMI(MBB, II, dl, TII.get(XCore::LDW_3r), Reg) + .addReg(ScratchBase, RegState::Kill) + .addReg(ScratchOffset, RegState::Kill) + .addMemOperand(*MI.memoperands_begin()); + break; + case XCore::STWFI: + BuildMI(MBB, II, dl, TII.get(XCore::STW_l3r)) + .addReg(Reg, getKillRegState(MI.getOperand(0).isKill())) + .addReg(ScratchBase, RegState::Kill) + .addReg(ScratchOffset, RegState::Kill) + .addMemOperand(*MI.memoperands_begin()); + break; + case XCore::LDAWFI: + BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l3r), Reg) + .addReg(ScratchBase, RegState::Kill) + .addReg(ScratchOffset, RegState::Kill); + break; + default: + llvm_unreachable("Unexpected Opcode"); + } +} + bool XCoreRegisterInfo::needsFrameMoves(const MachineFunction &MF) { return MF.getMMI().hasDebugInfo() || MF.getFunction()->needsUnwindTableEntry(); } -const uint16_t* XCoreRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) +const MCPhysReg* XCoreRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { - static const uint16_t CalleeSavedRegs[] = { + // The callee saved registers LR & FP are explicitly handled during + // emitPrologue & emitEpilogue and related functions. + static const MCPhysReg CalleeSavedRegs[] = { XCore::R4, XCore::R5, XCore::R6, XCore::R7, - XCore::R8, XCore::R9, XCore::R10, XCore::LR, + XCore::R8, XCore::R9, XCore::R10, 0 }; + static const MCPhysReg CalleeSavedRegsFP[] = { + XCore::R4, XCore::R5, XCore::R6, XCore::R7, + XCore::R8, XCore::R9, + 0 + }; + const TargetFrameLowering *TFI = MF->getTarget().getFrameLowering(); + if (TFI->hasFP(*MF)) + return CalleeSavedRegsFP; return CalleeSavedRegs; } @@ -85,15 +243,12 @@ BitVector XCoreRegisterInfo::getReservedRegs(const MachineFunction &MF) const { bool XCoreRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const { - const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); - - // TODO can we estimate stack size? - return TFI->hasFP(MF); + return true; } bool XCoreRegisterInfo::trackLivenessAfterRegAlloc(const MachineFunction &MF) const { - return requiresRegisterScavenging(MF); + return true; } bool @@ -107,12 +262,13 @@ XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, RegScavenger *RS) const { assert(SPAdj == 0 && "Unexpected"); MachineInstr &MI = *II; - DebugLoc dl = MI.getDebugLoc(); MachineOperand &FrameOp = MI.getOperand(FIOperandNum); int FrameIndex = FrameOp.getIndex(); MachineFunction &MF = *MI.getParent()->getParent(); - const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); + const XCoreInstrInfo &TII = + *static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo()); + const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex); int StackSize = MF.getFrameInfo()->getStackSize(); @@ -143,116 +299,28 @@ XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, MI.getOperand(FIOperandNum + 1).ChangeToImmediate(0); assert(Offset%4 == 0 && "Misaligned stack offset"); - DEBUG(errs() << "Offset : " << Offset << "\n" << "<--------->\n"); - Offset/=4; - bool FP = TFI->hasFP(MF); - unsigned Reg = MI.getOperand(0).getReg(); - bool isKill = MI.getOpcode() == XCore::STWFI && MI.getOperand(0).isKill(); - assert(XCore::GRRegsRegClass.contains(Reg) && "Unexpected register operand"); - - MachineBasicBlock &MBB = *MI.getParent(); - - if (FP) { - bool isUs = isImmUs(Offset); - - if (!isUs) { - if (!RS) - report_fatal_error("eliminateFrameIndex Frame size too big: " + - Twine(Offset)); - unsigned ScratchReg = RS->scavengeRegister(&XCore::GRRegsRegClass, II, - SPAdj); - loadConstant(MBB, II, ScratchReg, Offset, dl); - switch (MI.getOpcode()) { - case XCore::LDWFI: - BuildMI(MBB, II, dl, TII.get(XCore::LDW_3r), Reg) - .addReg(FrameReg) - .addReg(ScratchReg, RegState::Kill); - break; - case XCore::STWFI: - BuildMI(MBB, II, dl, TII.get(XCore::STW_l3r)) - .addReg(Reg, getKillRegState(isKill)) - .addReg(FrameReg) - .addReg(ScratchReg, RegState::Kill); - break; - case XCore::LDAWFI: - BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l3r), Reg) - .addReg(FrameReg) - .addReg(ScratchReg, RegState::Kill); - break; - default: - llvm_unreachable("Unexpected Opcode"); - } - } else { - switch (MI.getOpcode()) { - case XCore::LDWFI: - BuildMI(MBB, II, dl, TII.get(XCore::LDW_2rus), Reg) - .addReg(FrameReg) - .addImm(Offset); - break; - case XCore::STWFI: - BuildMI(MBB, II, dl, TII.get(XCore::STW_2rus)) - .addReg(Reg, getKillRegState(isKill)) - .addReg(FrameReg) - .addImm(Offset); - break; - case XCore::LDAWFI: - BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l2rus), Reg) - .addReg(FrameReg) - .addImm(Offset); - break; - default: - llvm_unreachable("Unexpected Opcode"); - } - } - } else { - bool isU6 = isImmU6(Offset); - if (!isU6 && !isImmU16(Offset)) - report_fatal_error("eliminateFrameIndex Frame size too big: " + - Twine(Offset)); - switch (MI.getOpcode()) { - int NewOpcode; - case XCore::LDWFI: - NewOpcode = (isU6) ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6; - BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg) - .addImm(Offset); - break; - case XCore::STWFI: - NewOpcode = (isU6) ? XCore::STWSP_ru6 : XCore::STWSP_lru6; - BuildMI(MBB, II, dl, TII.get(NewOpcode)) - .addReg(Reg, getKillRegState(isKill)) - .addImm(Offset); - break; - case XCore::LDAWFI: - NewOpcode = (isU6) ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6; - BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg) - .addImm(Offset); - break; - default: - llvm_unreachable("Unexpected Opcode"); - } + if (TFI->hasFP(MF)) { + if (isImmUs(Offset)) + InsertFPImmInst(II, TII, Reg, FrameReg, Offset); + else + InsertFPConstInst(II, TII, Reg, FrameReg, Offset, RS); + } else { + if (isImmU16(Offset)) + InsertSPImmInst(II, TII, Reg, Offset); + else + InsertSPConstInst(II, TII, Reg, Offset, RS); } // Erase old instruction. + MachineBasicBlock &MBB = *MI.getParent(); MBB.erase(II); } -void XCoreRegisterInfo:: -loadConstant(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, - unsigned DstReg, int64_t Value, DebugLoc dl) const { - // TODO use mkmsk if possible. - if (!isImmU16(Value)) { - // TODO use constant pool. - report_fatal_error("loadConstant value too big " + Twine(Value)); - } - int Opcode = isImmU6(Value) ? XCore::LDC_ru6 : XCore::LDC_lru6; - const TargetInstrInfo &TII = *MBB.getParent()->getTarget().getInstrInfo(); - BuildMI(MBB, I, dl, TII.get(Opcode), DstReg).addImm(Value); -} unsigned XCoreRegisterInfo::getFrameRegister(const MachineFunction &MF) const { const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); diff --git a/lib/Target/XCore/XCoreRegisterInfo.h b/lib/Target/XCore/XCoreRegisterInfo.h index 2370c6280f2ed..aa617a0106d0a 100644 --- a/lib/Target/XCore/XCoreRegisterInfo.h +++ b/lib/Target/XCore/XCoreRegisterInfo.h @@ -24,40 +24,28 @@ namespace llvm { class TargetInstrInfo; struct XCoreRegisterInfo : public XCoreGenRegisterInfo { -private: - void loadConstant(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - unsigned DstReg, int64_t Value, DebugLoc dl) const; - - void storeToStack(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - unsigned SrcReg, int Offset, DebugLoc dl) const; - - void loadFromStack(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - unsigned DstReg, int Offset, DebugLoc dl) const; - public: XCoreRegisterInfo(); /// Code Generation virtual methods... - const uint16_t *getCalleeSavedRegs(const MachineFunction *MF = 0) const; + const MCPhysReg * + getCalleeSavedRegs(const MachineFunction *MF =nullptr) const override; - BitVector getReservedRegs(const MachineFunction &MF) const; + BitVector getReservedRegs(const MachineFunction &MF) const override; - bool requiresRegisterScavenging(const MachineFunction &MF) const; + bool requiresRegisterScavenging(const MachineFunction &MF) const override; - bool trackLivenessAfterRegAlloc(const MachineFunction &MF) const; + bool trackLivenessAfterRegAlloc(const MachineFunction &MF) const override; - bool useFPForScavengingIndex(const MachineFunction &MF) const; + bool useFPForScavengingIndex(const MachineFunction &MF) const override; void eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum, - RegScavenger *RS = NULL) const; + RegScavenger *RS = nullptr) const override; // Debug information queries. - unsigned getFrameRegister(const MachineFunction &MF) const; + unsigned getFrameRegister(const MachineFunction &MF) const override; //! Return whether to emit frame moves static bool needsFrameMoves(const MachineFunction &MF); diff --git a/lib/Target/XCore/XCoreSelectionDAGInfo.cpp b/lib/Target/XCore/XCoreSelectionDAGInfo.cpp index 44aeb6057ccb6..91b33fd6559cf 100644 --- a/lib/Target/XCore/XCoreSelectionDAGInfo.cpp +++ b/lib/Target/XCore/XCoreSelectionDAGInfo.cpp @@ -11,13 +11,48 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "xcore-selectiondag-info" #include "XCoreTargetMachine.h" using namespace llvm; -XCoreSelectionDAGInfo::XCoreSelectionDAGInfo(const XCoreTargetMachine &TM) - : TargetSelectionDAGInfo(TM) { -} +#define DEBUG_TYPE "xcore-selectiondag-info" + +XCoreSelectionDAGInfo::XCoreSelectionDAGInfo(const DataLayout &DL) + : TargetSelectionDAGInfo(&DL) {} XCoreSelectionDAGInfo::~XCoreSelectionDAGInfo() { } + +SDValue XCoreSelectionDAGInfo:: +EmitTargetCodeForMemcpy(SelectionDAG &DAG, SDLoc dl, SDValue Chain, + SDValue Dst, SDValue Src, SDValue Size, unsigned Align, + bool isVolatile, bool AlwaysInline, + MachinePointerInfo DstPtrInfo, + MachinePointerInfo SrcPtrInfo) const +{ + unsigned SizeBitWidth = Size.getValueType().getSizeInBits(); + // Call __memcpy_4 if the src, dst and size are all 4 byte aligned. + if (!AlwaysInline && (Align & 3) == 0 && + DAG.MaskedValueIsZero(Size, APInt(SizeBitWidth, 3))) { + const TargetLowering &TLI = *DAG.getTarget().getTargetLowering(); + TargetLowering::ArgListTy Args; + TargetLowering::ArgListEntry Entry; + Entry.Ty = TLI.getDataLayout()->getIntPtrType(*DAG.getContext()); + Entry.Node = Dst; Args.push_back(Entry); + Entry.Node = Src; Args.push_back(Entry); + Entry.Node = Size; Args.push_back(Entry); + + TargetLowering::CallLoweringInfo CLI(DAG); + CLI.setDebugLoc(dl).setChain(Chain) + .setCallee(TLI.getLibcallCallingConv(RTLIB::MEMCPY), + Type::getVoidTy(*DAG.getContext()), + DAG.getExternalSymbol("__memcpy_4", TLI.getPointerTy()), + std::move(Args), 0) + .setDiscardResult(); + + std::pair<SDValue,SDValue> CallResult = TLI.LowerCallTo(CLI); + return CallResult.second; + } + + // Otherwise have the target-independent code call memcpy. + return SDValue(); +} diff --git a/lib/Target/XCore/XCoreSelectionDAGInfo.h b/lib/Target/XCore/XCoreSelectionDAGInfo.h index 0386968638bd5..0079de1798b2d 100644 --- a/lib/Target/XCore/XCoreSelectionDAGInfo.h +++ b/lib/Target/XCore/XCoreSelectionDAGInfo.h @@ -22,8 +22,17 @@ class XCoreTargetMachine; class XCoreSelectionDAGInfo : public TargetSelectionDAGInfo { public: - explicit XCoreSelectionDAGInfo(const XCoreTargetMachine &TM); + explicit XCoreSelectionDAGInfo(const DataLayout &DL); ~XCoreSelectionDAGInfo(); + + SDValue + EmitTargetCodeForMemcpy(SelectionDAG &DAG, SDLoc dl, + SDValue Chain, + SDValue Op1, SDValue Op2, + SDValue Op3, unsigned Align, bool isVolatile, + bool AlwaysInline, + MachinePointerInfo DstPtrInfo, + MachinePointerInfo SrcPtrInfo) const override; }; } diff --git a/lib/Target/XCore/XCoreSubtarget.cpp b/lib/Target/XCore/XCoreSubtarget.cpp index 8cfb77089f319..7227411ba560c 100644 --- a/lib/Target/XCore/XCoreSubtarget.cpp +++ b/lib/Target/XCore/XCoreSubtarget.cpp @@ -15,16 +15,18 @@ #include "XCore.h" #include "llvm/Support/TargetRegistry.h" +using namespace llvm; + +#define DEBUG_TYPE "xcore-subtarget" + #define GET_SUBTARGETINFO_TARGET_DESC #define GET_SUBTARGETINFO_CTOR #include "XCoreGenSubtargetInfo.inc" -using namespace llvm; - void XCoreSubtarget::anchor() { } -XCoreSubtarget::XCoreSubtarget(const std::string &TT, - const std::string &CPU, const std::string &FS) - : XCoreGenSubtargetInfo(TT, CPU, FS) -{ -} +XCoreSubtarget::XCoreSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS, const TargetMachine &TM) + : XCoreGenSubtargetInfo(TT, CPU, FS), + DL("e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:32-f64:32-a:0:32-n32"), + InstrInfo(), FrameLowering(*this), TLInfo(TM), TSInfo(DL) {} diff --git a/lib/Target/XCore/XCoreSubtarget.h b/lib/Target/XCore/XCoreSubtarget.h index 5ac4dbc4bc07d..1e9810bb89ef5 100644 --- a/lib/Target/XCore/XCoreSubtarget.h +++ b/lib/Target/XCore/XCoreSubtarget.h @@ -14,6 +14,11 @@ #ifndef XCORESUBTARGET_H #define XCORESUBTARGET_H +#include "XCoreFrameLowering.h" +#include "XCoreISelLowering.h" +#include "XCoreInstrInfo.h" +#include "XCoreSelectionDAGInfo.h" +#include "llvm/IR/DataLayout.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetSubtargetInfo.h" #include <string> @@ -26,17 +31,31 @@ class StringRef; class XCoreSubtarget : public XCoreGenSubtargetInfo { virtual void anchor(); + const DataLayout DL; // Calculates type size & alignment + XCoreInstrInfo InstrInfo; + XCoreFrameLowering FrameLowering; + XCoreTargetLowering TLInfo; + XCoreSelectionDAGInfo TSInfo; public: /// This constructor initializes the data members to match that /// of the specified triple. /// XCoreSubtarget(const std::string &TT, const std::string &CPU, - const std::string &FS); + const std::string &FS, const TargetMachine &TM); /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. void ParseSubtargetFeatures(StringRef CPU, StringRef FS); + + const XCoreInstrInfo *getInstrInfo() const { return &InstrInfo; } + const XCoreFrameLowering *getFrameLowering() const { return &FrameLowering; } + const XCoreTargetLowering *getTargetLowering() const { return &TLInfo; } + const XCoreSelectionDAGInfo *getSelectionDAGInfo() const { return &TSInfo; } + const TargetRegisterInfo *getRegisterInfo() const { + return &InstrInfo.getRegisterInfo(); + } + const DataLayout *getDataLayout() const { return &DL; } }; } // End llvm namespace diff --git a/lib/Target/XCore/XCoreTargetMachine.cpp b/lib/Target/XCore/XCoreTargetMachine.cpp index 9ae0b860dff91..8d8bb3800ea56 100644 --- a/lib/Target/XCore/XCoreTargetMachine.cpp +++ b/lib/Target/XCore/XCoreTargetMachine.cpp @@ -25,14 +25,8 @@ XCoreTargetMachine::XCoreTargetMachine(const Target &T, StringRef TT, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL) - : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL), - Subtarget(TT, CPU, FS), - DL("e-p:32:32:32-a0:0:32-f32:32:32-f64:32:32-i1:8:32-i8:8:32-" - "i16:16:32-i32:32:32-i64:32:32-n32"), - InstrInfo(), - FrameLowering(Subtarget), - TLInfo(*this), - TSInfo(*this) { + : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL), + Subtarget(TT, CPU, FS, *this) { initAsmInfo(); } @@ -47,8 +41,9 @@ public: return getTM<XCoreTargetMachine>(); } - virtual bool addPreISel(); - virtual bool addInstSelector(); + bool addPreISel() override; + bool addInstSelector() override; + bool addPreEmitPass() override; }; } // namespace @@ -66,6 +61,11 @@ bool XCorePassConfig::addInstSelector() { return false; } +bool XCorePassConfig::addPreEmitPass() { + addPass(createXCoreFrameToArgsOffsetEliminationPass()); + return false; +} + // Force static initialization. extern "C" void LLVMInitializeXCoreTarget() { RegisterTargetMachine<XCoreTargetMachine> X(TheXCoreTarget); diff --git a/lib/Target/XCore/XCoreTargetMachine.h b/lib/Target/XCore/XCoreTargetMachine.h index a19a67727f2c5..14c43bf151f41 100644 --- a/lib/Target/XCore/XCoreTargetMachine.h +++ b/lib/Target/XCore/XCoreTargetMachine.h @@ -14,51 +14,43 @@ #ifndef XCORETARGETMACHINE_H #define XCORETARGETMACHINE_H -#include "XCoreFrameLowering.h" -#include "XCoreISelLowering.h" -#include "XCoreInstrInfo.h" -#include "XCoreSelectionDAGInfo.h" #include "XCoreSubtarget.h" -#include "llvm/IR/DataLayout.h" #include "llvm/Target/TargetMachine.h" namespace llvm { class XCoreTargetMachine : public LLVMTargetMachine { XCoreSubtarget Subtarget; - const DataLayout DL; // Calculates type size & alignment - XCoreInstrInfo InstrInfo; - XCoreFrameLowering FrameLowering; - XCoreTargetLowering TLInfo; - XCoreSelectionDAGInfo TSInfo; public: XCoreTargetMachine(const Target &T, StringRef TT, StringRef CPU, StringRef FS, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL); - virtual const XCoreInstrInfo *getInstrInfo() const { return &InstrInfo; } - virtual const XCoreFrameLowering *getFrameLowering() const { - return &FrameLowering; + const XCoreInstrInfo *getInstrInfo() const override { + return getSubtargetImpl()->getInstrInfo(); } - virtual const XCoreSubtarget *getSubtargetImpl() const { return &Subtarget; } - virtual const XCoreTargetLowering *getTargetLowering() const { - return &TLInfo; + const XCoreFrameLowering *getFrameLowering() const override { + return getSubtargetImpl()->getFrameLowering(); } - - virtual const XCoreSelectionDAGInfo* getSelectionDAGInfo() const { - return &TSInfo; + const XCoreSubtarget *getSubtargetImpl() const override { return &Subtarget; } + const XCoreTargetLowering *getTargetLowering() const override { + return getSubtargetImpl()->getTargetLowering(); } - - virtual const TargetRegisterInfo *getRegisterInfo() const { - return &InstrInfo.getRegisterInfo(); + const XCoreSelectionDAGInfo* getSelectionDAGInfo() const override { + return getSubtargetImpl()->getSelectionDAGInfo(); + } + const TargetRegisterInfo *getRegisterInfo() const override { + return getSubtargetImpl()->getRegisterInfo(); + } + const DataLayout *getDataLayout() const override { + return getSubtargetImpl()->getDataLayout(); } - virtual const DataLayout *getDataLayout() const { return &DL; } // Pass Pipeline Configuration - virtual TargetPassConfig *createPassConfig(PassManagerBase &PM); + TargetPassConfig *createPassConfig(PassManagerBase &PM) override; - virtual void addAnalysisPasses(PassManagerBase &PM); + void addAnalysisPasses(PassManagerBase &PM) override; }; } // end namespace llvm diff --git a/lib/Target/XCore/XCoreTargetObjectFile.cpp b/lib/Target/XCore/XCoreTargetObjectFile.cpp index 88e3bfd7b81c8..cfd3302481e73 100644 --- a/lib/Target/XCore/XCoreTargetObjectFile.cpp +++ b/lib/Target/XCore/XCoreTargetObjectFile.cpp @@ -9,27 +9,58 @@ #include "XCoreTargetObjectFile.h" #include "XCoreSubtarget.h" +#include "llvm/IR/DataLayout.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/Support/ELF.h" #include "llvm/Target/TargetMachine.h" + using namespace llvm; void XCoreTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM){ TargetLoweringObjectFileELF::Initialize(Ctx, TM); + BSSSection = + Ctx.getELFSection(".dp.bss", ELF::SHT_NOBITS, + ELF::SHF_ALLOC | ELF::SHF_WRITE | + ELF::XCORE_SHF_DP_SECTION, + SectionKind::getBSS()); + BSSSectionLarge = + Ctx.getELFSection(".dp.bss.large", ELF::SHT_NOBITS, + ELF::SHF_ALLOC | ELF::SHF_WRITE | + ELF::XCORE_SHF_DP_SECTION, + SectionKind::getBSS()); DataSection = - Ctx.getELFSection(".dp.data", ELF::SHT_PROGBITS, + Ctx.getELFSection(".dp.data", ELF::SHT_PROGBITS, ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::XCORE_SHF_DP_SECTION, SectionKind::getDataRel()); - BSSSection = - Ctx.getELFSection(".dp.bss", ELF::SHT_NOBITS, + DataSectionLarge = + Ctx.getELFSection(".dp.data.large", ELF::SHT_PROGBITS, ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::XCORE_SHF_DP_SECTION, - SectionKind::getBSS()); - + SectionKind::getDataRel()); + DataRelROSection = + Ctx.getELFSection(".dp.rodata", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | ELF::SHF_WRITE | + ELF::XCORE_SHF_DP_SECTION, + SectionKind::getReadOnlyWithRel()); + DataRelROSectionLarge = + Ctx.getELFSection(".dp.rodata.large", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | ELF::SHF_WRITE | + ELF::XCORE_SHF_DP_SECTION, + SectionKind::getReadOnlyWithRel()); + ReadOnlySection = + Ctx.getELFSection(".cp.rodata", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | + ELF::XCORE_SHF_CP_SECTION, + SectionKind::getReadOnlyWithRel()); + ReadOnlySectionLarge = + Ctx.getELFSection(".cp.rodata.large", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | + ELF::XCORE_SHF_CP_SECTION, + SectionKind::getReadOnlyWithRel()); MergeableConst4Section = Ctx.getELFSection(".cp.rodata.cst4", ELF::SHT_PROGBITS, ELF::SHF_ALLOC | ELF::SHF_MERGE | @@ -45,16 +76,104 @@ void XCoreTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM){ ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::XCORE_SHF_CP_SECTION, SectionKind::getMergeableConst16()); - - // TLS globals are lowered in the backend to arrays indexed by the current - // thread id. After lowering they require no special handling by the linker - // and can be placed in the standard data / bss sections. - TLSDataSection = DataSection; - TLSBSSSection = BSSSection; - - ReadOnlySection = - Ctx.getELFSection(".cp.rodata", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC | + CStringSection = + Ctx.getELFSection(".cp.rodata.string", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS | ELF::XCORE_SHF_CP_SECTION, SectionKind::getReadOnlyWithRel()); + // TextSection - see MObjectFileInfo.cpp + // StaticCtorSection - see MObjectFileInfo.cpp + // StaticDtorSection - see MObjectFileInfo.cpp + } + +static unsigned getXCoreSectionType(SectionKind K) { + if (K.isBSS()) + return ELF::SHT_NOBITS; + return ELF::SHT_PROGBITS; +} + +static unsigned getXCoreSectionFlags(SectionKind K, bool IsCPRel) { + unsigned Flags = 0; + + if (!K.isMetadata()) + Flags |= ELF::SHF_ALLOC; + + if (K.isText()) + Flags |= ELF::SHF_EXECINSTR; + else if (IsCPRel) + Flags |= ELF::XCORE_SHF_CP_SECTION; + else + Flags |= ELF::XCORE_SHF_DP_SECTION; + + if (K.isWriteable()) + Flags |= ELF::SHF_WRITE; + + if (K.isMergeableCString() || K.isMergeableConst4() || + K.isMergeableConst8() || K.isMergeableConst16()) + Flags |= ELF::SHF_MERGE; + + if (K.isMergeableCString()) + Flags |= ELF::SHF_STRINGS; + + return Flags; +} + +const MCSection * +XCoreTargetObjectFile::getExplicitSectionGlobal(const GlobalValue *GV, + SectionKind Kind, Mangler &Mang, + const TargetMachine &TM) const { + StringRef SectionName = GV->getSection(); + // Infer section flags from the section name if we can. + bool IsCPRel = SectionName.startswith(".cp."); + if (IsCPRel && !Kind.isReadOnly()) + report_fatal_error("Using .cp. section for writeable object."); + return getContext().getELFSection(SectionName, getXCoreSectionType(Kind), + getXCoreSectionFlags(Kind, IsCPRel), Kind); +} + +const MCSection *XCoreTargetObjectFile:: +SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler &Mang, + const TargetMachine &TM) const{ + + bool UseCPRel = GV->isLocalLinkage(GV->getLinkage()); + + if (Kind.isText()) return TextSection; + if (UseCPRel) { + if (Kind.isMergeable1ByteCString()) return CStringSection; + if (Kind.isMergeableConst4()) return MergeableConst4Section; + if (Kind.isMergeableConst8()) return MergeableConst8Section; + if (Kind.isMergeableConst16()) return MergeableConst16Section; + } + Type *ObjType = GV->getType()->getPointerElementType(); + if (TM.getCodeModel() == CodeModel::Small || + !ObjType->isSized() || + TM.getDataLayout()->getTypeAllocSize(ObjType) < CodeModelLargeSize) { + if (Kind.isReadOnly()) return UseCPRel? ReadOnlySection + : DataRelROSection; + if (Kind.isBSS() || Kind.isCommon())return BSSSection; + if (Kind.isDataRel()) return DataSection; + if (Kind.isReadOnlyWithRel()) return DataRelROSection; + } else { + if (Kind.isReadOnly()) return UseCPRel? ReadOnlySectionLarge + : DataRelROSectionLarge; + if (Kind.isBSS() || Kind.isCommon())return BSSSectionLarge; + if (Kind.isDataRel()) return DataSectionLarge; + if (Kind.isReadOnlyWithRel()) return DataRelROSectionLarge; + } + + assert((Kind.isThreadLocal() || Kind.isCommon()) && "Unknown section kind"); + report_fatal_error("Target does not support TLS or Common sections"); +} + +const MCSection * +XCoreTargetObjectFile::getSectionForConstant(SectionKind Kind, + const Constant *C) const { + if (Kind.isMergeableConst4()) return MergeableConst4Section; + if (Kind.isMergeableConst8()) return MergeableConst8Section; + if (Kind.isMergeableConst16()) return MergeableConst16Section; + assert((Kind.isReadOnly() || Kind.isReadOnlyWithRel()) && + "Unknown section kind"); + // We assume the size of the object is never greater than CodeModelLargeSize. + // To handle CodeModelLargeSize changes to AsmPrinter would be required. + return ReadOnlySection; } diff --git a/lib/Target/XCore/XCoreTargetObjectFile.h b/lib/Target/XCore/XCoreTargetObjectFile.h index 27875e783b330..d389e55ae3990 100644 --- a/lib/Target/XCore/XCoreTargetObjectFile.h +++ b/lib/Target/XCore/XCoreTargetObjectFile.h @@ -14,11 +14,28 @@ namespace llvm { +static const unsigned CodeModelLargeSize = 256; + class XCoreTargetObjectFile : public TargetLoweringObjectFileELF { + const MCSection *BSSSectionLarge; + const MCSection *DataSectionLarge; + const MCSection *ReadOnlySectionLarge; + const MCSection *DataRelROSectionLarge; public: - void Initialize(MCContext &Ctx, const TargetMachine &TM); + void Initialize(MCContext &Ctx, const TargetMachine &TM) override; + + const MCSection * + getExplicitSectionGlobal(const GlobalValue *GV, + SectionKind Kind, Mangler &Mang, + const TargetMachine &TM) const override; + + const MCSection * + SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler &Mang, + const TargetMachine &TM) const override; - // TODO: Classify globals as xcore wishes. + const MCSection *getSectionForConstant(SectionKind Kind, + const Constant *C) const override; }; } // end namespace llvm diff --git a/lib/Target/XCore/XCoreTargetStreamer.h b/lib/Target/XCore/XCoreTargetStreamer.h new file mode 100644 index 0000000000000..0a394da98a0ef --- /dev/null +++ b/lib/Target/XCore/XCoreTargetStreamer.h @@ -0,0 +1,27 @@ +//===-- XCoreTargetStreamer.h - XCore Target Streamer ----------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef XCORETARGETSTREAMER_H +#define XCORETARGETSTREAMER_H + +#include "llvm/MC/MCStreamer.h" + +namespace llvm { +class XCoreTargetStreamer : public MCTargetStreamer { +public: + XCoreTargetStreamer(MCStreamer &S); + virtual ~XCoreTargetStreamer(); + virtual void emitCCTopData(StringRef Name) = 0; + virtual void emitCCTopFunction(StringRef Name) = 0; + virtual void emitCCBottomData(StringRef Name) = 0; + virtual void emitCCBottomFunction(StringRef Name) = 0; +}; +} + +#endif diff --git a/lib/Target/XCore/XCoreTargetTransformInfo.cpp b/lib/Target/XCore/XCoreTargetTransformInfo.cpp index cc165f70dc285..80d193d1c26ea 100644 --- a/lib/Target/XCore/XCoreTargetTransformInfo.cpp +++ b/lib/Target/XCore/XCoreTargetTransformInfo.cpp @@ -14,16 +14,17 @@ /// //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "xcoretti" #include "XCore.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Support/Debug.h" -#include "llvm/Target/TargetLowering.h" #include "llvm/Target/CostTable.h" +#include "llvm/Target/TargetLowering.h" using namespace llvm; +#define DEBUG_TYPE "xcoretti" + // Declare the pass initialization routine locally as target-specific passes -// don't havve a target-wide initialization entry point, and so we rely on the +// don't have a target-wide initialization entry point, and so we rely on the // pass constructor initialization. namespace llvm { void initializeXCoreTTIPass(PassRegistry &); @@ -31,7 +32,7 @@ void initializeXCoreTTIPass(PassRegistry &); namespace { -class XCoreTTI : public ImmutablePass, public TargetTransformInfo { +class XCoreTTI final : public ImmutablePass, public TargetTransformInfo { public: XCoreTTI() : ImmutablePass(ID) { llvm_unreachable("This pass cannot be directly constructed"); @@ -42,27 +43,23 @@ public: initializeXCoreTTIPass(*PassRegistry::getPassRegistry()); } - virtual void initializePass() { + virtual void initializePass() override { pushTTIStack(this); } - virtual void finalizePass() { - popTTIStack(); - } - - virtual void getAnalysisUsage(AnalysisUsage &AU) const { + virtual void getAnalysisUsage(AnalysisUsage &AU) const override { TargetTransformInfo::getAnalysisUsage(AU); } static char ID; - virtual void *getAdjustedAnalysisPointer(const void *ID) { + virtual void *getAdjustedAnalysisPointer(const void *ID) override { if (ID == &TargetTransformInfo::ID) return (TargetTransformInfo*)this; return this; } - unsigned getNumberOfRegisters(bool Vector) const { + unsigned getNumberOfRegisters(bool Vector) const override { if (Vector) { return 0; } |
