Chandler Carruth
2013-Apr-01 19:31 UTC
[LLVMdev] proposed change to class BasicTTI and dual mode mips16/32 working
On Thu, Mar 28, 2013 at 12:22 PM, Nadav Rotem <nrotem at apple.com> wrote:> IMHO the right way to handle target function attributes is to > re-initialize the target machine and TTI for every function (if the > attributes changed). Do you have another solution in mind ?I don't really understand this. TargetMachine and TTI may be quite expensive to initialize. Doing so for each (sometimes tiny) function processed doesn't make a lot of sense to me. Wouldn't it be better to design a TargetMachine (and TTI, or other passes that are similar) which provides context-sensitive answers? You could imagine this being a wrapper which delegates to one of two real TM and TTI implementations based on a mode switch. Alternatively, we could look at partitioning functions into two modules, and then bring up the infrastructure once per module. I would personally choose between these based on how much shared functionality there would be in the TM and TTI between the two. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20130401/a71389c1/attachment.html>
Nadav Rotem
2013-Apr-01 19:58 UTC
[LLVMdev] proposed change to class BasicTTI and dual mode mips16/32 working
> On Thu, Mar 28, 2013 at 12:22 PM, Nadav Rotem <nrotem at apple.com> wrote: > IMHO the right way to handle target function attributes is to re-initialize the target machine and TTI for every function (if the attributes changed). Do you have another solution in mind ? > > I don't really understand this. > > TargetMachine and TTI may be quite expensive to initialize.Yes. But we can keep a few TMs around and only initialize TTI, which should be inexpensive to initialize because it has no state.> Doing so for each (sometimes tiny) function processed doesn't make a lot of sense to me.I assume that even for LTO builds, the target attributes won't change very often.> Wouldn't it be better to design a TargetMachine (and TTI, or other passes that are similar) which provides context-sensitive answers? You could imagine this being a wrapper which delegates to one of two real TM and TTI implementations based on a mode switch.This can work, but I don't have enough information about two things: 1. How often do we switch TMs. (and how expensive it is) 2. How complex is it to create a wrapper and what overhead is the wrapper going to add. Do you have a design in mind for such a wrapper ?> Alternatively, we could look at partitioning functions into two modules, and then bring up the infrastructure once per module.I am not sure if this can work. I see a scenario where a non-AVX function can call an AVX functions. Splitting these into two modules can potentially prevent some optimizations.> I would personally choose between these based on how much shared functionality there would be in the TM and TTI between the two.-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20130401/be331513/attachment.html>
reed kotler
2013-Apr-01 20:41 UTC
[LLVMdev] proposed change to class BasicTTI and dual mode mips16/32 working
On 04/01/2013 12:31 PM, Chandler Carruth wrote:> On Thu, Mar 28, 2013 at 12:22 PM, Nadav Rotem <nrotem at apple.com > <mailto:nrotem at apple.com>> wrote: > > IMHO the right way to handle target function attributes is to > re-initialize the target machine and TTI for every function (if > the attributes changed). Do you have another solution in mind ? > > > I don't really understand this. > > TargetMachine and TTI may be quite expensive to initialize. Doing so > for each (sometimes tiny) function processed doesn't make a lot of > sense to me. > > Wouldn't it be better to design a TargetMachine (and TTI, or other > passes that are similar) which provides context-sensitive answers? You > could imagine this being a wrapper which delegates to one of two real > TM and TTI implementations based on a mode switch. > > Alternatively, we could look at partitioning functions into two > modules, and then bring up the infrastructure once per module. > > I would personally choose between these based on how much shared > functionality there would be in the TM and TTI between the two.For changing subtargets, i.e. mips16 to mips32 on a per function basis, I only have one copy of all that is needed for both mips16 and mips32. What I do is I have two versions of the instruction selection pass (mips16 and mips32) and a controller pass which is used to reset parts of target machine when needed (ptrs to target lowering, register info, frame lowering which in the case of mips16 / mips32 are different derived classes). If the run machine function is called in the mips16 instruction selection pass, it returns immediately if it's in mips32 mode and similarly in the mips32 instruction selection pass. The one hole is this immutable pass for basic target transform info which should be a function pass. This can also be done so that maybe only at most two copies of this pass are present and the information is reset when the subtarget changes. I'm attaching the current state of the patch in case you want to see how I'm doing this now. Many things can be handled with just options to the normal setup but something which differs as much as mips16 and mips32 or thumb1 and arm need a subtarget reset. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20130401/7d0151ef/attachment.html> -------------- next part -------------- diff --git a/lib/Target/Mips/CMakeLists.txt b/lib/Target/Mips/CMakeLists.txt index cf8bb18..1029e3c 100644 --- a/lib/Target/Mips/CMakeLists.txt +++ b/lib/Target/Mips/CMakeLists.txt @@ -32,6 +32,8 @@ add_llvm_target(MipsCodeGen MipsLongBranch.cpp MipsMCInstLower.cpp MipsMachineFunction.cpp + MipsModuleISelDAGToDAG.cpp + MipsModuleISelLowering.cpp MipsRegisterInfo.cpp MipsSEFrameLowering.cpp MipsSEInstrInfo.cpp diff --git a/lib/Target/Mips/Mips16ISelDAGToDAG.cpp b/lib/Target/Mips/Mips16ISelDAGToDAG.cpp index 00b3449..2ffd3a9 100644 --- a/lib/Target/Mips/Mips16ISelDAGToDAG.cpp +++ b/lib/Target/Mips/Mips16ISelDAGToDAG.cpp @@ -35,6 +35,11 @@ #include "llvm/Target/TargetMachine.h" using namespace llvm; +bool Mips16DAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { + if (!Subtarget.inMips16Mode()) + return false; + return MipsDAGToDAGISel::runOnMachineFunction(MF); +} /// Select multiply instructions. std::pair<SDNode*, SDNode*> Mips16DAGToDAGISel::selectMULT(SDNode *N, unsigned Opc, DebugLoc DL, EVT Ty, diff --git a/lib/Target/Mips/Mips16ISelDAGToDAG.h b/lib/Target/Mips/Mips16ISelDAGToDAG.h index baa8587..f05f9b7 100644 --- a/lib/Target/Mips/Mips16ISelDAGToDAG.h +++ b/lib/Target/Mips/Mips16ISelDAGToDAG.h @@ -28,6 +28,8 @@ private: SDValue getMips16SPAliasReg(); + virtual bool runOnMachineFunction(MachineFunction &MF); + void getMips16SPRefReg(SDNode *Parent, SDValue &AliasReg); virtual bool selectAddr16(SDNode *Parent, SDValue N, SDValue &Base, diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp index 1876cb6..e0ddade 100644 --- a/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/MipsAsmPrinter.cpp @@ -46,6 +46,10 @@ using namespace llvm; bool MipsAsmPrinter::runOnMachineFunction(MachineFunction &MF) { + // Initialize TargetLoweringObjectFile. + if (Subtarget->allowMixed16_32()) + const_cast<TargetLoweringObjectFile&>(getObjFileLowering()) + .Initialize(OutContext, TM); MipsFI = MF.getInfo<MipsFunctionInfo>(); AsmPrinter::runOnMachineFunction(MF); return true; diff --git a/lib/Target/Mips/MipsConstantIslandPass.cpp b/lib/Target/Mips/MipsConstantIslandPass.cpp index b5de1eb..579abbf 100644 --- a/lib/Target/Mips/MipsConstantIslandPass.cpp +++ b/lib/Target/Mips/MipsConstantIslandPass.cpp @@ -80,6 +80,9 @@ FunctionPass *llvm::createMipsConstantIslandPass(MipsTargetMachine &tm) { } bool MipsConstantIslands::runOnMachineFunction(MachineFunction &F) { - return true; + // The intention is for this to be a mips16 only pass for now + if (!TM.getSubtarget<MipsSubtarget>().inMips16Mode()) + return false; + return false; } diff --git a/lib/Target/Mips/MipsLongBranch.cpp b/lib/Target/Mips/MipsLongBranch.cpp index 2efe534..bf5ad37 100644 --- a/lib/Target/Mips/MipsLongBranch.cpp +++ b/lib/Target/Mips/MipsLongBranch.cpp @@ -399,6 +399,8 @@ static void emitGPDisp(MachineFunction &F, const MipsInstrInfo *TII) { } bool MipsLongBranch::runOnMachineFunction(MachineFunction &F) { + if (TM.getSubtarget<MipsSubtarget>().inMips16Mode()) + return false; if ((TM.getRelocationModel() == Reloc::PIC_) && TM.getSubtarget<MipsSubtarget>().isABI_O32() && F.getInfo<MipsFunctionInfo>()->globalBaseRegSet()) diff --git a/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp b/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp new file mode 100644 index 0000000..14a55b4 --- /dev/null +++ b/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// Instruction Selector Implementation +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// MipsDAGToDAGISel - MIPS specific code to select MIPS machine +// instructions for SelectionDAG operations. +//===----------------------------------------------------------------------===// + +#include "MipsISelDAGToDAG.h" +#include "MipsModuleISelDAGToDAG.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +bool MipsModuleDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { + DEBUG(errs() << "In MipsModuleDAGToDAGISel::runMachineFunction\n"); + const_cast<MipsSubtarget&>(Subtarget).resetSubtarget(&MF); + return false; +} + + +} + + +llvm::FunctionPass *llvm::createMipsModuleISelDag(MipsTargetMachine &TM) { + return new MipsModuleDAGToDAGISel(TM); +} diff --git a/lib/Target/Mips/MipsModuleISelDAGToDAG.h b/lib/Target/Mips/MipsModuleISelDAGToDAG.h new file mode 100644 index 0000000..64bbf83e --- /dev/null +++ b/lib/Target/Mips/MipsModuleISelDAGToDAG.h @@ -0,0 +1,60 @@ +//===---- MipsISelDAGToDAG.h - A Dag to Dag Inst Selector for Mips --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an instruction selector for the MIPS target. +// +//===----------------------------------------------------------------------===// + +#ifndef MIPSMODULEISELDAGTODAG_H +#define MIPSMODULEISELDAGTODAG_H + +#include "Mips.h" +#include "MipsSubtarget.h" +#include "MipsTargetMachine.h" +#include "llvm/CodeGen/SelectionDAGISel.h" + + +//===----------------------------------------------------------------------===// +// Instruction Selector Implementation +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// MipsModuleDAGToDAGISel - MIPS specific code to select MIPS machine +// instructions for SelectionDAG operations. +//===----------------------------------------------------------------------===// +namespace llvm { + +class MipsModuleDAGToDAGISel : public SelectionDAGISel { +public: + explicit MipsModuleDAGToDAGISel(MipsTargetMachine &TM) + : SelectionDAGISel(TM), Subtarget(TM.getSubtarget<MipsSubtarget>()) {} + + // Pass Name + virtual const char *getPassName() const { + return "MIPS DAG->DAG Pattern Instruction Selection"; + } + + virtual bool runOnMachineFunction(MachineFunction &MF); + + virtual SDNode *Select(SDNode *N) { + llvm_unreachable("unexpected"); + } + +protected: + /// Keep a pointer to the MipsSubtarget around so that we can make the right + /// decision when generating code for different targets. + const MipsSubtarget &Subtarget; +}; + +/// createMipsISelDag - This pass converts a legalized DAG into a +/// MIPS-specific DAG, ready for instruction scheduling. +FunctionPass *createMipsModuleISelDag(MipsTargetMachine &TM); +} + +#endif diff --git a/lib/Target/Mips/MipsSEISelDAGToDAG.cpp b/lib/Target/Mips/MipsSEISelDAGToDAG.cpp index d6d2207..0fc3c5e 100644 --- a/lib/Target/Mips/MipsSEISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsSEISelDAGToDAG.cpp @@ -35,6 +35,11 @@ #include "llvm/Target/TargetMachine.h" using namespace llvm; +bool MipsSEDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { + if (Subtarget.inMips16Mode()) + return false; + return MipsDAGToDAGISel::runOnMachineFunction(MF); +} bool MipsSEDAGToDAGISel::replaceUsesWithZeroReg(MachineRegisterInfo *MRI, const MachineInstr& MI) { diff --git a/lib/Target/Mips/MipsSEISelDAGToDAG.h b/lib/Target/Mips/MipsSEISelDAGToDAG.h index 6137ab0..0dae73d 100644 --- a/lib/Target/Mips/MipsSEISelDAGToDAG.h +++ b/lib/Target/Mips/MipsSEISelDAGToDAG.h @@ -24,6 +24,9 @@ public: explicit MipsSEDAGToDAGISel(MipsTargetMachine &TM) : MipsDAGToDAGISel(TM) {} private: + + virtual bool runOnMachineFunction(MachineFunction &MF); + bool replaceUsesWithZeroReg(MachineRegisterInfo *MRI, const MachineInstr&); std::pair<SDNode*, SDNode*> selectMULT(SDNode *N, unsigned Opc, DebugLoc dl, diff --git a/lib/Target/Mips/MipsSEISelLowering.cpp b/lib/Target/Mips/MipsSEISelLowering.cpp index 4f21921..df6af09 100644 --- a/lib/Target/Mips/MipsSEISelLowering.cpp +++ b/lib/Target/Mips/MipsSEISelLowering.cpp @@ -27,6 +27,9 @@ EnableMipsTailCalls("enable-mips-tail-calls", cl::Hidden, MipsSETargetLowering::MipsSETargetLowering(MipsTargetMachine &TM) : MipsTargetLowering(TM) { // Set up the register classes + + clearRegisterClasses(); + addRegisterClass(MVT::i32, &Mips::CPURegsRegClass); if (HasMips64) diff --git a/lib/Target/Mips/MipsSubtarget.cpp b/lib/Target/Mips/MipsSubtarget.cpp index e11e5d1..4f56bd5 100644 --- a/lib/Target/Mips/MipsSubtarget.cpp +++ b/lib/Target/Mips/MipsSubtarget.cpp @@ -11,29 +11,47 @@ // //===----------------------------------------------------------------------===// +#define DEBUG_TYPE "mips-subtarget" + +#include "MipsMachineFunction.h" #include "MipsSubtarget.h" +#include "MipsTargetMachine.h" #include "Mips.h" #include "MipsRegisterInfo.h" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/Function.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/raw_ostream.h" #define GET_SUBTARGETINFO_TARGET_DESC #define GET_SUBTARGETINFO_CTOR #include "MipsGenSubtargetInfo.inc" + using namespace llvm; +static cl::opt<bool> Mixed16_32( + "mips-mixed-16-32", + cl::init(false), + cl::desc("Allow for a mixture of Mips16 " + "and Mips32 code in a single source file"), + cl::Hidden); + void MipsSubtarget::anchor() { } MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU, const std::string &FS, bool little, - Reloc::Model _RM) : + Reloc::Model _RM, MipsTargetMachine *_TM) : MipsGenSubtargetInfo(TT, CPU, FS), MipsArchVersion(Mips32), MipsABI(UnknownABI), IsLittle(little), IsSingleFloat(false), IsFP64bit(false), IsGP64bit(false), HasVFPU(false), IsLinux(true), HasSEInReg(false), HasCondMov(false), HasSwap(false), HasBitCount(false), HasFPIdx(false), InMips16Mode(false), InMicroMipsMode(false), HasDSP(false), HasDSPR2(false), - RM(_RM) + AllowMixed16_32(Mixed16_32), + RM(_RM), OverrideMode(NoOverride), TM(_TM) { std::string CPUName = CPU; if (CPUName.empty()) @@ -42,6 +60,8 @@ MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU, // Parse features string. ParseSubtargetFeatures(CPUName, FS); + PreviousInMips16Mode = InMips16Mode; + // Initialize scheduling itinerary for the specified CPU. InstrItins = getInstrItineraryForCPU(CPUName); @@ -72,3 +92,45 @@ MipsSubtarget::enablePostRAScheduler(CodeGenOpt::Level OptLevel, &Mips::CPU64RegsRegClass : &Mips::CPURegsRegClass); return OptLevel >= CodeGenOpt::Aggressive; } +void MipsSubtarget::resetSubtarget(MachineFunction *MF) { + bool ChangeToMips16 = false, ChangeToNoMips16 = false; + DEBUG(dbgs() << "resetSubtargetFeatures" << "\n"); + AttributeSet FnAttrs = MF->getFunction()->getAttributes(); + ChangeToMips16 = FnAttrs.hasAttribute(AttributeSet::FunctionIndex, + "mips16"); + ChangeToNoMips16 = FnAttrs.hasAttribute(AttributeSet::FunctionIndex, + "nomips16"); + assert (!(ChangeToMips16 & ChangeToNoMips16) && + "mips16 and nomips16 specified on the same function"); + if (ChangeToMips16) { + if (PreviousInMips16Mode) + return; + OverrideMode = Mips16Override; + PreviousInMips16Mode = true; + TM->setHelperClassesMips16(); + return; + } + else if (ChangeToNoMips16) { + if (!PreviousInMips16Mode) + return; + OverrideMode = NoMips16Override; + PreviousInMips16Mode = false; + TM->setHelperClassesMipsSE(); + return; + } + else { + if (OverrideMode == NoOverride) + return; + OverrideMode = NoOverride; + DEBUG(dbgs() << "back to default" << "\n"); + if (inMips16Mode() && !PreviousInMips16Mode) + TM->setHelperClassesMips16(); + else if (!inMips16Mode() && PreviousInMips16Mode) + TM->setHelperClassesMipsSE(); + return; + } +} + +void MipsSubtarget::resetSubtargetFeatures(const MachineFunction *MF) { +} + diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h index 7a2e47c..b201bd8 100644 --- a/lib/Target/Mips/MipsSubtarget.h +++ b/lib/Target/Mips/MipsSubtarget.h @@ -16,7 +16,9 @@ #include "MCTargetDesc/MipsReginfo.h" #include "llvm/MC/MCInstrItineraries.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Target/TargetSubtargetInfo.h" + #include <string> #define GET_SUBTARGETINFO_HEADER @@ -25,6 +27,8 @@ namespace llvm { class StringRef; +class MipsTargetMachine; + class MipsSubtarget : public MipsGenSubtargetInfo { virtual void anchor(); @@ -89,12 +93,18 @@ protected: // InMips16 -- can process Mips16 instructions bool InMips16Mode; + // PreviousInMips16 -- the function we just processed was in Mips 16 Mode + bool PreviousInMips16Mode; + // InMicroMips -- can process MicroMips instructions bool InMicroMipsMode; // HasDSP, HasDSPR2 -- supports DSP ASE. bool HasDSP, HasDSPR2; + // Allow mixed Mips16 and Mips32 in one source file + bool AllowMixed16_32; + InstrItineraryData InstrItins; // The instance to the register info section object @@ -103,6 +113,12 @@ protected: // Relocation Model Reloc::Model RM; + // We can override the determination of whether we are in mips16 mode + // as from the command line + enum {NoOverride, Mips16Override, NoMips16Override} OverrideMode; + + MipsTargetMachine *TM; + public: virtual bool enablePostRAScheduler(CodeGenOpt::Level OptLevel, AntiDepBreakMode& Mode, @@ -118,7 +134,8 @@ public: /// This constructor initializes the data members to match that /// of the specified triple. MipsSubtarget(const std::string &TT, const std::string &CPU, - const std::string &FS, bool little, Reloc::Model RM); + const std::string &FS, bool little, Reloc::Model RM, + MipsTargetMachine *TM); /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. @@ -137,7 +154,20 @@ public: bool isSingleFloat() const { return IsSingleFloat; } bool isNotSingleFloat() const { return !IsSingleFloat; } bool hasVFPU() const { return HasVFPU; } - bool inMips16Mode() const { return InMips16Mode; } + bool inMips16Mode() const { + switch (OverrideMode) { + case NoOverride: + return InMips16Mode; + case Mips16Override: + return true; + case NoMips16Override: + return false; + } + llvm_unreachable("Unexpected mode"); + } + bool inMips16ModeDefault() { + return InMips16Mode; + } bool inMicroMipsMode() const { return InMicroMipsMode; } bool hasDSP() const { return HasDSP; } bool hasDSPR2() const { return HasDSPR2; } @@ -153,11 +183,20 @@ public: bool hasBitCount() const { return HasBitCount; } bool hasFPIdx() const { return HasFPIdx; } + bool allowMixed16_32() const { return AllowMixed16_32;}; + // Grab MipsRegInfo object const MipsReginfo &getMReginfo() const { return MRI; } // Grab relocation model Reloc::Model getRelocationModel() const {return RM;} + + /// \brief Reset the subtarget for the Mips target. + virtual void resetSubtarget(MachineFunction *MF); + + /// \brief Reset the features for the Mips target. + virtual void resetSubtargetFeatures(const MachineFunction *MF); + }; } // End llvm namespace diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp index 3336358..e0e4a3e 100644 --- a/lib/Target/Mips/MipsTargetMachine.cpp +++ b/lib/Target/Mips/MipsTargetMachine.cpp @@ -15,11 +15,25 @@ #include "Mips.h" #include "MipsFrameLowering.h" #include "MipsInstrInfo.h" +#include "MipsModuleISelDAGToDAG.h" +#include "MipsSEFrameLowering.h" +#include "MipsSEInstrInfo.h" +#include "MipsSEISelLowering.h" +#include "MipsSEISelDAGToDAG.h" +#include "Mips16FrameLowering.h" +#include "Mips16InstrInfo.h" +#include "Mips16ISelDAGToDAG.h" +#include "Mips16ISelLowering.h" +#include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/CodeGen/Passes.h" #include "llvm/PassManager.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Support/TargetRegistry.h" using namespace llvm; + + extern "C" void LLVMInitializeMipsTarget() { // Register the target. RegisterTargetMachine<MipsebTargetMachine> X(TheMipsTarget); @@ -42,7 +56,7 @@ MipsTargetMachine(const Target &T, StringRef TT, CodeGenOpt::Level OL, bool isLittle) : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL), - Subtarget(TT, CPU, FS, isLittle, RM), + Subtarget(TT, CPU, FS, isLittle, RM, this), DL(isLittle ? (Subtarget.isABI_N64() ? "e-p:64:64:64-i8:8:32-i16:16:32-i64:64:64-f128:128:128-" @@ -54,9 +68,48 @@ MipsTargetMachine(const Target &T, StringRef TT, "E-p:32:32:32-i8:8:32-i16:16:32-i64:64:64-n32-S64")), InstrInfo(MipsInstrInfo::create(*this)), FrameLowering(MipsFrameLowering::create(*this, Subtarget)), - TLInfo(MipsTargetLowering::create(*this)), TSInfo(*this), JITInfo() { + TLInfo(MipsTargetLowering::create(*this)), + TSInfo(*this), JITInfo() { +} + + +void MipsTargetMachine::setHelperClassesMips16() { + InstrInfoSE.swap(InstrInfo); + FrameLoweringSE.swap(FrameLowering); + TLInfoSE.swap(TLInfo); + if (!InstrInfo16) { + InstrInfo.reset(MipsInstrInfo::create(*this)); + FrameLowering.reset(MipsFrameLowering::create(*this, Subtarget)); + TLInfo.reset(MipsTargetLowering::create(*this)); + } + else { + InstrInfo16.swap(InstrInfo); + FrameLowering16.swap(FrameLowering); + TLInfo16.swap(TLInfo); + } + assert(TLInfo && "null target lowering 16"); + assert(InstrInfo && "null instr info 16"); + assert(FrameLowering && "null frame lowering 16"); } +void MipsTargetMachine::setHelperClassesMipsSE() { + InstrInfo16.swap(InstrInfo); + FrameLowering16.swap(FrameLowering); + TLInfo16.swap(TLInfo); + if (!InstrInfoSE) { + InstrInfo.reset(MipsInstrInfo::create(*this)); + FrameLowering.reset(MipsFrameLowering::create(*this, Subtarget)); + TLInfo.reset(MipsTargetLowering::create(*this)); + } + else { + InstrInfoSE.swap(InstrInfo); + FrameLoweringSE.swap(FrameLowering); + TLInfoSE.swap(TLInfo); + } + assert(TLInfo && "null target lowering in SE"); + assert(InstrInfo && "null instr info SE"); + assert(FrameLowering && "null frame lowering SE"); +} void MipsebTargetMachine::anchor() { } MipsebTargetMachine:: @@ -102,21 +155,40 @@ TargetPassConfig *MipsTargetMachine::createPassConfig(PassManagerBase &PM) { // Install an instruction selector pass using // the ISelDag to gen Mips code. bool MipsPassConfig::addInstSelector() { - addPass(createMipsISelDag(getMipsTargetMachine())); + if (getMipsSubtarget().allowMixed16_32()) { + addPass(createMipsModuleISelDag(getMipsTargetMachine())); + addPass(createMips16ISelDag(getMipsTargetMachine())); + addPass(createMipsSEISelDag(getMipsTargetMachine())); + } + else { + addPass(createMipsISelDag(getMipsTargetMachine())); + } return false; } +void MipsTargetMachine::addAnalysisPasses(PassManagerBase &PM) { + if (Subtarget.allowMixed16_32()) { + DEBUG(errs() << "No "); + PM.add(createNoTargetTransformInfoPass()); + } + else + LLVMTargetMachine::addAnalysisPasses(PM); + DEBUG(errs() << "Target Transform Info Pass Added\n"); +} + // Implemented by targets that want to run passes immediately before // machine code is emitted. return true if -print-machineinstrs should // print out the code after the passes. bool MipsPassConfig::addPreEmitPass() { MipsTargetMachine &TM = getMipsTargetMachine(); + const MipsSubtarget &Subtarget = TM.getSubtarget<MipsSubtarget>(); addPass(createMipsDelaySlotFillerPass(TM)); - // NOTE: long branch has not been implemented for mips16. - if (TM.getSubtarget<MipsSubtarget>().hasStandardEncoding()) + if (Subtarget.hasStandardEncoding() || + Subtarget.allowMixed16_32()) addPass(createMipsLongBranchPass(TM)); - if (TM.getSubtarget<MipsSubtarget>().inMips16Mode()) + if (Subtarget.inMips16Mode() || + Subtarget.allowMixed16_32()) addPass(createMipsConstantIslandPass(TM)); return true; diff --git a/lib/Target/Mips/MipsTargetMachine.h b/lib/Target/Mips/MipsTargetMachine.h index 7e5f192..ee55708 100644 --- a/lib/Target/Mips/MipsTargetMachine.h +++ b/lib/Target/Mips/MipsTargetMachine.h @@ -21,6 +21,8 @@ #include "MipsSelectionDAGInfo.h" #include "MipsSubtarget.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/IR/DataLayout.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetMachine.h" @@ -35,6 +37,12 @@ class MipsTargetMachine : public LLVMTargetMachine { OwningPtr<const MipsInstrInfo> InstrInfo; OwningPtr<const MipsFrameLowering> FrameLowering; OwningPtr<const MipsTargetLowering> TLInfo; + OwningPtr<const MipsInstrInfo> InstrInfo16; + OwningPtr<const MipsFrameLowering> FrameLowering16; + OwningPtr<const MipsTargetLowering> TLInfo16; + OwningPtr<const MipsInstrInfo> InstrInfoSE; + OwningPtr<const MipsFrameLowering> FrameLoweringSE; + OwningPtr<const MipsTargetLowering> TLInfoSE; MipsSelectionDAGInfo TSInfo; MipsJITInfo JITInfo; @@ -47,6 +55,8 @@ public: virtual ~MipsTargetMachine() {} + virtual void addAnalysisPasses(PassManagerBase &PM); + virtual const MipsInstrInfo *getInstrInfo() const { return InstrInfo.get(); } virtual const TargetFrameLowering *getFrameLowering() const @@ -73,6 +83,13 @@ public: // Pass Pipeline Configuration virtual TargetPassConfig *createPassConfig(PassManagerBase &PM); virtual bool addCodeEmitter(PassManagerBase &PM, JITCodeEmitter &JCE); + + // Set helper classes + void setHelperClassesMips16(); + + void setHelperClassesMipsSE(); + + }; /// MipsebTargetMachine - Mips32/64 big endian target machine. diff --git a/test/CodeGen/Mips/mips16_32_1.ll b/test/CodeGen/Mips/mips16_32_1.ll new file mode 100644 index 0000000..6f4826e --- /dev/null +++ b/test/CodeGen/Mips/mips16_32_1.ll @@ -0,0 +1,14 @@ +; RUN: llc -march=mipsel -mcpu=mips16 -relocation-model=pic -O3 < %s -mips-mixed-16-32 | FileCheck %s +; RUN: llc -march=mipsel -mcpu=mips32 -relocation-model=pic -O3 < %s -mips-mixed-16-32 | FileCheck %s + +define void @foo() #0 { +entry: + ret void +} + +; CHECK: .set mips16 # @foo +; CHECK: .ent foo +; CHECK: save {{.+}} +; CHECK: restore {{.+}} +; CHECK: .end foo +attributes #0 = { nounwind "less-precise-fpmad"="false" "mips16" "no-frame-pointer-elim"="false" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
Reed Kotler
2013-Apr-01 21:50 UTC
[LLVMdev] proposed change to class BasicTTI and dual mode mips16/32 working
One set of issues here is that target independent optimizations that use the TTI would have to all be function passes too if they are going to change based on the subtarget (mip32/mips16 or arm/thumb1). On 04/01/2013 01:41 PM, reed kotler wrote:> On 04/01/2013 12:31 PM, Chandler Carruth wrote: >> On Thu, Mar 28, 2013 at 12:22 PM, Nadav Rotem <nrotem at apple.com >> <mailto:nrotem at apple.com>> wrote: >> >> IMHO the right way to handle target function attributes is to >> re-initialize the target machine and TTI for every function (if >> the attributes changed). Do you have another solution in mind ? >> >> >> I don't really understand this. >> >> TargetMachine and TTI may be quite expensive to initialize. Doing so >> for each (sometimes tiny) function processed doesn't make a lot of >> sense to me. >> >> Wouldn't it be better to design a TargetMachine (and TTI, or other >> passes that are similar) which provides context-sensitive answers? You >> could imagine this being a wrapper which delegates to one of two real >> TM and TTI implementations based on a mode switch. >> >> Alternatively, we could look at partitioning functions into two >> modules, and then bring up the infrastructure once per module. >> >> I would personally choose between these based on how much shared >> functionality there would be in the TM and TTI between the two. > For changing subtargets, i.e. mips16 to mips32 on a per function basis, > I only have one copy of all that is needed for both mips16 and mips32. > > What I do is I have two versions of the instruction selection pass > (mips16 and mips32) and a controller pass which is used to reset parts > of target machine when needed (ptrs to target lowering, register info, > frame lowering which in the case of mips16 / mips32 are different > derived classes). > > If the run machine function is called in the mips16 instruction > selection pass, it returns immediately if it's in mips32 mode and > similarly in the mips32 instruction selection pass. > > The one hole is this immutable pass for basic target transform info > which should be a function pass. This can also be done so that maybe > only at most two copies of this pass are present and the information is > reset when the subtarget changes. > > I'm attaching the current state of the patch in case you want to see how > I'm doing this now. > > Many things can be handled with just options to the normal setup but > something which differs as much as mips16 and mips32 or thumb1 and arm > need a subtarget reset. > > > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >
Seemingly Similar Threads
- [LLVMdev] proposed change to class BasicTTI and dual mode mips16/32 working
- [LLVMdev] [MC] [llvm-mc] Getting target specific information to <target>ELFObjectWriter
- [LLVMdev] [MC] [llvm-mc] Getting target specific information to <target>ELFObjectWriter
- [LLVMdev] [MC] [llvm-mc] Getting target specific information to <target>ELFObjectWriter
- [LLVMdev] llvm-gcc and mips