LLVM 23.0.0git
X86Subtarget.h
Go to the documentation of this file.
1//===-- X86Subtarget.h - Define Subtarget for the X86 ----------*- C++ -*--===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file declares the X86 specific subclass of TargetSubtargetInfo.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_LIB_TARGET_X86_X86SUBTARGET_H
14#define LLVM_LIB_TARGET_X86_X86SUBTARGET_H
15
16#include "X86FrameLowering.h"
17#include "X86ISelLowering.h"
18#include "X86InstrInfo.h"
19#include "X86SelectionDAGInfo.h"
20#include "llvm/ADT/BitVector.h"
22#include "llvm/IR/CallingConv.h"
24#include <climits>
25#include <memory>
26
27#define GET_SUBTARGETINFO_HEADER
28#include "X86GenSubtargetInfo.inc"
29
30namespace llvm {
31
32class CallLowering;
33class GlobalValue;
34class InstructionSelector;
35class LegalizerInfo;
36class RegisterBankInfo;
37class StringRef;
38class TargetMachine;
39
40/// The X86 backend supports a number of different styles of PIC.
41///
42namespace PICStyles {
43
44enum class Style {
45 StubPIC, // Used on i386-darwin in pic mode.
46 GOT, // Used on 32 bit elf on when in pic mode.
47 RIPRel, // Used on X86-64 when in pic mode.
48 None // Set when not in pic mode.
49};
50
51} // end namespace PICStyles
52
53class X86Subtarget final : public X86GenSubtargetInfo {
54 enum X86SSEEnum {
55 NoSSE, SSE1, SSE2, SSE3, SSSE3, SSE41, SSE42, AVX, AVX2, AVX512
56 };
57
58 /// Which PIC style to use
59 PICStyles::Style PICStyle;
60
61 const TargetMachine &TM;
62
63 /// SSE1, SSE2, SSE3, SSSE3, SSE41, SSE42, or none supported.
64 X86SSEEnum X86SSELevel = NoSSE;
65
66#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \
67 bool ATTRIBUTE = DEFAULT;
68#include "X86GenSubtargetInfo.inc"
69 /// ReservedRReg R#i is not available as a general purpose register.
70 BitVector ReservedRReg;
71
72 /// The minimum alignment known to hold of the stack frame on
73 /// entry to the function and which must be maintained by every function.
74 Align stackAlignment = Align(4);
75
76 Align TileConfigAlignment = Align(4);
77
78 /// Max. memset / memcpy size that is turned into rep/movs, rep/stos ops.
79 ///
80 // FIXME: this is a known good value for Yonah. How about others?
81 unsigned MaxInlineSizeThreshold = 128;
82
83 /// What processor and OS we're targeting.
84 Triple TargetTriple;
85
86 /// GlobalISel related APIs.
87 std::unique_ptr<CallLowering> CallLoweringInfo;
88 std::unique_ptr<LegalizerInfo> Legalizer;
89 std::unique_ptr<RegisterBankInfo> RegBankInfo;
90 std::unique_ptr<InstructionSelector> InstSelector;
91
92 /// Override the stack alignment.
93 MaybeAlign StackAlignOverride;
94
95 /// Preferred vector width from function attribute.
96 unsigned PreferVectorWidthOverride;
97
98 /// Resolved preferred vector width from function attribute and subtarget
99 /// features.
100 unsigned PreferVectorWidth = UINT32_MAX;
101
102 /// Required vector width from function attribute.
103 unsigned RequiredVectorWidth;
104
105 X86SelectionDAGInfo TSInfo;
106 // Ordering here is important. X86InstrInfo initializes X86RegisterInfo which
107 // X86TargetLowering needs.
108 X86InstrInfo InstrInfo;
109 X86TargetLowering TLInfo;
110 X86FrameLowering FrameLowering;
111
112public:
113 /// This constructor initializes the data members to match that
114 /// of the specified triple.
115 ///
116 X86Subtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU, StringRef FS,
117 const X86TargetMachine &TM, MaybeAlign StackAlignOverride,
118 unsigned PreferVectorWidthOverride,
119 unsigned RequiredVectorWidth);
120 ~X86Subtarget() override;
121
122 const X86TargetLowering *getTargetLowering() const override {
123 return &TLInfo;
124 }
125
126 const X86InstrInfo *getInstrInfo() const override { return &InstrInfo; }
127
128 const X86FrameLowering *getFrameLowering() const override {
129 return &FrameLowering;
130 }
131
132 const X86SelectionDAGInfo *getSelectionDAGInfo() const override {
133 return &TSInfo;
134 }
135
136 const X86RegisterInfo *getRegisterInfo() const override {
137 return &getInstrInfo()->getRegisterInfo();
138 }
139
140 unsigned getTileConfigSize() const { return 64; }
141 Align getTileConfigAlignment() const { return TileConfigAlignment; }
142
143 /// Returns the minimum alignment known to hold of the
144 /// stack frame on entry to the function and which must be maintained by every
145 /// function for this subtarget.
146 Align getStackAlignment() const { return stackAlignment; }
147
148 /// Returns the maximum memset / memcpy size
149 /// that still makes it profitable to inline the call.
150 unsigned getMaxInlineSizeThreshold() const { return MaxInlineSizeThreshold; }
151
152 /// ParseSubtargetFeatures - Parses features string setting specified
153 /// subtarget options. Definition of function is auto generated by tblgen.
155
156 /// Methods used by Global ISel
157 const CallLowering *getCallLowering() const override;
159 const LegalizerInfo *getLegalizerInfo() const override;
160 const RegisterBankInfo *getRegBankInfo() const override;
161
162 bool isRegisterReservedByUser(Register i) const override {
163 return ReservedRReg[i.id()];
164 }
165
166private:
167 /// Initialize the full set of dependencies so we can use an initializer
168 /// list for X86Subtarget.
169 X86Subtarget &initializeSubtargetDependencies(StringRef CPU,
170 StringRef TuneCPU,
171 StringRef FS);
172 void initSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
173
174public:
175
176#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \
177 bool GETTER() const { return ATTRIBUTE; }
178#include "X86GenSubtargetInfo.inc"
179
180 /// Is this x86_64 with the ILP32 programming model (x32 ABI)?
181 bool isTarget64BitILP32() const { return Is64Bit && IsX32; }
182
183 /// Is this x86_64 with the LP64 programming model (standard AMD64, no x32)?
184 bool isTarget64BitLP64() const { return Is64Bit && !IsX32; }
185
186 PICStyles::Style getPICStyle() const { return PICStyle; }
187 void setPICStyle(PICStyles::Style Style) { PICStyle = Style; }
188
189 bool canUseCMPXCHG8B() const { return hasCX8(); }
190 bool canUseCMPXCHG16B() const {
191 // CX16 is just the CPUID bit, instruction requires 64-bit mode too.
192 return hasCX16() && is64Bit();
193 }
194 // SSE codegen depends on cmovs, and all SSE1+ processors support them.
195 // All 64-bit processors support cmov.
196 bool canUseCMOV() const { return hasCMOV() || hasSSE1() || is64Bit(); }
197 bool hasSSE1() const { return X86SSELevel >= SSE1; }
198 bool hasSSE2() const { return X86SSELevel >= SSE2; }
199 bool hasSSE3() const { return X86SSELevel >= SSE3; }
200 bool hasSSSE3() const { return X86SSELevel >= SSSE3; }
201 bool hasSSE41() const { return X86SSELevel >= SSE41; }
202 bool hasSSE42() const { return X86SSELevel >= SSE42; }
203 bool hasAVX() const { return X86SSELevel >= AVX; }
204 bool hasAVX2() const { return X86SSELevel >= AVX2; }
205 bool hasAVX512() const { return X86SSELevel >= AVX512; }
206 bool hasInt256() const { return hasAVX2(); }
207 bool hasAnyFMA() const { return hasFMA() || hasFMA4(); }
208 bool hasPrefetchW() const {
209 // The PREFETCHW instruction was added with 3DNow but later CPUs gave it
210 // its own CPUID bit as part of deprecating 3DNow.
211 return hasPRFCHW();
212 }
213 bool hasSSEPrefetch() const {
214 // We also implicitly enable these when we have a write prefix supporting
215 // cache level OR if we have prfchw.
216 return hasSSE1() || hasPRFCHW() || hasPREFETCHI();
217 }
218 bool canUseLAHFSAHF() const { return hasLAHFSAHF64() || !is64Bit(); }
219 // These are generic getters that OR together all of the thunk types
220 // supported by the subtarget. Therefore useIndirectThunk*() will return true
221 // if any respective thunk feature is enabled.
223 return useRetpolineIndirectCalls() || useLVIControlFlowIntegrity();
224 }
226 return useRetpolineIndirectBranches() || useLVIControlFlowIntegrity();
227 }
228
229 unsigned getPreferVectorWidth() const { return PreferVectorWidth; }
230 unsigned getRequiredVectorWidth() const { return RequiredVectorWidth; }
231
232 // Helper functions to determine when we should allow widening to 512-bit
233 // during codegen.
234 // TODO: Currently we're always allowing widening on CPUs without VLX,
235 // because for many cases we don't have a better option.
236 bool canExtendTo512DQ() const {
237 return hasAVX512() && (!hasVLX() || getPreferVectorWidth() >= 512);
238 }
239 bool canExtendTo512BW() const {
240 return hasBWI() && canExtendTo512DQ();
241 }
242
243 bool hasNoDomainDelay() const { return NoDomainDelay; }
244 bool hasNoDomainDelayMov() const {
245 return hasNoDomainDelay() || NoDomainDelayMov;
246 }
248 return hasNoDomainDelay() || NoDomainDelayBlend;
249 }
251 return hasNoDomainDelay() || NoDomainDelayShuffle;
252 }
253
254 // If there are no 512-bit vectors and we prefer not to use 512-bit registers,
255 // disable them in the legalizer.
256 bool useAVX512Regs() const {
257 return hasAVX512() && (canExtendTo512DQ() || RequiredVectorWidth > 256);
258 }
259
261 return getPreferVectorWidth() >= 256 || AllowLight256Bit;
262 }
263
264 bool useBWIRegs() const {
265 return hasBWI() && useAVX512Regs();
266 }
267
268 // Returns true if the destination register of a BSF/BSR instruction is
269 // not touched if the source register is zero.
270 // NOTE: i32->i64 implicit zext isn't guaranteed by BSR/BSF pass through.
271 bool hasBitScanPassThrough() const { return is64Bit(); }
272
273 bool isXRaySupported() const override { return is64Bit(); }
274
275 /// Use clflush if we have SSE2 or we're on x86-64 (even if we asked for
276 /// no-sse2). There isn't any reason to disable it if the target processor
277 /// supports it.
278 bool hasCLFLUSH() const { return hasSSE2() || is64Bit(); }
279
280 /// Use mfence if we have SSE2 or we're on x86-64 (even if we asked for
281 /// no-sse2). There isn't any reason to disable it if the target processor
282 /// supports it.
283 bool hasMFence() const { return hasSSE2() || is64Bit(); }
284
285 /// Avoid use of `mfence` for`fence seq_cst`, and instead use `lock or`.
286 bool avoidMFence() const { return is64Bit(); }
287
288 const Triple &getTargetTriple() const { return TargetTriple; }
289
290 bool isTargetDarwin() const { return TargetTriple.isOSDarwin(); }
291 bool isTargetFreeBSD() const { return TargetTriple.isOSFreeBSD(); }
292 bool isTargetDragonFly() const { return TargetTriple.isOSDragonFly(); }
293 bool isTargetSolaris() const { return TargetTriple.isOSSolaris(); }
294 bool isTargetPS() const { return TargetTriple.isPS(); }
295
296 bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); }
297 bool isTargetCOFF() const { return TargetTriple.isOSBinFormatCOFF(); }
298 bool isTargetMachO() const { return TargetTriple.isOSBinFormatMachO(); }
299
300 bool isTargetLinux() const { return TargetTriple.isOSLinux(); }
301 bool isTargetKFreeBSD() const { return TargetTriple.isOSKFreeBSD(); }
302 bool isTargetHurd() const { return TargetTriple.isOSHurd(); }
303 bool isTargetGlibc() const { return TargetTriple.isOSGlibc(); }
304 bool isTargetMusl() const { return TargetTriple.isMusl(); }
305 bool isTargetAndroid() const { return TargetTriple.isAndroid(); }
306 bool isTargetMCU() const { return TargetTriple.isOSIAMCU(); }
307 bool isTargetFuchsia() const { return TargetTriple.isOSFuchsia(); }
308
309 bool isTargetWindowsMSVC() const {
310 return TargetTriple.isWindowsMSVCEnvironment();
311 }
312
314 return TargetTriple.isWindowsCoreCLREnvironment();
315 }
316
318 return TargetTriple.isWindowsCygwinEnvironment();
319 }
320
321 bool isTargetWindowsGNU() const {
322 return TargetTriple.isWindowsGNUEnvironment();
323 }
324
326 return TargetTriple.isWindowsItaniumEnvironment();
327 }
328
329 bool isTargetCygMing() const { return TargetTriple.isOSCygMing(); }
330
331 bool isUEFI() const { return TargetTriple.isUEFI(); }
332
333 bool isOSWindows() const { return TargetTriple.isOSWindows(); }
334
335 bool isTargetUEFI64() const { return Is64Bit && isUEFI(); }
336
337 bool isTargetWin64() const { return Is64Bit && isOSWindows(); }
338
339 bool isTargetWin32() const { return !Is64Bit && isOSWindows(); }
340
341 bool isPICStyleGOT() const { return PICStyle == PICStyles::Style::GOT; }
342 bool isPICStyleRIPRel() const { return PICStyle == PICStyles::Style::RIPRel; }
343
344 bool isPICStyleStubPIC() const {
345 return PICStyle == PICStyles::Style::StubPIC;
346 }
347
348 bool isPositionIndependent() const;
349
351 switch (CC) {
352 // On Win64, all these conventions just use the default convention.
353 case CallingConv::C:
356 return isTargetWin64() || isTargetUEFI64();
364 return isTargetWin64();
365 // This convention allows using the Win64 convention on other targets.
367 return true;
368 // This convention allows using the SysV convention on Windows targets.
370 return false;
371 // Otherwise, who knows what this is.
372 default:
373 return false;
374 }
375 }
376
377 /// Classify a global variable reference for the current subtarget according
378 /// to how we should reference it in a non-pcrel context.
379 unsigned char classifyLocalReference(const GlobalValue *GV) const;
380
381 unsigned char classifyGlobalReference(const GlobalValue *GV,
382 const Module &M) const;
383 unsigned char classifyGlobalReference(const GlobalValue *GV) const;
384
385 /// Classify a global function reference for the current subtarget.
386 unsigned char classifyGlobalFunctionReference(const GlobalValue *GV,
387 const Module &M) const;
388 unsigned char
389 classifyGlobalFunctionReference(const GlobalValue *GV) const override;
390
391 /// Classify a blockaddress reference for the current subtarget according to
392 /// how we should reference it in a non-pcrel context.
393 unsigned char classifyBlockAddressReference() const;
394
395 /// Return true if the subtarget allows calls to immediate address.
396 bool isLegalToCallImmediateAddr() const;
397
398 /// Return whether FrameLowering should always set the "extended frame
399 /// present" bit in FP, or set it based on a symbol in the runtime.
401 // Older OS versions (particularly system unwinders) are confused by the
402 // Swift extended frame, so when building code that might be run on them we
403 // must dynamically query the concurrency library to determine whether
404 // extended frames should be flagged as present.
405 const Triple &TT = getTargetTriple();
406
407 unsigned Major = TT.getOSVersion().getMajor();
408 switch(TT.getOS()) {
409 default:
410 return false;
411 case Triple::IOS:
412 case Triple::TvOS:
413 return Major < 15;
414 case Triple::WatchOS:
415 return Major < 8;
416 case Triple::MacOSX:
417 case Triple::Darwin:
418 return Major < 12;
419 }
420 }
421
422 /// If we are using indirect thunks, we need to expand indirectbr to avoid it
423 /// lowering to an actual indirect jump.
424 bool enableIndirectBrExpand() const override {
426 }
427
428 /// Enable the MachineScheduler pass for all X86 subtargets.
429 bool enableMachineScheduler() const override { return true; }
430
431 bool enableEarlyIfConversion() const override;
432
433 void getPostRAMutations(std::vector<std::unique_ptr<ScheduleDAGMutation>>
434 &Mutations) const override;
435
436 AntiDepBreakMode getAntiDepBreakMode() const override {
437 return TargetSubtargetInfo::ANTIDEP_CRITICAL;
438 }
439};
440
441} // end namespace llvm
442
443#endif // LLVM_LIB_TARGET_X86_X86SUBTARGET_H
This file implements the BitVector class.
DXIL Legalizer
static bool is64Bit(const char *name)
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
Holds all the information related to register banks.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
constexpr unsigned id() const
Definition Register.h:100
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
Primary interface to the complete machine description for the target machine.
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:47
const X86RegisterInfo & getRegisterInfo() const
getRegisterInfo - TargetInstrInfo is a superset of MRegister info.
bool canExtendTo512BW() const
bool hasAnyFMA() const
bool enableEarlyIfConversion() const override
~X86Subtarget() override
bool isOSWindows() const
bool isTargetMachO() const
unsigned getTileConfigSize() const
bool canUseLAHFSAHF() const
bool isUEFI() const
bool isTargetKFreeBSD() const
bool isXRaySupported() const override
unsigned getRequiredVectorWidth() const
bool useIndirectThunkBranches() const
bool hasSSE1() const
bool avoidMFence() const
Avoid use of mfence forfence seq_cst, and instead use lock or.
bool useLight256BitInstructions() const
bool isTargetSolaris() const
bool hasBitScanPassThrough() const
bool isPICStyleGOT() const
bool isTargetWindowsCygwin() const
bool hasSSE42() const
InstructionSelector * getInstructionSelector() const override
const X86TargetLowering * getTargetLowering() const override
bool hasMFence() const
Use mfence if we have SSE2 or we're on x86-64 (even if we asked for no-sse2).
bool hasNoDomainDelayBlend() const
Align getTileConfigAlignment() const
bool isTargetMCU() const
bool isTargetDragonFly() const
bool canUseCMOV() const
bool isPICStyleStubPIC() const
bool isLegalToCallImmediateAddr() const
Return true if the subtarget allows calls to immediate address.
bool enableMachineScheduler() const override
Enable the MachineScheduler pass for all X86 subtargets.
bool isTargetWindowsMSVC() const
bool canUseCMPXCHG8B() const
bool isTarget64BitILP32() const
Is this x86_64 with the ILP32 programming model (x32 ABI)?
bool hasNoDomainDelayShuffle() const
bool isTargetDarwin() const
bool isTargetWin64() const
bool hasPrefetchW() const
bool isTarget64BitLP64() const
Is this x86_64 with the LP64 programming model (standard AMD64, no x32)?
bool swiftAsyncContextIsDynamicallySet() const
Return whether FrameLowering should always set the "extended framepresent" bit in FP,...
const Triple & getTargetTriple() const
bool isRegisterReservedByUser(Register i) const override
AntiDepBreakMode getAntiDepBreakMode() const override
bool isTargetWindowsCoreCLR() const
const X86InstrInfo * getInstrInfo() const override
const RegisterBankInfo * getRegBankInfo() const override
bool useAVX512Regs() const
bool isTargetCOFF() const
bool hasSSE3() const
bool isCallingConvWin64(CallingConv::ID CC) const
bool hasAVX512() const
bool canExtendTo512DQ() const
bool hasSSE41() const
Align getStackAlignment() const
Returns the minimum alignment known to hold of the stack frame on entry to the function and which mus...
bool isTargetELF() const
bool hasSSEPrefetch() const
bool canUseCMPXCHG16B() const
unsigned char classifyGlobalReference(const GlobalValue *GV, const Module &M) const
const LegalizerInfo * getLegalizerInfo() const override
bool isPositionIndependent() const
bool hasSSE2() const
bool isTargetFreeBSD() const
bool isTargetGlibc() const
bool isTargetFuchsia() const
bool hasSSSE3() const
bool hasInt256() const
bool isPICStyleRIPRel() const
bool isTargetCygMing() const
bool hasNoDomainDelay() const
unsigned char classifyLocalReference(const GlobalValue *GV) const
Classify a global variable reference for the current subtarget according to how we should reference i...
unsigned char classifyBlockAddressReference() const
Classify a blockaddress reference for the current subtarget according to how we should reference it i...
PICStyles::Style getPICStyle() const
bool enableIndirectBrExpand() const override
If we are using indirect thunks, we need to expand indirectbr to avoid it lowering to an actual indir...
bool hasNoDomainDelayMov() const
bool isTargetPS() const
bool isTargetUEFI64() const
const X86RegisterInfo * getRegisterInfo() const override
void setPICStyle(PICStyles::Style Style)
X86Subtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU, StringRef FS, const X86TargetMachine &TM, MaybeAlign StackAlignOverride, unsigned PreferVectorWidthOverride, unsigned RequiredVectorWidth)
This constructor initializes the data members to match that of the specified triple.
bool hasAVX() const
bool isTargetWindowsGNU() const
unsigned getMaxInlineSizeThreshold() const
Returns the maximum memset / memcpy size that still makes it profitable to inline the call.
unsigned getPreferVectorWidth() const
bool isTargetWindowsItanium() const
bool isTargetMusl() const
bool isTargetAndroid() const
const CallLowering * getCallLowering() const override
Methods used by Global ISel.
bool hasCLFLUSH() const
Use clflush if we have SSE2 or we're on x86-64 (even if we asked for no-sse2).
void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS)
ParseSubtargetFeatures - Parses features string setting specified subtarget options.
const X86FrameLowering * getFrameLowering() const override
void getPostRAMutations(std::vector< std::unique_ptr< ScheduleDAGMutation > > &Mutations) const override
bool isTargetHurd() const
bool useBWIRegs() const
bool isTargetWin32() const
bool useIndirectThunkCalls() const
unsigned char classifyGlobalFunctionReference(const GlobalValue *GV, const Module &M) const
Classify a global function reference for the current subtarget.
bool hasAVX2() const
const X86SelectionDAGInfo * getSelectionDAGInfo() const override
bool isTargetLinux() const
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ X86_64_SysV
The C convention as specified in the x86-64 supplement to the System V ABI, used on most non-Windows ...
@ Swift
Calling convention for Swift.
Definition CallingConv.h:69
@ X86_ThisCall
Similar to X86_StdCall.
@ X86_StdCall
stdcall is mostly used by the Win32 API.
Definition CallingConv.h:99
@ Fast
Attempts to make calls as fast as possible (e.g.
Definition CallingConv.h:41
@ X86_VectorCall
MSVC calling convention that passes vectors and vector aggregates in SSE registers.
@ Intel_OCL_BI
Used for Intel OpenCL built-ins.
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
Definition CallingConv.h:76
@ Win64
The C convention as implemented on Windows/x86-64 and AArch64.
@ SwiftTail
This follows the Swift calling convention in how arguments are passed but guarantees tail calls will ...
Definition CallingConv.h:87
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ X86_FastCall
'fast' analog of X86_StdCall.
The X86 backend supports a number of different styles of PIC.
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39