1*0b57cec5SDimitry Andric //===-- X86TargetMachine.cpp - Define TargetMachine for the X86 -----------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file defines the X86 specific subclass of TargetMachine. 10*0b57cec5SDimitry Andric // 11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #include "X86TargetMachine.h" 14*0b57cec5SDimitry Andric #include "MCTargetDesc/X86MCTargetDesc.h" 15*0b57cec5SDimitry Andric #include "TargetInfo/X86TargetInfo.h" 16*0b57cec5SDimitry Andric #include "X86.h" 17*0b57cec5SDimitry Andric #include "X86CallLowering.h" 18*0b57cec5SDimitry Andric #include "X86LegalizerInfo.h" 19*0b57cec5SDimitry Andric #include "X86MacroFusion.h" 20*0b57cec5SDimitry Andric #include "X86Subtarget.h" 21*0b57cec5SDimitry Andric #include "X86TargetObjectFile.h" 22*0b57cec5SDimitry Andric #include "X86TargetTransformInfo.h" 23*0b57cec5SDimitry Andric #include "llvm/ADT/Optional.h" 24*0b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 25*0b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 26*0b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 27*0b57cec5SDimitry Andric #include "llvm/ADT/Triple.h" 28*0b57cec5SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h" 29*0b57cec5SDimitry Andric #include "llvm/CodeGen/ExecutionDomainFix.h" 30*0b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/CallLowering.h" 31*0b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/IRTranslator.h" 32*0b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/InstructionSelect.h" 33*0b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/Legalizer.h" 34*0b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/RegBankSelect.h" 35*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineScheduler.h" 36*0b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h" 37*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h" 38*0b57cec5SDimitry Andric #include "llvm/IR/Attributes.h" 39*0b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 40*0b57cec5SDimitry Andric #include "llvm/IR/Function.h" 41*0b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 42*0b57cec5SDimitry Andric #include "llvm/Pass.h" 43*0b57cec5SDimitry Andric #include "llvm/Support/CodeGen.h" 44*0b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 45*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 46*0b57cec5SDimitry Andric #include "llvm/Support/TargetRegistry.h" 47*0b57cec5SDimitry Andric #include "llvm/Target/TargetLoweringObjectFile.h" 48*0b57cec5SDimitry Andric #include "llvm/Target/TargetOptions.h" 49*0b57cec5SDimitry Andric #include <memory> 50*0b57cec5SDimitry Andric #include <string> 51*0b57cec5SDimitry Andric 52*0b57cec5SDimitry Andric using namespace llvm; 53*0b57cec5SDimitry Andric 54*0b57cec5SDimitry Andric static cl::opt<bool> EnableMachineCombinerPass("x86-machine-combiner", 55*0b57cec5SDimitry Andric cl::desc("Enable the machine combiner pass"), 56*0b57cec5SDimitry Andric cl::init(true), cl::Hidden); 57*0b57cec5SDimitry Andric 58*0b57cec5SDimitry Andric static cl::opt<bool> EnableCondBrFoldingPass("x86-condbr-folding", 59*0b57cec5SDimitry Andric cl::desc("Enable the conditional branch " 60*0b57cec5SDimitry Andric "folding pass"), 61*0b57cec5SDimitry Andric cl::init(false), cl::Hidden); 62*0b57cec5SDimitry Andric 63*0b57cec5SDimitry Andric extern "C" void LLVMInitializeX86Target() { 64*0b57cec5SDimitry Andric // Register the target. 65*0b57cec5SDimitry Andric RegisterTargetMachine<X86TargetMachine> X(getTheX86_32Target()); 66*0b57cec5SDimitry Andric RegisterTargetMachine<X86TargetMachine> Y(getTheX86_64Target()); 67*0b57cec5SDimitry Andric 68*0b57cec5SDimitry Andric PassRegistry &PR = *PassRegistry::getPassRegistry(); 69*0b57cec5SDimitry Andric initializeGlobalISel(PR); 70*0b57cec5SDimitry Andric initializeWinEHStatePassPass(PR); 71*0b57cec5SDimitry Andric initializeFixupBWInstPassPass(PR); 72*0b57cec5SDimitry Andric initializeEvexToVexInstPassPass(PR); 73*0b57cec5SDimitry Andric initializeFixupLEAPassPass(PR); 74*0b57cec5SDimitry Andric initializeFPSPass(PR); 75*0b57cec5SDimitry Andric initializeX86CallFrameOptimizationPass(PR); 76*0b57cec5SDimitry Andric initializeX86CmovConverterPassPass(PR); 77*0b57cec5SDimitry Andric initializeX86ExpandPseudoPass(PR); 78*0b57cec5SDimitry Andric initializeX86ExecutionDomainFixPass(PR); 79*0b57cec5SDimitry Andric initializeX86DomainReassignmentPass(PR); 80*0b57cec5SDimitry Andric initializeX86AvoidSFBPassPass(PR); 81*0b57cec5SDimitry Andric initializeX86SpeculativeLoadHardeningPassPass(PR); 82*0b57cec5SDimitry Andric initializeX86FlagsCopyLoweringPassPass(PR); 83*0b57cec5SDimitry Andric initializeX86CondBrFoldingPassPass(PR); 84*0b57cec5SDimitry Andric } 85*0b57cec5SDimitry Andric 86*0b57cec5SDimitry Andric static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) { 87*0b57cec5SDimitry Andric if (TT.isOSBinFormatMachO()) { 88*0b57cec5SDimitry Andric if (TT.getArch() == Triple::x86_64) 89*0b57cec5SDimitry Andric return llvm::make_unique<X86_64MachoTargetObjectFile>(); 90*0b57cec5SDimitry Andric return llvm::make_unique<TargetLoweringObjectFileMachO>(); 91*0b57cec5SDimitry Andric } 92*0b57cec5SDimitry Andric 93*0b57cec5SDimitry Andric if (TT.isOSFreeBSD()) 94*0b57cec5SDimitry Andric return llvm::make_unique<X86FreeBSDTargetObjectFile>(); 95*0b57cec5SDimitry Andric if (TT.isOSLinux() || TT.isOSNaCl() || TT.isOSIAMCU()) 96*0b57cec5SDimitry Andric return llvm::make_unique<X86LinuxNaClTargetObjectFile>(); 97*0b57cec5SDimitry Andric if (TT.isOSSolaris()) 98*0b57cec5SDimitry Andric return llvm::make_unique<X86SolarisTargetObjectFile>(); 99*0b57cec5SDimitry Andric if (TT.isOSFuchsia()) 100*0b57cec5SDimitry Andric return llvm::make_unique<X86FuchsiaTargetObjectFile>(); 101*0b57cec5SDimitry Andric if (TT.isOSBinFormatELF()) 102*0b57cec5SDimitry Andric return llvm::make_unique<X86ELFTargetObjectFile>(); 103*0b57cec5SDimitry Andric if (TT.isOSBinFormatCOFF()) 104*0b57cec5SDimitry Andric return llvm::make_unique<TargetLoweringObjectFileCOFF>(); 105*0b57cec5SDimitry Andric llvm_unreachable("unknown subtarget type"); 106*0b57cec5SDimitry Andric } 107*0b57cec5SDimitry Andric 108*0b57cec5SDimitry Andric static std::string computeDataLayout(const Triple &TT) { 109*0b57cec5SDimitry Andric // X86 is little endian 110*0b57cec5SDimitry Andric std::string Ret = "e"; 111*0b57cec5SDimitry Andric 112*0b57cec5SDimitry Andric Ret += DataLayout::getManglingComponent(TT); 113*0b57cec5SDimitry Andric // X86 and x32 have 32 bit pointers. 114*0b57cec5SDimitry Andric if ((TT.isArch64Bit() && 115*0b57cec5SDimitry Andric (TT.getEnvironment() == Triple::GNUX32 || TT.isOSNaCl())) || 116*0b57cec5SDimitry Andric !TT.isArch64Bit()) 117*0b57cec5SDimitry Andric Ret += "-p:32:32"; 118*0b57cec5SDimitry Andric 119*0b57cec5SDimitry Andric // Some ABIs align 64 bit integers and doubles to 64 bits, others to 32. 120*0b57cec5SDimitry Andric if (TT.isArch64Bit() || TT.isOSWindows() || TT.isOSNaCl()) 121*0b57cec5SDimitry Andric Ret += "-i64:64"; 122*0b57cec5SDimitry Andric else if (TT.isOSIAMCU()) 123*0b57cec5SDimitry Andric Ret += "-i64:32-f64:32"; 124*0b57cec5SDimitry Andric else 125*0b57cec5SDimitry Andric Ret += "-f64:32:64"; 126*0b57cec5SDimitry Andric 127*0b57cec5SDimitry Andric // Some ABIs align long double to 128 bits, others to 32. 128*0b57cec5SDimitry Andric if (TT.isOSNaCl() || TT.isOSIAMCU()) 129*0b57cec5SDimitry Andric ; // No f80 130*0b57cec5SDimitry Andric else if (TT.isArch64Bit() || TT.isOSDarwin()) 131*0b57cec5SDimitry Andric Ret += "-f80:128"; 132*0b57cec5SDimitry Andric else 133*0b57cec5SDimitry Andric Ret += "-f80:32"; 134*0b57cec5SDimitry Andric 135*0b57cec5SDimitry Andric if (TT.isOSIAMCU()) 136*0b57cec5SDimitry Andric Ret += "-f128:32"; 137*0b57cec5SDimitry Andric 138*0b57cec5SDimitry Andric // The registers can hold 8, 16, 32 or, in x86-64, 64 bits. 139*0b57cec5SDimitry Andric if (TT.isArch64Bit()) 140*0b57cec5SDimitry Andric Ret += "-n8:16:32:64"; 141*0b57cec5SDimitry Andric else 142*0b57cec5SDimitry Andric Ret += "-n8:16:32"; 143*0b57cec5SDimitry Andric 144*0b57cec5SDimitry Andric // The stack is aligned to 32 bits on some ABIs and 128 bits on others. 145*0b57cec5SDimitry Andric if ((!TT.isArch64Bit() && TT.isOSWindows()) || TT.isOSIAMCU()) 146*0b57cec5SDimitry Andric Ret += "-a:0:32-S32"; 147*0b57cec5SDimitry Andric else 148*0b57cec5SDimitry Andric Ret += "-S128"; 149*0b57cec5SDimitry Andric 150*0b57cec5SDimitry Andric return Ret; 151*0b57cec5SDimitry Andric } 152*0b57cec5SDimitry Andric 153*0b57cec5SDimitry Andric static Reloc::Model getEffectiveRelocModel(const Triple &TT, 154*0b57cec5SDimitry Andric bool JIT, 155*0b57cec5SDimitry Andric Optional<Reloc::Model> RM) { 156*0b57cec5SDimitry Andric bool is64Bit = TT.getArch() == Triple::x86_64; 157*0b57cec5SDimitry Andric if (!RM.hasValue()) { 158*0b57cec5SDimitry Andric // JIT codegen should use static relocations by default, since it's 159*0b57cec5SDimitry Andric // typically executed in process and not relocatable. 160*0b57cec5SDimitry Andric if (JIT) 161*0b57cec5SDimitry Andric return Reloc::Static; 162*0b57cec5SDimitry Andric 163*0b57cec5SDimitry Andric // Darwin defaults to PIC in 64 bit mode and dynamic-no-pic in 32 bit mode. 164*0b57cec5SDimitry Andric // Win64 requires rip-rel addressing, thus we force it to PIC. Otherwise we 165*0b57cec5SDimitry Andric // use static relocation model by default. 166*0b57cec5SDimitry Andric if (TT.isOSDarwin()) { 167*0b57cec5SDimitry Andric if (is64Bit) 168*0b57cec5SDimitry Andric return Reloc::PIC_; 169*0b57cec5SDimitry Andric return Reloc::DynamicNoPIC; 170*0b57cec5SDimitry Andric } 171*0b57cec5SDimitry Andric if (TT.isOSWindows() && is64Bit) 172*0b57cec5SDimitry Andric return Reloc::PIC_; 173*0b57cec5SDimitry Andric return Reloc::Static; 174*0b57cec5SDimitry Andric } 175*0b57cec5SDimitry Andric 176*0b57cec5SDimitry Andric // ELF and X86-64 don't have a distinct DynamicNoPIC model. DynamicNoPIC 177*0b57cec5SDimitry Andric // is defined as a model for code which may be used in static or dynamic 178*0b57cec5SDimitry Andric // executables but not necessarily a shared library. On X86-32 we just 179*0b57cec5SDimitry Andric // compile in -static mode, in x86-64 we use PIC. 180*0b57cec5SDimitry Andric if (*RM == Reloc::DynamicNoPIC) { 181*0b57cec5SDimitry Andric if (is64Bit) 182*0b57cec5SDimitry Andric return Reloc::PIC_; 183*0b57cec5SDimitry Andric if (!TT.isOSDarwin()) 184*0b57cec5SDimitry Andric return Reloc::Static; 185*0b57cec5SDimitry Andric } 186*0b57cec5SDimitry Andric 187*0b57cec5SDimitry Andric // If we are on Darwin, disallow static relocation model in X86-64 mode, since 188*0b57cec5SDimitry Andric // the Mach-O file format doesn't support it. 189*0b57cec5SDimitry Andric if (*RM == Reloc::Static && TT.isOSDarwin() && is64Bit) 190*0b57cec5SDimitry Andric return Reloc::PIC_; 191*0b57cec5SDimitry Andric 192*0b57cec5SDimitry Andric return *RM; 193*0b57cec5SDimitry Andric } 194*0b57cec5SDimitry Andric 195*0b57cec5SDimitry Andric static CodeModel::Model getEffectiveX86CodeModel(Optional<CodeModel::Model> CM, 196*0b57cec5SDimitry Andric bool JIT, bool Is64Bit) { 197*0b57cec5SDimitry Andric if (CM) { 198*0b57cec5SDimitry Andric if (*CM == CodeModel::Tiny) 199*0b57cec5SDimitry Andric report_fatal_error("Target does not support the tiny CodeModel", false); 200*0b57cec5SDimitry Andric return *CM; 201*0b57cec5SDimitry Andric } 202*0b57cec5SDimitry Andric if (JIT) 203*0b57cec5SDimitry Andric return Is64Bit ? CodeModel::Large : CodeModel::Small; 204*0b57cec5SDimitry Andric return CodeModel::Small; 205*0b57cec5SDimitry Andric } 206*0b57cec5SDimitry Andric 207*0b57cec5SDimitry Andric /// Create an X86 target. 208*0b57cec5SDimitry Andric /// 209*0b57cec5SDimitry Andric X86TargetMachine::X86TargetMachine(const Target &T, const Triple &TT, 210*0b57cec5SDimitry Andric StringRef CPU, StringRef FS, 211*0b57cec5SDimitry Andric const TargetOptions &Options, 212*0b57cec5SDimitry Andric Optional<Reloc::Model> RM, 213*0b57cec5SDimitry Andric Optional<CodeModel::Model> CM, 214*0b57cec5SDimitry Andric CodeGenOpt::Level OL, bool JIT) 215*0b57cec5SDimitry Andric : LLVMTargetMachine( 216*0b57cec5SDimitry Andric T, computeDataLayout(TT), TT, CPU, FS, Options, 217*0b57cec5SDimitry Andric getEffectiveRelocModel(TT, JIT, RM), 218*0b57cec5SDimitry Andric getEffectiveX86CodeModel(CM, JIT, TT.getArch() == Triple::x86_64), 219*0b57cec5SDimitry Andric OL), 220*0b57cec5SDimitry Andric TLOF(createTLOF(getTargetTriple())) { 221*0b57cec5SDimitry Andric // Windows stack unwinder gets confused when execution flow "falls through" 222*0b57cec5SDimitry Andric // after a call to 'noreturn' function. 223*0b57cec5SDimitry Andric // To prevent that, we emit a trap for 'unreachable' IR instructions. 224*0b57cec5SDimitry Andric // (which on X86, happens to be the 'ud2' instruction) 225*0b57cec5SDimitry Andric // On PS4, the "return address" of a 'noreturn' call must still be within 226*0b57cec5SDimitry Andric // the calling function, and TrapUnreachable is an easy way to get that. 227*0b57cec5SDimitry Andric // The check here for 64-bit windows is a bit icky, but as we're unlikely 228*0b57cec5SDimitry Andric // to ever want to mix 32 and 64-bit windows code in a single module 229*0b57cec5SDimitry Andric // this should be fine. 230*0b57cec5SDimitry Andric if ((TT.isOSWindows() && TT.getArch() == Triple::x86_64) || TT.isPS4() || 231*0b57cec5SDimitry Andric TT.isOSBinFormatMachO()) { 232*0b57cec5SDimitry Andric this->Options.TrapUnreachable = true; 233*0b57cec5SDimitry Andric this->Options.NoTrapAfterNoreturn = TT.isOSBinFormatMachO(); 234*0b57cec5SDimitry Andric } 235*0b57cec5SDimitry Andric 236*0b57cec5SDimitry Andric // Outlining is available for x86-64. 237*0b57cec5SDimitry Andric if (TT.getArch() == Triple::x86_64) 238*0b57cec5SDimitry Andric setMachineOutliner(true); 239*0b57cec5SDimitry Andric 240*0b57cec5SDimitry Andric initAsmInfo(); 241*0b57cec5SDimitry Andric } 242*0b57cec5SDimitry Andric 243*0b57cec5SDimitry Andric X86TargetMachine::~X86TargetMachine() = default; 244*0b57cec5SDimitry Andric 245*0b57cec5SDimitry Andric const X86Subtarget * 246*0b57cec5SDimitry Andric X86TargetMachine::getSubtargetImpl(const Function &F) const { 247*0b57cec5SDimitry Andric Attribute CPUAttr = F.getFnAttribute("target-cpu"); 248*0b57cec5SDimitry Andric Attribute FSAttr = F.getFnAttribute("target-features"); 249*0b57cec5SDimitry Andric 250*0b57cec5SDimitry Andric StringRef CPU = !CPUAttr.hasAttribute(Attribute::None) 251*0b57cec5SDimitry Andric ? CPUAttr.getValueAsString() 252*0b57cec5SDimitry Andric : (StringRef)TargetCPU; 253*0b57cec5SDimitry Andric StringRef FS = !FSAttr.hasAttribute(Attribute::None) 254*0b57cec5SDimitry Andric ? FSAttr.getValueAsString() 255*0b57cec5SDimitry Andric : (StringRef)TargetFS; 256*0b57cec5SDimitry Andric 257*0b57cec5SDimitry Andric SmallString<512> Key; 258*0b57cec5SDimitry Andric Key.reserve(CPU.size() + FS.size()); 259*0b57cec5SDimitry Andric Key += CPU; 260*0b57cec5SDimitry Andric Key += FS; 261*0b57cec5SDimitry Andric 262*0b57cec5SDimitry Andric // FIXME: This is related to the code below to reset the target options, 263*0b57cec5SDimitry Andric // we need to know whether or not the soft float flag is set on the 264*0b57cec5SDimitry Andric // function before we can generate a subtarget. We also need to use 265*0b57cec5SDimitry Andric // it as a key for the subtarget since that can be the only difference 266*0b57cec5SDimitry Andric // between two functions. 267*0b57cec5SDimitry Andric bool SoftFloat = 268*0b57cec5SDimitry Andric F.getFnAttribute("use-soft-float").getValueAsString() == "true"; 269*0b57cec5SDimitry Andric // If the soft float attribute is set on the function turn on the soft float 270*0b57cec5SDimitry Andric // subtarget feature. 271*0b57cec5SDimitry Andric if (SoftFloat) 272*0b57cec5SDimitry Andric Key += FS.empty() ? "+soft-float" : ",+soft-float"; 273*0b57cec5SDimitry Andric 274*0b57cec5SDimitry Andric // Keep track of the key width after all features are added so we can extract 275*0b57cec5SDimitry Andric // the feature string out later. 276*0b57cec5SDimitry Andric unsigned CPUFSWidth = Key.size(); 277*0b57cec5SDimitry Andric 278*0b57cec5SDimitry Andric // Extract prefer-vector-width attribute. 279*0b57cec5SDimitry Andric unsigned PreferVectorWidthOverride = 0; 280*0b57cec5SDimitry Andric if (F.hasFnAttribute("prefer-vector-width")) { 281*0b57cec5SDimitry Andric StringRef Val = F.getFnAttribute("prefer-vector-width").getValueAsString(); 282*0b57cec5SDimitry Andric unsigned Width; 283*0b57cec5SDimitry Andric if (!Val.getAsInteger(0, Width)) { 284*0b57cec5SDimitry Andric Key += ",prefer-vector-width="; 285*0b57cec5SDimitry Andric Key += Val; 286*0b57cec5SDimitry Andric PreferVectorWidthOverride = Width; 287*0b57cec5SDimitry Andric } 288*0b57cec5SDimitry Andric } 289*0b57cec5SDimitry Andric 290*0b57cec5SDimitry Andric // Extract min-legal-vector-width attribute. 291*0b57cec5SDimitry Andric unsigned RequiredVectorWidth = UINT32_MAX; 292*0b57cec5SDimitry Andric if (F.hasFnAttribute("min-legal-vector-width")) { 293*0b57cec5SDimitry Andric StringRef Val = 294*0b57cec5SDimitry Andric F.getFnAttribute("min-legal-vector-width").getValueAsString(); 295*0b57cec5SDimitry Andric unsigned Width; 296*0b57cec5SDimitry Andric if (!Val.getAsInteger(0, Width)) { 297*0b57cec5SDimitry Andric Key += ",min-legal-vector-width="; 298*0b57cec5SDimitry Andric Key += Val; 299*0b57cec5SDimitry Andric RequiredVectorWidth = Width; 300*0b57cec5SDimitry Andric } 301*0b57cec5SDimitry Andric } 302*0b57cec5SDimitry Andric 303*0b57cec5SDimitry Andric // Extracted here so that we make sure there is backing for the StringRef. If 304*0b57cec5SDimitry Andric // we assigned earlier, its possible the SmallString reallocated leaving a 305*0b57cec5SDimitry Andric // dangling StringRef. 306*0b57cec5SDimitry Andric FS = Key.slice(CPU.size(), CPUFSWidth); 307*0b57cec5SDimitry Andric 308*0b57cec5SDimitry Andric auto &I = SubtargetMap[Key]; 309*0b57cec5SDimitry Andric if (!I) { 310*0b57cec5SDimitry Andric // This needs to be done before we create a new subtarget since any 311*0b57cec5SDimitry Andric // creation will depend on the TM and the code generation flags on the 312*0b57cec5SDimitry Andric // function that reside in TargetOptions. 313*0b57cec5SDimitry Andric resetTargetOptions(F); 314*0b57cec5SDimitry Andric I = llvm::make_unique<X86Subtarget>(TargetTriple, CPU, FS, *this, 315*0b57cec5SDimitry Andric Options.StackAlignmentOverride, 316*0b57cec5SDimitry Andric PreferVectorWidthOverride, 317*0b57cec5SDimitry Andric RequiredVectorWidth); 318*0b57cec5SDimitry Andric } 319*0b57cec5SDimitry Andric return I.get(); 320*0b57cec5SDimitry Andric } 321*0b57cec5SDimitry Andric 322*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 323*0b57cec5SDimitry Andric // Command line options for x86 324*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 325*0b57cec5SDimitry Andric static cl::opt<bool> 326*0b57cec5SDimitry Andric UseVZeroUpper("x86-use-vzeroupper", cl::Hidden, 327*0b57cec5SDimitry Andric cl::desc("Minimize AVX to SSE transition penalty"), 328*0b57cec5SDimitry Andric cl::init(true)); 329*0b57cec5SDimitry Andric 330*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 331*0b57cec5SDimitry Andric // X86 TTI query. 332*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 333*0b57cec5SDimitry Andric 334*0b57cec5SDimitry Andric TargetTransformInfo 335*0b57cec5SDimitry Andric X86TargetMachine::getTargetTransformInfo(const Function &F) { 336*0b57cec5SDimitry Andric return TargetTransformInfo(X86TTIImpl(this, F)); 337*0b57cec5SDimitry Andric } 338*0b57cec5SDimitry Andric 339*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 340*0b57cec5SDimitry Andric // Pass Pipeline Configuration 341*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 342*0b57cec5SDimitry Andric 343*0b57cec5SDimitry Andric namespace { 344*0b57cec5SDimitry Andric 345*0b57cec5SDimitry Andric /// X86 Code Generator Pass Configuration Options. 346*0b57cec5SDimitry Andric class X86PassConfig : public TargetPassConfig { 347*0b57cec5SDimitry Andric public: 348*0b57cec5SDimitry Andric X86PassConfig(X86TargetMachine &TM, PassManagerBase &PM) 349*0b57cec5SDimitry Andric : TargetPassConfig(TM, PM) {} 350*0b57cec5SDimitry Andric 351*0b57cec5SDimitry Andric X86TargetMachine &getX86TargetMachine() const { 352*0b57cec5SDimitry Andric return getTM<X86TargetMachine>(); 353*0b57cec5SDimitry Andric } 354*0b57cec5SDimitry Andric 355*0b57cec5SDimitry Andric ScheduleDAGInstrs * 356*0b57cec5SDimitry Andric createMachineScheduler(MachineSchedContext *C) const override { 357*0b57cec5SDimitry Andric ScheduleDAGMILive *DAG = createGenericSchedLive(C); 358*0b57cec5SDimitry Andric DAG->addMutation(createX86MacroFusionDAGMutation()); 359*0b57cec5SDimitry Andric return DAG; 360*0b57cec5SDimitry Andric } 361*0b57cec5SDimitry Andric 362*0b57cec5SDimitry Andric ScheduleDAGInstrs * 363*0b57cec5SDimitry Andric createPostMachineScheduler(MachineSchedContext *C) const override { 364*0b57cec5SDimitry Andric ScheduleDAGMI *DAG = createGenericSchedPostRA(C); 365*0b57cec5SDimitry Andric DAG->addMutation(createX86MacroFusionDAGMutation()); 366*0b57cec5SDimitry Andric return DAG; 367*0b57cec5SDimitry Andric } 368*0b57cec5SDimitry Andric 369*0b57cec5SDimitry Andric void addIRPasses() override; 370*0b57cec5SDimitry Andric bool addInstSelector() override; 371*0b57cec5SDimitry Andric bool addIRTranslator() override; 372*0b57cec5SDimitry Andric bool addLegalizeMachineIR() override; 373*0b57cec5SDimitry Andric bool addRegBankSelect() override; 374*0b57cec5SDimitry Andric bool addGlobalInstructionSelect() override; 375*0b57cec5SDimitry Andric bool addILPOpts() override; 376*0b57cec5SDimitry Andric bool addPreISel() override; 377*0b57cec5SDimitry Andric void addMachineSSAOptimization() override; 378*0b57cec5SDimitry Andric void addPreRegAlloc() override; 379*0b57cec5SDimitry Andric void addPostRegAlloc() override; 380*0b57cec5SDimitry Andric void addPreEmitPass() override; 381*0b57cec5SDimitry Andric void addPreEmitPass2() override; 382*0b57cec5SDimitry Andric void addPreSched2() override; 383*0b57cec5SDimitry Andric 384*0b57cec5SDimitry Andric std::unique_ptr<CSEConfigBase> getCSEConfig() const override; 385*0b57cec5SDimitry Andric }; 386*0b57cec5SDimitry Andric 387*0b57cec5SDimitry Andric class X86ExecutionDomainFix : public ExecutionDomainFix { 388*0b57cec5SDimitry Andric public: 389*0b57cec5SDimitry Andric static char ID; 390*0b57cec5SDimitry Andric X86ExecutionDomainFix() : ExecutionDomainFix(ID, X86::VR128XRegClass) {} 391*0b57cec5SDimitry Andric StringRef getPassName() const override { 392*0b57cec5SDimitry Andric return "X86 Execution Dependency Fix"; 393*0b57cec5SDimitry Andric } 394*0b57cec5SDimitry Andric }; 395*0b57cec5SDimitry Andric char X86ExecutionDomainFix::ID; 396*0b57cec5SDimitry Andric 397*0b57cec5SDimitry Andric } // end anonymous namespace 398*0b57cec5SDimitry Andric 399*0b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(X86ExecutionDomainFix, "x86-execution-domain-fix", 400*0b57cec5SDimitry Andric "X86 Execution Domain Fix", false, false) 401*0b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(ReachingDefAnalysis) 402*0b57cec5SDimitry Andric INITIALIZE_PASS_END(X86ExecutionDomainFix, "x86-execution-domain-fix", 403*0b57cec5SDimitry Andric "X86 Execution Domain Fix", false, false) 404*0b57cec5SDimitry Andric 405*0b57cec5SDimitry Andric TargetPassConfig *X86TargetMachine::createPassConfig(PassManagerBase &PM) { 406*0b57cec5SDimitry Andric return new X86PassConfig(*this, PM); 407*0b57cec5SDimitry Andric } 408*0b57cec5SDimitry Andric 409*0b57cec5SDimitry Andric void X86PassConfig::addIRPasses() { 410*0b57cec5SDimitry Andric addPass(createAtomicExpandPass()); 411*0b57cec5SDimitry Andric 412*0b57cec5SDimitry Andric TargetPassConfig::addIRPasses(); 413*0b57cec5SDimitry Andric 414*0b57cec5SDimitry Andric if (TM->getOptLevel() != CodeGenOpt::None) 415*0b57cec5SDimitry Andric addPass(createInterleavedAccessPass()); 416*0b57cec5SDimitry Andric 417*0b57cec5SDimitry Andric // Add passes that handle indirect branch removal and insertion of a retpoline 418*0b57cec5SDimitry Andric // thunk. These will be a no-op unless a function subtarget has the retpoline 419*0b57cec5SDimitry Andric // feature enabled. 420*0b57cec5SDimitry Andric addPass(createIndirectBrExpandPass()); 421*0b57cec5SDimitry Andric } 422*0b57cec5SDimitry Andric 423*0b57cec5SDimitry Andric bool X86PassConfig::addInstSelector() { 424*0b57cec5SDimitry Andric // Install an instruction selector. 425*0b57cec5SDimitry Andric addPass(createX86ISelDag(getX86TargetMachine(), getOptLevel())); 426*0b57cec5SDimitry Andric 427*0b57cec5SDimitry Andric // For ELF, cleanup any local-dynamic TLS accesses. 428*0b57cec5SDimitry Andric if (TM->getTargetTriple().isOSBinFormatELF() && 429*0b57cec5SDimitry Andric getOptLevel() != CodeGenOpt::None) 430*0b57cec5SDimitry Andric addPass(createCleanupLocalDynamicTLSPass()); 431*0b57cec5SDimitry Andric 432*0b57cec5SDimitry Andric addPass(createX86GlobalBaseRegPass()); 433*0b57cec5SDimitry Andric return false; 434*0b57cec5SDimitry Andric } 435*0b57cec5SDimitry Andric 436*0b57cec5SDimitry Andric bool X86PassConfig::addIRTranslator() { 437*0b57cec5SDimitry Andric addPass(new IRTranslator()); 438*0b57cec5SDimitry Andric return false; 439*0b57cec5SDimitry Andric } 440*0b57cec5SDimitry Andric 441*0b57cec5SDimitry Andric bool X86PassConfig::addLegalizeMachineIR() { 442*0b57cec5SDimitry Andric addPass(new Legalizer()); 443*0b57cec5SDimitry Andric return false; 444*0b57cec5SDimitry Andric } 445*0b57cec5SDimitry Andric 446*0b57cec5SDimitry Andric bool X86PassConfig::addRegBankSelect() { 447*0b57cec5SDimitry Andric addPass(new RegBankSelect()); 448*0b57cec5SDimitry Andric return false; 449*0b57cec5SDimitry Andric } 450*0b57cec5SDimitry Andric 451*0b57cec5SDimitry Andric bool X86PassConfig::addGlobalInstructionSelect() { 452*0b57cec5SDimitry Andric addPass(new InstructionSelect()); 453*0b57cec5SDimitry Andric return false; 454*0b57cec5SDimitry Andric } 455*0b57cec5SDimitry Andric 456*0b57cec5SDimitry Andric bool X86PassConfig::addILPOpts() { 457*0b57cec5SDimitry Andric if (EnableCondBrFoldingPass) 458*0b57cec5SDimitry Andric addPass(createX86CondBrFolding()); 459*0b57cec5SDimitry Andric addPass(&EarlyIfConverterID); 460*0b57cec5SDimitry Andric if (EnableMachineCombinerPass) 461*0b57cec5SDimitry Andric addPass(&MachineCombinerID); 462*0b57cec5SDimitry Andric addPass(createX86CmovConverterPass()); 463*0b57cec5SDimitry Andric return true; 464*0b57cec5SDimitry Andric } 465*0b57cec5SDimitry Andric 466*0b57cec5SDimitry Andric bool X86PassConfig::addPreISel() { 467*0b57cec5SDimitry Andric // Only add this pass for 32-bit x86 Windows. 468*0b57cec5SDimitry Andric const Triple &TT = TM->getTargetTriple(); 469*0b57cec5SDimitry Andric if (TT.isOSWindows() && TT.getArch() == Triple::x86) 470*0b57cec5SDimitry Andric addPass(createX86WinEHStatePass()); 471*0b57cec5SDimitry Andric return true; 472*0b57cec5SDimitry Andric } 473*0b57cec5SDimitry Andric 474*0b57cec5SDimitry Andric void X86PassConfig::addPreRegAlloc() { 475*0b57cec5SDimitry Andric if (getOptLevel() != CodeGenOpt::None) { 476*0b57cec5SDimitry Andric addPass(&LiveRangeShrinkID); 477*0b57cec5SDimitry Andric addPass(createX86FixupSetCC()); 478*0b57cec5SDimitry Andric addPass(createX86OptimizeLEAs()); 479*0b57cec5SDimitry Andric addPass(createX86CallFrameOptimization()); 480*0b57cec5SDimitry Andric addPass(createX86AvoidStoreForwardingBlocks()); 481*0b57cec5SDimitry Andric } 482*0b57cec5SDimitry Andric 483*0b57cec5SDimitry Andric addPass(createX86SpeculativeLoadHardeningPass()); 484*0b57cec5SDimitry Andric addPass(createX86FlagsCopyLoweringPass()); 485*0b57cec5SDimitry Andric addPass(createX86WinAllocaExpander()); 486*0b57cec5SDimitry Andric } 487*0b57cec5SDimitry Andric void X86PassConfig::addMachineSSAOptimization() { 488*0b57cec5SDimitry Andric addPass(createX86DomainReassignmentPass()); 489*0b57cec5SDimitry Andric TargetPassConfig::addMachineSSAOptimization(); 490*0b57cec5SDimitry Andric } 491*0b57cec5SDimitry Andric 492*0b57cec5SDimitry Andric void X86PassConfig::addPostRegAlloc() { 493*0b57cec5SDimitry Andric addPass(createX86FloatingPointStackifierPass()); 494*0b57cec5SDimitry Andric } 495*0b57cec5SDimitry Andric 496*0b57cec5SDimitry Andric void X86PassConfig::addPreSched2() { addPass(createX86ExpandPseudoPass()); } 497*0b57cec5SDimitry Andric 498*0b57cec5SDimitry Andric void X86PassConfig::addPreEmitPass() { 499*0b57cec5SDimitry Andric if (getOptLevel() != CodeGenOpt::None) { 500*0b57cec5SDimitry Andric addPass(new X86ExecutionDomainFix()); 501*0b57cec5SDimitry Andric addPass(createBreakFalseDeps()); 502*0b57cec5SDimitry Andric } 503*0b57cec5SDimitry Andric 504*0b57cec5SDimitry Andric addPass(createX86IndirectBranchTrackingPass()); 505*0b57cec5SDimitry Andric 506*0b57cec5SDimitry Andric if (UseVZeroUpper) 507*0b57cec5SDimitry Andric addPass(createX86IssueVZeroUpperPass()); 508*0b57cec5SDimitry Andric 509*0b57cec5SDimitry Andric if (getOptLevel() != CodeGenOpt::None) { 510*0b57cec5SDimitry Andric addPass(createX86FixupBWInsts()); 511*0b57cec5SDimitry Andric addPass(createX86PadShortFunctions()); 512*0b57cec5SDimitry Andric addPass(createX86FixupLEAs()); 513*0b57cec5SDimitry Andric addPass(createX86EvexToVexInsts()); 514*0b57cec5SDimitry Andric } 515*0b57cec5SDimitry Andric addPass(createX86DiscriminateMemOpsPass()); 516*0b57cec5SDimitry Andric addPass(createX86InsertPrefetchPass()); 517*0b57cec5SDimitry Andric } 518*0b57cec5SDimitry Andric 519*0b57cec5SDimitry Andric void X86PassConfig::addPreEmitPass2() { 520*0b57cec5SDimitry Andric addPass(createX86RetpolineThunksPass()); 521*0b57cec5SDimitry Andric // Verify basic block incoming and outgoing cfa offset and register values and 522*0b57cec5SDimitry Andric // correct CFA calculation rule where needed by inserting appropriate CFI 523*0b57cec5SDimitry Andric // instructions. 524*0b57cec5SDimitry Andric const Triple &TT = TM->getTargetTriple(); 525*0b57cec5SDimitry Andric const MCAsmInfo *MAI = TM->getMCAsmInfo(); 526*0b57cec5SDimitry Andric if (!TT.isOSDarwin() && 527*0b57cec5SDimitry Andric (!TT.isOSWindows() || 528*0b57cec5SDimitry Andric MAI->getExceptionHandlingType() == ExceptionHandling::DwarfCFI)) 529*0b57cec5SDimitry Andric addPass(createCFIInstrInserter()); 530*0b57cec5SDimitry Andric } 531*0b57cec5SDimitry Andric 532*0b57cec5SDimitry Andric std::unique_ptr<CSEConfigBase> X86PassConfig::getCSEConfig() const { 533*0b57cec5SDimitry Andric return getStandardCSEConfigForOpt(TM->getOptLevel()); 534*0b57cec5SDimitry Andric } 535