X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FTarget%2FX86%2FX86TargetMachine.cpp;h=2c59ed3f1ac91d2e3589d35e5722fe57f7b8b5e8;hp=126042eeae42efb5be535b96dea9f6303f8e2e0d;hb=c1896335867238b01457db7e5a2a1a66d81a39d9;hpb=8a8d479214745c82ef00f08d4e4f1c173b5f9ce2 diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp index 126042eeae4..2c59ed3f1ac 100644 --- a/lib/Target/X86/X86TargetMachine.cpp +++ b/lib/Target/X86/X86TargetMachine.cpp @@ -13,149 +13,237 @@ #include "X86TargetMachine.h" #include "X86.h" -#include "llvm/PassManager.h" -#include "llvm/CodeGen/MachineFunction.h" +#include "X86TargetObjectFile.h" +#include "X86TargetTransformInfo.h" #include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/Target/TargetOptions.h" #include "llvm/Support/TargetRegistry.h" +#include "llvm/Target/TargetOptions.h" using namespace llvm; extern "C" void LLVMInitializeX86Target() { // Register the target. - RegisterTargetMachine X(TheX86_32Target); - RegisterTargetMachine Y(TheX86_64Target); + RegisterTargetMachine X(TheX86_32Target); + RegisterTargetMachine Y(TheX86_64Target); } +static std::unique_ptr createTLOF(const Triple &TT) { + if (TT.isOSBinFormatMachO()) { + if (TT.getArch() == Triple::x86_64) + return make_unique(); + return make_unique(); + } -X86_32TargetMachine::X86_32TargetMachine(const Target &T, StringRef TT, - StringRef CPU, StringRef FS, - const TargetOptions &Options, - Reloc::Model RM, CodeModel::Model CM, - CodeGenOpt::Level OL) - : X86TargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false), - DataLayout(getSubtargetImpl()->isTargetDarwin() ? - "e-p:32:32-f64:32:64-i64:32:64-f80:128:128-f128:128:128-" - "n8:16:32-S128" : - (getSubtargetImpl()->isTargetCygMing() || - getSubtargetImpl()->isTargetWindows()) ? - "e-p:32:32-f64:64:64-i64:64:64-f80:32:32-f128:128:128-" - "n8:16:32-S32" : - "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-f128:128:128-" - "n8:16:32-S128"), - InstrInfo(*this), - TSInfo(*this), - TLInfo(*this), - JITInfo(*this) { + if (TT.isOSLinux() || TT.isOSNaCl()) + return make_unique(); + if (TT.isOSBinFormatELF()) + return make_unique(); + if (TT.isKnownWindowsMSVCEnvironment()) + return make_unique(); + if (TT.isOSBinFormatCOFF()) + return make_unique(); + llvm_unreachable("unknown subtarget type"); } - -X86_64TargetMachine::X86_64TargetMachine(const Target &T, StringRef TT, - StringRef CPU, StringRef FS, - const TargetOptions &Options, - Reloc::Model RM, CodeModel::Model CM, - CodeGenOpt::Level OL) - : X86TargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true), - DataLayout("e-p:64:64-s:64-f64:64:64-i64:64:64-f80:128:128-f128:128:128-" - "n8:16:32:64-S128"), - InstrInfo(*this), - TSInfo(*this), - TLInfo(*this), - JITInfo(*this) { +static std::string computeDataLayout(const Triple &TT) { + // X86 is little endian + std::string Ret = "e"; + + Ret += DataLayout::getManglingComponent(TT); + // X86 and x32 have 32 bit pointers. + if ((TT.isArch64Bit() && + (TT.getEnvironment() == Triple::GNUX32 || TT.isOSNaCl())) || + !TT.isArch64Bit()) + Ret += "-p:32:32"; + + // Some ABIs align 64 bit integers and doubles to 64 bits, others to 32. + if (TT.isArch64Bit() || TT.isOSWindows() || TT.isOSNaCl()) + Ret += "-i64:64"; + else + Ret += "-f64:32:64"; + + // Some ABIs align long double to 128 bits, others to 32. + if (TT.isOSNaCl()) + ; // No f80 + else if (TT.isArch64Bit() || TT.isOSDarwin()) + Ret += "-f80:128"; + else + Ret += "-f80:32"; + + // The registers can hold 8, 16, 32 or, in x86-64, 64 bits. + if (TT.isArch64Bit()) + Ret += "-n8:16:32:64"; + else + Ret += "-n8:16:32"; + + // The stack is aligned to 32 bits on some ABIs and 128 bits on others. + if (!TT.isArch64Bit() && TT.isOSWindows()) + Ret += "-a:0:32-S32"; + else + Ret += "-S128"; + + return Ret; } /// X86TargetMachine ctor - Create an X86 target. /// -X86TargetMachine::X86TargetMachine(const Target &T, StringRef TT, - StringRef CPU, StringRef FS, - const TargetOptions &Options, +X86TargetMachine::X86TargetMachine(const Target &T, StringRef TT, StringRef CPU, + StringRef FS, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, - CodeGenOpt::Level OL, - bool is64Bit) - : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL), - Subtarget(TT, CPU, FS, Options.StackAlignmentOverride, is64Bit), - FrameLowering(*this, Subtarget), - ELFWriterInfo(is64Bit, true) { - // Determine the PICStyle based on the target selected. - if (getRelocationModel() == Reloc::Static) { - // Unless we're in PIC or DynamicNoPIC mode, set the PIC style to None. - Subtarget.setPICStyle(PICStyles::None); - } else if (Subtarget.is64Bit()) { - // PIC in 64 bit mode is always rip-rel. - Subtarget.setPICStyle(PICStyles::RIPRel); - } else if (Subtarget.isTargetCygMing()) { - Subtarget.setPICStyle(PICStyles::None); - } else if (Subtarget.isTargetDarwin()) { - if (getRelocationModel() == Reloc::PIC_) - Subtarget.setPICStyle(PICStyles::StubPIC); - else { - assert(getRelocationModel() == Reloc::DynamicNoPIC); - Subtarget.setPICStyle(PICStyles::StubDynamicNoPIC); - } - } else if (Subtarget.isTargetELF()) { - Subtarget.setPICStyle(PICStyles::GOT); - } - - // default to hard float ABI - if (Options.FloatABIType == FloatABI::Default) - this->Options.FloatABIType = FloatABI::Hard; + CodeGenOpt::Level OL) + : LLVMTargetMachine(T, computeDataLayout(Triple(TT)), TT, CPU, FS, Options, + RM, CM, OL), + TLOF(createTLOF(Triple(getTargetTriple()))), + Subtarget(TT, CPU, FS, *this, Options.StackAlignmentOverride) { + // Windows stack unwinder gets confused when execution flow "falls through" + // after a call to 'noreturn' function. + // To prevent that, we emit a trap for 'unreachable' IR instructions. + // (which on X86, happens to be the 'ud2' instruction) + if (Subtarget.isTargetWin64()) + this->Options.TrapUnreachable = true; + + initAsmInfo(); +} - if (Options.EnableSegmentedStacks && !Subtarget.isTargetELF()) - report_fatal_error("Segmented stacks are only implemented on ELF."); +X86TargetMachine::~X86TargetMachine() {} + +const X86Subtarget * +X86TargetMachine::getSubtargetImpl(const Function &F) const { + Attribute CPUAttr = F.getFnAttribute("target-cpu"); + Attribute FSAttr = F.getFnAttribute("target-features"); + + std::string CPU = !CPUAttr.hasAttribute(Attribute::None) + ? CPUAttr.getValueAsString().str() + : TargetCPU; + std::string FS = !FSAttr.hasAttribute(Attribute::None) + ? FSAttr.getValueAsString().str() + : TargetFS; + + // FIXME: This is related to the code below to reset the target options, + // we need to know whether or not the soft float flag is set on the + // function before we can generate a subtarget. We also need to use + // it as a key for the subtarget since that can be the only difference + // between two functions. + bool SoftFloat = + F.hasFnAttribute("use-soft-float") && + F.getFnAttribute("use-soft-float").getValueAsString() == "true"; + // If the soft float attribute is set on the function turn on the soft float + // subtarget feature. + if (SoftFloat) + FS += FS.empty() ? "+soft-float" : ",+soft-float"; + + auto &I = SubtargetMap[CPU + FS]; + if (!I) { + // This needs to be done before we create a new subtarget since any + // creation will depend on the TM and the code generation flags on the + // function that reside in TargetOptions. + resetTargetOptions(F); + I = llvm::make_unique(TargetTriple, CPU, FS, *this, + Options.StackAlignmentOverride); + } + return I.get(); } //===----------------------------------------------------------------------===// // Command line options for x86 //===----------------------------------------------------------------------===// static cl::opt -UseVZeroUpper("x86-use-vzeroupper", +UseVZeroUpper("x86-use-vzeroupper", cl::Hidden, cl::desc("Minimize AVX to SSE transition penalty"), cl::init(true)); +//===----------------------------------------------------------------------===// +// X86 TTI query. +//===----------------------------------------------------------------------===// + +TargetIRAnalysis X86TargetMachine::getTargetIRAnalysis() { + return TargetIRAnalysis( + [this](Function &F) { return TargetTransformInfo(X86TTIImpl(this, F)); }); +} + + //===----------------------------------------------------------------------===// // Pass Pipeline Configuration //===----------------------------------------------------------------------===// -bool X86TargetMachine::addInstSelector(PassManagerBase &PM) { +namespace { +/// X86 Code Generator Pass Configuration Options. +class X86PassConfig : public TargetPassConfig { +public: + X86PassConfig(X86TargetMachine *TM, PassManagerBase &PM) + : TargetPassConfig(TM, PM) {} + + X86TargetMachine &getX86TargetMachine() const { + return getTM(); + } + + void addIRPasses() override; + bool addInstSelector() override; + bool addILPOpts() override; + bool addPreISel() override; + void addPreRegAlloc() override; + void addPostRegAlloc() override; + void addPreEmitPass() override; +}; +} // namespace + +TargetPassConfig *X86TargetMachine::createPassConfig(PassManagerBase &PM) { + return new X86PassConfig(this, PM); +} + +void X86PassConfig::addIRPasses() { + addPass(createAtomicExpandPass(&getX86TargetMachine())); + + TargetPassConfig::addIRPasses(); +} + +bool X86PassConfig::addInstSelector() { // Install an instruction selector. - PM.add(createX86ISelDag(*this, getOptLevel())); + addPass(createX86ISelDag(getX86TargetMachine(), getOptLevel())); + + // For ELF, cleanup any local-dynamic TLS accesses. + if (Triple(TM->getTargetTriple()).isOSBinFormatELF() && + getOptLevel() != CodeGenOpt::None) + addPass(createCleanupLocalDynamicTLSPass()); - // For 32-bit, prepend instructions to set the "global base reg" for PIC. - if (!Subtarget.is64Bit()) - PM.add(createGlobalBaseRegPass()); + addPass(createX86GlobalBaseRegPass()); return false; } -bool X86TargetMachine::addPreRegAlloc(PassManagerBase &PM) { - PM.add(createX86MaxStackAlignmentHeuristicPass()); - return false; // -print-machineinstr shouldn't print after this. +bool X86PassConfig::addILPOpts() { + addPass(&EarlyIfConverterID); + return true; } -bool X86TargetMachine::addPostRegAlloc(PassManagerBase &PM) { - PM.add(createX86FloatingPointStackifierPass()); - return true; // -print-machineinstr should print after this. +bool X86PassConfig::addPreISel() { + // Only add this pass for 32-bit x86. + Triple TT(TM->getTargetTriple()); + if (TT.getArch() == Triple::x86) + addPass(createX86WinEHStatePass()); + return true; } -bool X86TargetMachine::addPreEmitPass(PassManagerBase &PM) { - bool ShouldPrint = false; - if (getOptLevel() != CodeGenOpt::None && Subtarget.hasXMMInt()) { - PM.add(createExecutionDependencyFixPass(&X86::VR128RegClass)); - ShouldPrint = true; - } - - if (Subtarget.hasAVX() && UseVZeroUpper) { - PM.add(createX86IssueVZeroUpperPass()); - ShouldPrint = true; - } +void X86PassConfig::addPreRegAlloc() { + addPass(createX86CallFrameOptimization()); +} - return ShouldPrint; +void X86PassConfig::addPostRegAlloc() { + addPass(createX86FloatingPointStackifierPass()); } -bool X86TargetMachine::addCodeEmitter(PassManagerBase &PM, - JITCodeEmitter &JCE) { - PM.add(createX86JITCodeEmitterPass(*this, JCE)); +void X86PassConfig::addPreEmitPass() { + if (getOptLevel() != CodeGenOpt::None) + addPass(createExecutionDependencyFixPass(&X86::VR128RegClass)); - return false; + if (UseVZeroUpper) + addPass(createX86IssueVZeroUpperPass()); + + if (getOptLevel() != CodeGenOpt::None) { + addPass(createX86PadShortFunctions()); + addPass(createX86FixupLEAs()); + } }