xref: /freebsd/contrib/llvm-project/llvm/lib/Target/X86/X86TargetMachine.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
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