106f32e7eSjoerg //===-- X86Subtarget.h - Define Subtarget for the X86 ----------*- C++ -*--===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg //===----------------------------------------------------------------------===//
806f32e7eSjoerg //
906f32e7eSjoerg // This file declares the X86 specific subclass of TargetSubtargetInfo.
1006f32e7eSjoerg //
1106f32e7eSjoerg //===----------------------------------------------------------------------===//
1206f32e7eSjoerg 
1306f32e7eSjoerg #ifndef LLVM_LIB_TARGET_X86_X86SUBTARGET_H
1406f32e7eSjoerg #define LLVM_LIB_TARGET_X86_X86SUBTARGET_H
1506f32e7eSjoerg 
1606f32e7eSjoerg #include "X86FrameLowering.h"
1706f32e7eSjoerg #include "X86ISelLowering.h"
1806f32e7eSjoerg #include "X86InstrInfo.h"
1906f32e7eSjoerg #include "X86SelectionDAGInfo.h"
2006f32e7eSjoerg #include "llvm/ADT/Triple.h"
2106f32e7eSjoerg #include "llvm/CodeGen/TargetSubtargetInfo.h"
2206f32e7eSjoerg #include "llvm/IR/CallingConv.h"
2306f32e7eSjoerg #include <climits>
2406f32e7eSjoerg #include <memory>
2506f32e7eSjoerg 
2606f32e7eSjoerg #define GET_SUBTARGETINFO_HEADER
2706f32e7eSjoerg #include "X86GenSubtargetInfo.inc"
2806f32e7eSjoerg 
2906f32e7eSjoerg namespace llvm {
3006f32e7eSjoerg 
31*da58b97aSjoerg class CallLowering;
3206f32e7eSjoerg class GlobalValue;
33*da58b97aSjoerg class InstructionSelector;
34*da58b97aSjoerg class LegalizerInfo;
35*da58b97aSjoerg class RegisterBankInfo;
36*da58b97aSjoerg class StringRef;
37*da58b97aSjoerg class TargetMachine;
3806f32e7eSjoerg 
3906f32e7eSjoerg /// The X86 backend supports a number of different styles of PIC.
4006f32e7eSjoerg ///
4106f32e7eSjoerg namespace PICStyles {
4206f32e7eSjoerg 
43*da58b97aSjoerg enum class Style {
4406f32e7eSjoerg   StubPIC,          // Used on i386-darwin in pic mode.
4506f32e7eSjoerg   GOT,              // Used on 32 bit elf on when in pic mode.
4606f32e7eSjoerg   RIPRel,           // Used on X86-64 when in pic mode.
4706f32e7eSjoerg   None              // Set when not in pic mode.
4806f32e7eSjoerg };
4906f32e7eSjoerg 
5006f32e7eSjoerg } // end namespace PICStyles
5106f32e7eSjoerg 
5206f32e7eSjoerg class X86Subtarget final : public X86GenSubtargetInfo {
5306f32e7eSjoerg   // NOTE: Do not add anything new to this list. Coarse, CPU name based flags
5406f32e7eSjoerg   // are not a good idea. We should be migrating away from these.
5506f32e7eSjoerg   enum X86ProcFamilyEnum {
5606f32e7eSjoerg     Others,
5706f32e7eSjoerg     IntelAtom,
58*da58b97aSjoerg     IntelSLM
5906f32e7eSjoerg   };
6006f32e7eSjoerg 
6106f32e7eSjoerg   enum X86SSEEnum {
6206f32e7eSjoerg     NoSSE, SSE1, SSE2, SSE3, SSSE3, SSE41, SSE42, AVX, AVX2, AVX512F
6306f32e7eSjoerg   };
6406f32e7eSjoerg 
6506f32e7eSjoerg   enum X863DNowEnum {
6606f32e7eSjoerg     NoThreeDNow, MMX, ThreeDNow, ThreeDNowA
6706f32e7eSjoerg   };
6806f32e7eSjoerg 
6906f32e7eSjoerg   /// X86 processor family: Intel Atom, and others
7006f32e7eSjoerg   X86ProcFamilyEnum X86ProcFamily = Others;
7106f32e7eSjoerg 
7206f32e7eSjoerg   /// Which PIC style to use
7306f32e7eSjoerg   PICStyles::Style PICStyle;
7406f32e7eSjoerg 
7506f32e7eSjoerg   const TargetMachine &TM;
7606f32e7eSjoerg 
7706f32e7eSjoerg   /// SSE1, SSE2, SSE3, SSSE3, SSE41, SSE42, or none supported.
7806f32e7eSjoerg   X86SSEEnum X86SSELevel = NoSSE;
7906f32e7eSjoerg 
8006f32e7eSjoerg   /// MMX, 3DNow, 3DNow Athlon, or none supported.
8106f32e7eSjoerg   X863DNowEnum X863DNowLevel = NoThreeDNow;
8206f32e7eSjoerg 
8306f32e7eSjoerg   /// True if the processor supports X87 instructions.
8406f32e7eSjoerg   bool HasX87 = false;
8506f32e7eSjoerg 
8606f32e7eSjoerg   /// True if the processor supports CMPXCHG8B.
8706f32e7eSjoerg   bool HasCmpxchg8b = false;
8806f32e7eSjoerg 
8906f32e7eSjoerg   /// True if this processor has NOPL instruction
9006f32e7eSjoerg   /// (generally pentium pro+).
9106f32e7eSjoerg   bool HasNOPL = false;
9206f32e7eSjoerg 
9306f32e7eSjoerg   /// True if this processor has conditional move instructions
9406f32e7eSjoerg   /// (generally pentium pro+).
9506f32e7eSjoerg   bool HasCMov = false;
9606f32e7eSjoerg 
9706f32e7eSjoerg   /// True if the processor supports X86-64 instructions.
9806f32e7eSjoerg   bool HasX86_64 = false;
9906f32e7eSjoerg 
10006f32e7eSjoerg   /// True if the processor supports POPCNT.
10106f32e7eSjoerg   bool HasPOPCNT = false;
10206f32e7eSjoerg 
10306f32e7eSjoerg   /// True if the processor supports SSE4A instructions.
10406f32e7eSjoerg   bool HasSSE4A = false;
10506f32e7eSjoerg 
10606f32e7eSjoerg   /// Target has AES instructions
10706f32e7eSjoerg   bool HasAES = false;
10806f32e7eSjoerg   bool HasVAES = false;
10906f32e7eSjoerg 
11006f32e7eSjoerg   /// Target has FXSAVE/FXRESTOR instructions
11106f32e7eSjoerg   bool HasFXSR = false;
11206f32e7eSjoerg 
11306f32e7eSjoerg   /// Target has XSAVE instructions
11406f32e7eSjoerg   bool HasXSAVE = false;
11506f32e7eSjoerg 
11606f32e7eSjoerg   /// Target has XSAVEOPT instructions
11706f32e7eSjoerg   bool HasXSAVEOPT = false;
11806f32e7eSjoerg 
11906f32e7eSjoerg   /// Target has XSAVEC instructions
12006f32e7eSjoerg   bool HasXSAVEC = false;
12106f32e7eSjoerg 
12206f32e7eSjoerg   /// Target has XSAVES instructions
12306f32e7eSjoerg   bool HasXSAVES = false;
12406f32e7eSjoerg 
12506f32e7eSjoerg   /// Target has carry-less multiplication
12606f32e7eSjoerg   bool HasPCLMUL = false;
12706f32e7eSjoerg   bool HasVPCLMULQDQ = false;
12806f32e7eSjoerg 
12906f32e7eSjoerg   /// Target has Galois Field Arithmetic instructions
13006f32e7eSjoerg   bool HasGFNI = false;
13106f32e7eSjoerg 
13206f32e7eSjoerg   /// Target has 3-operand fused multiply-add
13306f32e7eSjoerg   bool HasFMA = false;
13406f32e7eSjoerg 
13506f32e7eSjoerg   /// Target has 4-operand fused multiply-add
13606f32e7eSjoerg   bool HasFMA4 = false;
13706f32e7eSjoerg 
13806f32e7eSjoerg   /// Target has XOP instructions
13906f32e7eSjoerg   bool HasXOP = false;
14006f32e7eSjoerg 
14106f32e7eSjoerg   /// Target has TBM instructions.
14206f32e7eSjoerg   bool HasTBM = false;
14306f32e7eSjoerg 
14406f32e7eSjoerg   /// Target has LWP instructions
14506f32e7eSjoerg   bool HasLWP = false;
14606f32e7eSjoerg 
14706f32e7eSjoerg   /// True if the processor has the MOVBE instruction.
14806f32e7eSjoerg   bool HasMOVBE = false;
14906f32e7eSjoerg 
15006f32e7eSjoerg   /// True if the processor has the RDRAND instruction.
15106f32e7eSjoerg   bool HasRDRAND = false;
15206f32e7eSjoerg 
15306f32e7eSjoerg   /// Processor has 16-bit floating point conversion instructions.
15406f32e7eSjoerg   bool HasF16C = false;
15506f32e7eSjoerg 
15606f32e7eSjoerg   /// Processor has FS/GS base insturctions.
15706f32e7eSjoerg   bool HasFSGSBase = false;
15806f32e7eSjoerg 
15906f32e7eSjoerg   /// Processor has LZCNT instruction.
16006f32e7eSjoerg   bool HasLZCNT = false;
16106f32e7eSjoerg 
16206f32e7eSjoerg   /// Processor has BMI1 instructions.
16306f32e7eSjoerg   bool HasBMI = false;
16406f32e7eSjoerg 
16506f32e7eSjoerg   /// Processor has BMI2 instructions.
16606f32e7eSjoerg   bool HasBMI2 = false;
16706f32e7eSjoerg 
16806f32e7eSjoerg   /// Processor has VBMI instructions.
16906f32e7eSjoerg   bool HasVBMI = false;
17006f32e7eSjoerg 
17106f32e7eSjoerg   /// Processor has VBMI2 instructions.
17206f32e7eSjoerg   bool HasVBMI2 = false;
17306f32e7eSjoerg 
17406f32e7eSjoerg   /// Processor has Integer Fused Multiply Add
17506f32e7eSjoerg   bool HasIFMA = false;
17606f32e7eSjoerg 
17706f32e7eSjoerg   /// Processor has RTM instructions.
17806f32e7eSjoerg   bool HasRTM = false;
17906f32e7eSjoerg 
18006f32e7eSjoerg   /// Processor has ADX instructions.
18106f32e7eSjoerg   bool HasADX = false;
18206f32e7eSjoerg 
18306f32e7eSjoerg   /// Processor has SHA instructions.
18406f32e7eSjoerg   bool HasSHA = false;
18506f32e7eSjoerg 
18606f32e7eSjoerg   /// Processor has PRFCHW instructions.
18706f32e7eSjoerg   bool HasPRFCHW = false;
18806f32e7eSjoerg 
18906f32e7eSjoerg   /// Processor has RDSEED instructions.
19006f32e7eSjoerg   bool HasRDSEED = false;
19106f32e7eSjoerg 
192*da58b97aSjoerg   /// Processor has LAHF/SAHF instructions in 64-bit mode.
193*da58b97aSjoerg   bool HasLAHFSAHF64 = false;
19406f32e7eSjoerg 
19506f32e7eSjoerg   /// Processor has MONITORX/MWAITX instructions.
19606f32e7eSjoerg   bool HasMWAITX = false;
19706f32e7eSjoerg 
19806f32e7eSjoerg   /// Processor has Cache Line Zero instruction
19906f32e7eSjoerg   bool HasCLZERO = false;
20006f32e7eSjoerg 
20106f32e7eSjoerg   /// Processor has Cache Line Demote instruction
20206f32e7eSjoerg   bool HasCLDEMOTE = false;
20306f32e7eSjoerg 
20406f32e7eSjoerg   /// Processor has MOVDIRI instruction (direct store integer).
20506f32e7eSjoerg   bool HasMOVDIRI = false;
20606f32e7eSjoerg 
20706f32e7eSjoerg   /// Processor has MOVDIR64B instruction (direct store 64 bytes).
20806f32e7eSjoerg   bool HasMOVDIR64B = false;
20906f32e7eSjoerg 
21006f32e7eSjoerg   /// Processor has ptwrite instruction.
21106f32e7eSjoerg   bool HasPTWRITE = false;
21206f32e7eSjoerg 
21306f32e7eSjoerg   /// Processor has Prefetch with intent to Write instruction
21406f32e7eSjoerg   bool HasPREFETCHWT1 = false;
21506f32e7eSjoerg 
21606f32e7eSjoerg   /// True if SHLD instructions are slow.
21706f32e7eSjoerg   bool IsSHLDSlow = false;
21806f32e7eSjoerg 
21906f32e7eSjoerg   /// True if the PMULLD instruction is slow compared to PMULLW/PMULHW and
22006f32e7eSjoerg   //  PMULUDQ.
22106f32e7eSjoerg   bool IsPMULLDSlow = false;
22206f32e7eSjoerg 
22306f32e7eSjoerg   /// True if the PMADDWD instruction is slow compared to PMULLD.
22406f32e7eSjoerg   bool IsPMADDWDSlow = false;
22506f32e7eSjoerg 
22606f32e7eSjoerg   /// True if unaligned memory accesses of 16-bytes are slow.
22706f32e7eSjoerg   bool IsUAMem16Slow = false;
22806f32e7eSjoerg 
22906f32e7eSjoerg   /// True if unaligned memory accesses of 32-bytes are slow.
23006f32e7eSjoerg   bool IsUAMem32Slow = false;
23106f32e7eSjoerg 
23206f32e7eSjoerg   /// True if SSE operations can have unaligned memory operands.
23306f32e7eSjoerg   /// This may require setting a configuration bit in the processor.
23406f32e7eSjoerg   bool HasSSEUnalignedMem = false;
23506f32e7eSjoerg 
23606f32e7eSjoerg   /// True if this processor has the CMPXCHG16B instruction;
23706f32e7eSjoerg   /// this is true for most x86-64 chips, but not the first AMD chips.
23806f32e7eSjoerg   bool HasCmpxchg16b = false;
23906f32e7eSjoerg 
24006f32e7eSjoerg   /// True if the LEA instruction should be used for adjusting
24106f32e7eSjoerg   /// the stack pointer. This is an optimization for Intel Atom processors.
24206f32e7eSjoerg   bool UseLeaForSP = false;
24306f32e7eSjoerg 
24406f32e7eSjoerg   /// True if POPCNT instruction has a false dependency on the destination register.
24506f32e7eSjoerg   bool HasPOPCNTFalseDeps = false;
24606f32e7eSjoerg 
24706f32e7eSjoerg   /// True if LZCNT/TZCNT instructions have a false dependency on the destination register.
24806f32e7eSjoerg   bool HasLZCNTFalseDeps = false;
24906f32e7eSjoerg 
25006f32e7eSjoerg   /// True if its preferable to combine to a single shuffle using a variable
25106f32e7eSjoerg   /// mask over multiple fixed shuffles.
25206f32e7eSjoerg   bool HasFastVariableShuffle = false;
25306f32e7eSjoerg 
254*da58b97aSjoerg   /// True if vzeroupper instructions should be inserted after code that uses
255*da58b97aSjoerg   /// ymm or zmm registers.
256*da58b97aSjoerg   bool InsertVZEROUPPER = false;
257*da58b97aSjoerg 
258*da58b97aSjoerg   /// True if there is no performance penalty for writing NOPs with up to
259*da58b97aSjoerg   /// 7 bytes.
260*da58b97aSjoerg   bool HasFast7ByteNOP = false;
26106f32e7eSjoerg 
26206f32e7eSjoerg   /// True if there is no performance penalty for writing NOPs with up to
26306f32e7eSjoerg   /// 11 bytes.
26406f32e7eSjoerg   bool HasFast11ByteNOP = false;
26506f32e7eSjoerg 
26606f32e7eSjoerg   /// True if there is no performance penalty for writing NOPs with up to
26706f32e7eSjoerg   /// 15 bytes.
26806f32e7eSjoerg   bool HasFast15ByteNOP = false;
26906f32e7eSjoerg 
27006f32e7eSjoerg   /// True if gather is reasonably fast. This is true for Skylake client and
27106f32e7eSjoerg   /// all AVX-512 CPUs.
27206f32e7eSjoerg   bool HasFastGather = false;
27306f32e7eSjoerg 
27406f32e7eSjoerg   /// True if hardware SQRTSS instruction is at least as fast (latency) as
27506f32e7eSjoerg   /// RSQRTSS followed by a Newton-Raphson iteration.
27606f32e7eSjoerg   bool HasFastScalarFSQRT = false;
27706f32e7eSjoerg 
27806f32e7eSjoerg   /// True if hardware SQRTPS/VSQRTPS instructions are at least as fast
27906f32e7eSjoerg   /// (throughput) as RSQRTPS/VRSQRTPS followed by a Newton-Raphson iteration.
28006f32e7eSjoerg   bool HasFastVectorFSQRT = false;
28106f32e7eSjoerg 
28206f32e7eSjoerg   /// True if 8-bit divisions are significantly faster than
28306f32e7eSjoerg   /// 32-bit divisions and should be used when possible.
28406f32e7eSjoerg   bool HasSlowDivide32 = false;
28506f32e7eSjoerg 
28606f32e7eSjoerg   /// True if 32-bit divides are significantly faster than
28706f32e7eSjoerg   /// 64-bit divisions and should be used when possible.
28806f32e7eSjoerg   bool HasSlowDivide64 = false;
28906f32e7eSjoerg 
29006f32e7eSjoerg   /// True if LZCNT instruction is fast.
29106f32e7eSjoerg   bool HasFastLZCNT = false;
29206f32e7eSjoerg 
29306f32e7eSjoerg   /// True if SHLD based rotate is fast.
29406f32e7eSjoerg   bool HasFastSHLDRotate = false;
29506f32e7eSjoerg 
29606f32e7eSjoerg   /// True if the processor supports macrofusion.
29706f32e7eSjoerg   bool HasMacroFusion = false;
29806f32e7eSjoerg 
29906f32e7eSjoerg   /// True if the processor supports branch fusion.
30006f32e7eSjoerg   bool HasBranchFusion = false;
30106f32e7eSjoerg 
30206f32e7eSjoerg   /// True if the processor has enhanced REP MOVSB/STOSB.
30306f32e7eSjoerg   bool HasERMSB = false;
30406f32e7eSjoerg 
305*da58b97aSjoerg   /// True if the processor has fast short REP MOV.
306*da58b97aSjoerg   bool HasFSRM = false;
307*da58b97aSjoerg 
30806f32e7eSjoerg   /// True if the short functions should be padded to prevent
30906f32e7eSjoerg   /// a stall when returning too early.
31006f32e7eSjoerg   bool PadShortFunctions = false;
31106f32e7eSjoerg 
31206f32e7eSjoerg   /// True if two memory operand instructions should use a temporary register
31306f32e7eSjoerg   /// instead.
31406f32e7eSjoerg   bool SlowTwoMemOps = false;
31506f32e7eSjoerg 
31606f32e7eSjoerg   /// True if the LEA instruction inputs have to be ready at address generation
31706f32e7eSjoerg   /// (AG) time.
31806f32e7eSjoerg   bool LEAUsesAG = false;
31906f32e7eSjoerg 
32006f32e7eSjoerg   /// True if the LEA instruction with certain arguments is slow
32106f32e7eSjoerg   bool SlowLEA = false;
32206f32e7eSjoerg 
32306f32e7eSjoerg   /// True if the LEA instruction has all three source operands: base, index,
32406f32e7eSjoerg   /// and offset or if the LEA instruction uses base and index registers where
32506f32e7eSjoerg   /// the base is EBP, RBP,or R13
32606f32e7eSjoerg   bool Slow3OpsLEA = false;
32706f32e7eSjoerg 
32806f32e7eSjoerg   /// True if INC and DEC instructions are slow when writing to flags
32906f32e7eSjoerg   bool SlowIncDec = false;
33006f32e7eSjoerg 
33106f32e7eSjoerg   /// Processor has AVX-512 PreFetch Instructions
33206f32e7eSjoerg   bool HasPFI = false;
33306f32e7eSjoerg 
33406f32e7eSjoerg   /// Processor has AVX-512 Exponential and Reciprocal Instructions
33506f32e7eSjoerg   bool HasERI = false;
33606f32e7eSjoerg 
33706f32e7eSjoerg   /// Processor has AVX-512 Conflict Detection Instructions
33806f32e7eSjoerg   bool HasCDI = false;
33906f32e7eSjoerg 
34006f32e7eSjoerg   /// Processor has AVX-512 population count Instructions
34106f32e7eSjoerg   bool HasVPOPCNTDQ = false;
34206f32e7eSjoerg 
34306f32e7eSjoerg   /// Processor has AVX-512 Doubleword and Quadword instructions
34406f32e7eSjoerg   bool HasDQI = false;
34506f32e7eSjoerg 
34606f32e7eSjoerg   /// Processor has AVX-512 Byte and Word instructions
34706f32e7eSjoerg   bool HasBWI = false;
34806f32e7eSjoerg 
34906f32e7eSjoerg   /// Processor has AVX-512 Vector Length eXtenstions
35006f32e7eSjoerg   bool HasVLX = false;
35106f32e7eSjoerg 
35206f32e7eSjoerg   /// Processor has PKU extenstions
35306f32e7eSjoerg   bool HasPKU = false;
35406f32e7eSjoerg 
35506f32e7eSjoerg   /// Processor has AVX-512 Vector Neural Network Instructions
35606f32e7eSjoerg   bool HasVNNI = false;
35706f32e7eSjoerg 
358*da58b97aSjoerg   /// Processor has AVX Vector Neural Network Instructions
359*da58b97aSjoerg   bool HasAVXVNNI = false;
360*da58b97aSjoerg 
36106f32e7eSjoerg   /// Processor has AVX-512 bfloat16 floating-point extensions
36206f32e7eSjoerg   bool HasBF16 = false;
36306f32e7eSjoerg 
36406f32e7eSjoerg   /// Processor supports ENQCMD instructions
36506f32e7eSjoerg   bool HasENQCMD = false;
36606f32e7eSjoerg 
36706f32e7eSjoerg   /// Processor has AVX-512 Bit Algorithms instructions
36806f32e7eSjoerg   bool HasBITALG = false;
36906f32e7eSjoerg 
37006f32e7eSjoerg   /// Processor has AVX-512 vp2intersect instructions
37106f32e7eSjoerg   bool HasVP2INTERSECT = false;
37206f32e7eSjoerg 
37306f32e7eSjoerg   /// Processor supports CET SHSTK - Control-Flow Enforcement Technology
37406f32e7eSjoerg   /// using Shadow Stack
37506f32e7eSjoerg   bool HasSHSTK = false;
37606f32e7eSjoerg 
37706f32e7eSjoerg   /// Processor supports Invalidate Process-Context Identifier
37806f32e7eSjoerg   bool HasINVPCID = false;
37906f32e7eSjoerg 
38006f32e7eSjoerg   /// Processor has Software Guard Extensions
38106f32e7eSjoerg   bool HasSGX = false;
38206f32e7eSjoerg 
38306f32e7eSjoerg   /// Processor supports Flush Cache Line instruction
38406f32e7eSjoerg   bool HasCLFLUSHOPT = false;
38506f32e7eSjoerg 
38606f32e7eSjoerg   /// Processor supports Cache Line Write Back instruction
38706f32e7eSjoerg   bool HasCLWB = false;
38806f32e7eSjoerg 
38906f32e7eSjoerg   /// Processor supports Write Back No Invalidate instruction
39006f32e7eSjoerg   bool HasWBNOINVD = false;
39106f32e7eSjoerg 
39206f32e7eSjoerg   /// Processor support RDPID instruction
39306f32e7eSjoerg   bool HasRDPID = false;
39406f32e7eSjoerg 
39506f32e7eSjoerg   /// Processor supports WaitPKG instructions
39606f32e7eSjoerg   bool HasWAITPKG = false;
39706f32e7eSjoerg 
39806f32e7eSjoerg   /// Processor supports PCONFIG instruction
39906f32e7eSjoerg   bool HasPCONFIG = false;
40006f32e7eSjoerg 
401*da58b97aSjoerg   /// Processor support key locker instructions
402*da58b97aSjoerg   bool HasKL = false;
403*da58b97aSjoerg 
404*da58b97aSjoerg   /// Processor support key locker wide instructions
405*da58b97aSjoerg   bool HasWIDEKL = false;
406*da58b97aSjoerg 
407*da58b97aSjoerg   /// Processor supports HRESET instruction
408*da58b97aSjoerg   bool HasHRESET = false;
409*da58b97aSjoerg 
410*da58b97aSjoerg   /// Processor supports SERIALIZE instruction
411*da58b97aSjoerg   bool HasSERIALIZE = false;
412*da58b97aSjoerg 
413*da58b97aSjoerg   /// Processor supports TSXLDTRK instruction
414*da58b97aSjoerg   bool HasTSXLDTRK = false;
415*da58b97aSjoerg 
416*da58b97aSjoerg   /// Processor has AMX support
417*da58b97aSjoerg   bool HasAMXTILE = false;
418*da58b97aSjoerg   bool HasAMXBF16 = false;
419*da58b97aSjoerg   bool HasAMXINT8 = false;
420*da58b97aSjoerg 
421*da58b97aSjoerg   /// Processor supports User Level Interrupt instructions
422*da58b97aSjoerg   bool HasUINTR = false;
423*da58b97aSjoerg 
42406f32e7eSjoerg   /// Processor has a single uop BEXTR implementation.
42506f32e7eSjoerg   bool HasFastBEXTR = false;
42606f32e7eSjoerg 
42706f32e7eSjoerg   /// Try harder to combine to horizontal vector ops if they are fast.
42806f32e7eSjoerg   bool HasFastHorizontalOps = false;
42906f32e7eSjoerg 
43006f32e7eSjoerg   /// Prefer a left/right scalar logical shifts pair over a shift+and pair.
43106f32e7eSjoerg   bool HasFastScalarShiftMasks = false;
43206f32e7eSjoerg 
43306f32e7eSjoerg   /// Prefer a left/right vector logical shifts pair over a shift+and pair.
43406f32e7eSjoerg   bool HasFastVectorShiftMasks = false;
43506f32e7eSjoerg 
436*da58b97aSjoerg   /// Prefer a movbe over a single-use load + bswap / single-use bswap + store.
437*da58b97aSjoerg   bool HasFastMOVBE = false;
438*da58b97aSjoerg 
43906f32e7eSjoerg   /// Use a retpoline thunk rather than indirect calls to block speculative
44006f32e7eSjoerg   /// execution.
44106f32e7eSjoerg   bool UseRetpolineIndirectCalls = false;
44206f32e7eSjoerg 
44306f32e7eSjoerg   /// Use a retpoline thunk or remove any indirect branch to block speculative
44406f32e7eSjoerg   /// execution.
44506f32e7eSjoerg   bool UseRetpolineIndirectBranches = false;
44606f32e7eSjoerg 
44706f32e7eSjoerg   /// Deprecated flag, query `UseRetpolineIndirectCalls` and
44806f32e7eSjoerg   /// `UseRetpolineIndirectBranches` instead.
44906f32e7eSjoerg   bool DeprecatedUseRetpoline = false;
45006f32e7eSjoerg 
45106f32e7eSjoerg   /// When using a retpoline thunk, call an externally provided thunk rather
45206f32e7eSjoerg   /// than emitting one inside the compiler.
45306f32e7eSjoerg   bool UseRetpolineExternalThunk = false;
45406f32e7eSjoerg 
455*da58b97aSjoerg   /// Prevent generation of indirect call/branch instructions from memory,
456*da58b97aSjoerg   /// and force all indirect call/branch instructions from a register to be
457*da58b97aSjoerg   /// preceded by an LFENCE. Also decompose RET instructions into a
458*da58b97aSjoerg   /// POP+LFENCE+JMP sequence.
459*da58b97aSjoerg   bool UseLVIControlFlowIntegrity = false;
460*da58b97aSjoerg 
461*da58b97aSjoerg   /// Enable Speculative Execution Side Effect Suppression
462*da58b97aSjoerg   bool UseSpeculativeExecutionSideEffectSuppression = false;
463*da58b97aSjoerg 
464*da58b97aSjoerg   /// Insert LFENCE instructions to prevent data speculatively injected into
465*da58b97aSjoerg   /// loads from being used maliciously.
466*da58b97aSjoerg   bool UseLVILoadHardening = false;
467*da58b97aSjoerg 
46806f32e7eSjoerg   /// Use software floating point for code generation.
46906f32e7eSjoerg   bool UseSoftFloat = false;
47006f32e7eSjoerg 
47106f32e7eSjoerg   /// Use alias analysis during code generation.
47206f32e7eSjoerg   bool UseAA = false;
47306f32e7eSjoerg 
47406f32e7eSjoerg   /// The minimum alignment known to hold of the stack frame on
47506f32e7eSjoerg   /// entry to the function and which must be maintained by every function.
47606f32e7eSjoerg   Align stackAlignment = Align(4);
47706f32e7eSjoerg 
478*da58b97aSjoerg   Align TileConfigAlignment = Align(4);
479*da58b97aSjoerg 
48006f32e7eSjoerg   /// Max. memset / memcpy size that is turned into rep/movs, rep/stos ops.
48106f32e7eSjoerg   ///
48206f32e7eSjoerg   // FIXME: this is a known good value for Yonah. How about others?
48306f32e7eSjoerg   unsigned MaxInlineSizeThreshold = 128;
48406f32e7eSjoerg 
48506f32e7eSjoerg   /// Indicates target prefers 128 bit instructions.
48606f32e7eSjoerg   bool Prefer128Bit = false;
48706f32e7eSjoerg 
48806f32e7eSjoerg   /// Indicates target prefers 256 bit instructions.
48906f32e7eSjoerg   bool Prefer256Bit = false;
49006f32e7eSjoerg 
49106f32e7eSjoerg   /// Indicates target prefers AVX512 mask registers.
49206f32e7eSjoerg   bool PreferMaskRegisters = false;
49306f32e7eSjoerg 
494*da58b97aSjoerg   /// Use Goldmont specific floating point div/sqrt costs.
495*da58b97aSjoerg   bool UseGLMDivSqrtCosts = false;
49606f32e7eSjoerg 
49706f32e7eSjoerg   /// What processor and OS we're targeting.
49806f32e7eSjoerg   Triple TargetTriple;
49906f32e7eSjoerg 
50006f32e7eSjoerg   /// GlobalISel related APIs.
50106f32e7eSjoerg   std::unique_ptr<CallLowering> CallLoweringInfo;
50206f32e7eSjoerg   std::unique_ptr<LegalizerInfo> Legalizer;
50306f32e7eSjoerg   std::unique_ptr<RegisterBankInfo> RegBankInfo;
50406f32e7eSjoerg   std::unique_ptr<InstructionSelector> InstSelector;
50506f32e7eSjoerg 
50606f32e7eSjoerg private:
50706f32e7eSjoerg   /// Override the stack alignment.
50806f32e7eSjoerg   MaybeAlign StackAlignOverride;
50906f32e7eSjoerg 
51006f32e7eSjoerg   /// Preferred vector width from function attribute.
51106f32e7eSjoerg   unsigned PreferVectorWidthOverride;
51206f32e7eSjoerg 
51306f32e7eSjoerg   /// Resolved preferred vector width from function attribute and subtarget
51406f32e7eSjoerg   /// features.
51506f32e7eSjoerg   unsigned PreferVectorWidth = UINT32_MAX;
51606f32e7eSjoerg 
51706f32e7eSjoerg   /// Required vector width from function attribute.
51806f32e7eSjoerg   unsigned RequiredVectorWidth;
51906f32e7eSjoerg 
52006f32e7eSjoerg   /// True if compiling for 64-bit, false for 16-bit or 32-bit.
521*da58b97aSjoerg   bool In64BitMode = false;
52206f32e7eSjoerg 
52306f32e7eSjoerg   /// True if compiling for 32-bit, false for 16-bit or 64-bit.
524*da58b97aSjoerg   bool In32BitMode = false;
52506f32e7eSjoerg 
52606f32e7eSjoerg   /// True if compiling for 16-bit, false for 32-bit or 64-bit.
527*da58b97aSjoerg   bool In16BitMode = false;
52806f32e7eSjoerg 
52906f32e7eSjoerg   X86SelectionDAGInfo TSInfo;
53006f32e7eSjoerg   // Ordering here is important. X86InstrInfo initializes X86RegisterInfo which
53106f32e7eSjoerg   // X86TargetLowering needs.
53206f32e7eSjoerg   X86InstrInfo InstrInfo;
53306f32e7eSjoerg   X86TargetLowering TLInfo;
53406f32e7eSjoerg   X86FrameLowering FrameLowering;
53506f32e7eSjoerg 
53606f32e7eSjoerg public:
53706f32e7eSjoerg   /// This constructor initializes the data members to match that
53806f32e7eSjoerg   /// of the specified triple.
53906f32e7eSjoerg   ///
540*da58b97aSjoerg   X86Subtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU, StringRef FS,
54106f32e7eSjoerg                const X86TargetMachine &TM, MaybeAlign StackAlignOverride,
54206f32e7eSjoerg                unsigned PreferVectorWidthOverride,
54306f32e7eSjoerg                unsigned RequiredVectorWidth);
54406f32e7eSjoerg 
getTargetLowering()54506f32e7eSjoerg   const X86TargetLowering *getTargetLowering() const override {
54606f32e7eSjoerg     return &TLInfo;
54706f32e7eSjoerg   }
54806f32e7eSjoerg 
getInstrInfo()54906f32e7eSjoerg   const X86InstrInfo *getInstrInfo() const override { return &InstrInfo; }
55006f32e7eSjoerg 
getFrameLowering()55106f32e7eSjoerg   const X86FrameLowering *getFrameLowering() const override {
55206f32e7eSjoerg     return &FrameLowering;
55306f32e7eSjoerg   }
55406f32e7eSjoerg 
getSelectionDAGInfo()55506f32e7eSjoerg   const X86SelectionDAGInfo *getSelectionDAGInfo() const override {
55606f32e7eSjoerg     return &TSInfo;
55706f32e7eSjoerg   }
55806f32e7eSjoerg 
getRegisterInfo()55906f32e7eSjoerg   const X86RegisterInfo *getRegisterInfo() const override {
56006f32e7eSjoerg     return &getInstrInfo()->getRegisterInfo();
56106f32e7eSjoerg   }
56206f32e7eSjoerg 
getTileConfigSize()563*da58b97aSjoerg   unsigned getTileConfigSize() const { return 64; }
getTileConfigAlignment()564*da58b97aSjoerg   Align getTileConfigAlignment() const { return TileConfigAlignment; }
565*da58b97aSjoerg 
56606f32e7eSjoerg   /// Returns the minimum alignment known to hold of the
56706f32e7eSjoerg   /// stack frame on entry to the function and which must be maintained by every
56806f32e7eSjoerg   /// function for this subtarget.
getStackAlignment()56906f32e7eSjoerg   Align getStackAlignment() const { return stackAlignment; }
57006f32e7eSjoerg 
57106f32e7eSjoerg   /// Returns the maximum memset / memcpy size
57206f32e7eSjoerg   /// that still makes it profitable to inline the call.
getMaxInlineSizeThreshold()57306f32e7eSjoerg   unsigned getMaxInlineSizeThreshold() const { return MaxInlineSizeThreshold; }
57406f32e7eSjoerg 
57506f32e7eSjoerg   /// ParseSubtargetFeatures - Parses features string setting specified
57606f32e7eSjoerg   /// subtarget options.  Definition of function is auto generated by tblgen.
577*da58b97aSjoerg   void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
57806f32e7eSjoerg 
57906f32e7eSjoerg   /// Methods used by Global ISel
58006f32e7eSjoerg   const CallLowering *getCallLowering() const override;
58106f32e7eSjoerg   InstructionSelector *getInstructionSelector() const override;
58206f32e7eSjoerg   const LegalizerInfo *getLegalizerInfo() const override;
58306f32e7eSjoerg   const RegisterBankInfo *getRegBankInfo() const override;
58406f32e7eSjoerg 
58506f32e7eSjoerg private:
58606f32e7eSjoerg   /// Initialize the full set of dependencies so we can use an initializer
58706f32e7eSjoerg   /// list for X86Subtarget.
588*da58b97aSjoerg   X86Subtarget &initializeSubtargetDependencies(StringRef CPU,
589*da58b97aSjoerg                                                 StringRef TuneCPU,
590*da58b97aSjoerg                                                 StringRef FS);
591*da58b97aSjoerg   void initSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
59206f32e7eSjoerg 
59306f32e7eSjoerg public:
59406f32e7eSjoerg   /// Is this x86_64? (disregarding specific ABI / programming model)
is64Bit()59506f32e7eSjoerg   bool is64Bit() const {
59606f32e7eSjoerg     return In64BitMode;
59706f32e7eSjoerg   }
59806f32e7eSjoerg 
is32Bit()59906f32e7eSjoerg   bool is32Bit() const {
60006f32e7eSjoerg     return In32BitMode;
60106f32e7eSjoerg   }
60206f32e7eSjoerg 
is16Bit()60306f32e7eSjoerg   bool is16Bit() const {
60406f32e7eSjoerg     return In16BitMode;
60506f32e7eSjoerg   }
60606f32e7eSjoerg 
60706f32e7eSjoerg   /// Is this x86_64 with the ILP32 programming model (x32 ABI)?
isTarget64BitILP32()60806f32e7eSjoerg   bool isTarget64BitILP32() const {
60906f32e7eSjoerg     return In64BitMode && (TargetTriple.getEnvironment() == Triple::GNUX32 ||
61006f32e7eSjoerg                            TargetTriple.isOSNaCl());
61106f32e7eSjoerg   }
61206f32e7eSjoerg 
61306f32e7eSjoerg   /// Is this x86_64 with the LP64 programming model (standard AMD64, no x32)?
isTarget64BitLP64()61406f32e7eSjoerg   bool isTarget64BitLP64() const {
61506f32e7eSjoerg     return In64BitMode && (TargetTriple.getEnvironment() != Triple::GNUX32 &&
61606f32e7eSjoerg                            !TargetTriple.isOSNaCl());
61706f32e7eSjoerg   }
61806f32e7eSjoerg 
getPICStyle()61906f32e7eSjoerg   PICStyles::Style getPICStyle() const { return PICStyle; }
setPICStyle(PICStyles::Style Style)62006f32e7eSjoerg   void setPICStyle(PICStyles::Style Style)  { PICStyle = Style; }
62106f32e7eSjoerg 
hasX87()62206f32e7eSjoerg   bool hasX87() const { return HasX87; }
hasCmpxchg8b()62306f32e7eSjoerg   bool hasCmpxchg8b() const { return HasCmpxchg8b; }
hasNOPL()62406f32e7eSjoerg   bool hasNOPL() const { return HasNOPL; }
62506f32e7eSjoerg   // SSE codegen depends on cmovs, and all SSE1+ processors support them.
62606f32e7eSjoerg   // All 64-bit processors support cmov.
hasCMov()62706f32e7eSjoerg   bool hasCMov() const { return HasCMov || X86SSELevel >= SSE1 || is64Bit(); }
hasSSE1()62806f32e7eSjoerg   bool hasSSE1() const { return X86SSELevel >= SSE1; }
hasSSE2()62906f32e7eSjoerg   bool hasSSE2() const { return X86SSELevel >= SSE2; }
hasSSE3()63006f32e7eSjoerg   bool hasSSE3() const { return X86SSELevel >= SSE3; }
hasSSSE3()63106f32e7eSjoerg   bool hasSSSE3() const { return X86SSELevel >= SSSE3; }
hasSSE41()63206f32e7eSjoerg   bool hasSSE41() const { return X86SSELevel >= SSE41; }
hasSSE42()63306f32e7eSjoerg   bool hasSSE42() const { return X86SSELevel >= SSE42; }
hasAVX()63406f32e7eSjoerg   bool hasAVX() const { return X86SSELevel >= AVX; }
hasAVX2()63506f32e7eSjoerg   bool hasAVX2() const { return X86SSELevel >= AVX2; }
hasAVX512()63606f32e7eSjoerg   bool hasAVX512() const { return X86SSELevel >= AVX512F; }
hasInt256()63706f32e7eSjoerg   bool hasInt256() const { return hasAVX2(); }
hasSSE4A()63806f32e7eSjoerg   bool hasSSE4A() const { return HasSSE4A; }
hasMMX()63906f32e7eSjoerg   bool hasMMX() const { return X863DNowLevel >= MMX; }
has3DNow()64006f32e7eSjoerg   bool has3DNow() const { return X863DNowLevel >= ThreeDNow; }
has3DNowA()64106f32e7eSjoerg   bool has3DNowA() const { return X863DNowLevel >= ThreeDNowA; }
hasPOPCNT()64206f32e7eSjoerg   bool hasPOPCNT() const { return HasPOPCNT; }
hasAES()64306f32e7eSjoerg   bool hasAES() const { return HasAES; }
hasVAES()64406f32e7eSjoerg   bool hasVAES() const { return HasVAES; }
hasFXSR()64506f32e7eSjoerg   bool hasFXSR() const { return HasFXSR; }
hasXSAVE()64606f32e7eSjoerg   bool hasXSAVE() const { return HasXSAVE; }
hasXSAVEOPT()64706f32e7eSjoerg   bool hasXSAVEOPT() const { return HasXSAVEOPT; }
hasXSAVEC()64806f32e7eSjoerg   bool hasXSAVEC() const { return HasXSAVEC; }
hasXSAVES()64906f32e7eSjoerg   bool hasXSAVES() const { return HasXSAVES; }
hasPCLMUL()65006f32e7eSjoerg   bool hasPCLMUL() const { return HasPCLMUL; }
hasVPCLMULQDQ()65106f32e7eSjoerg   bool hasVPCLMULQDQ() const { return HasVPCLMULQDQ; }
hasGFNI()65206f32e7eSjoerg   bool hasGFNI() const { return HasGFNI; }
65306f32e7eSjoerg   // Prefer FMA4 to FMA - its better for commutation/memory folding and
65406f32e7eSjoerg   // has equal or better performance on all supported targets.
hasFMA()65506f32e7eSjoerg   bool hasFMA() const { return HasFMA; }
hasFMA4()65606f32e7eSjoerg   bool hasFMA4() const { return HasFMA4; }
hasAnyFMA()65706f32e7eSjoerg   bool hasAnyFMA() const { return hasFMA() || hasFMA4(); }
hasXOP()65806f32e7eSjoerg   bool hasXOP() const { return HasXOP; }
hasTBM()65906f32e7eSjoerg   bool hasTBM() const { return HasTBM; }
hasLWP()66006f32e7eSjoerg   bool hasLWP() const { return HasLWP; }
hasMOVBE()66106f32e7eSjoerg   bool hasMOVBE() const { return HasMOVBE; }
hasRDRAND()66206f32e7eSjoerg   bool hasRDRAND() const { return HasRDRAND; }
hasF16C()66306f32e7eSjoerg   bool hasF16C() const { return HasF16C; }
hasFSGSBase()66406f32e7eSjoerg   bool hasFSGSBase() const { return HasFSGSBase; }
hasLZCNT()66506f32e7eSjoerg   bool hasLZCNT() const { return HasLZCNT; }
hasBMI()66606f32e7eSjoerg   bool hasBMI() const { return HasBMI; }
hasBMI2()66706f32e7eSjoerg   bool hasBMI2() const { return HasBMI2; }
hasVBMI()66806f32e7eSjoerg   bool hasVBMI() const { return HasVBMI; }
hasVBMI2()66906f32e7eSjoerg   bool hasVBMI2() const { return HasVBMI2; }
hasIFMA()67006f32e7eSjoerg   bool hasIFMA() const { return HasIFMA; }
hasRTM()67106f32e7eSjoerg   bool hasRTM() const { return HasRTM; }
hasADX()67206f32e7eSjoerg   bool hasADX() const { return HasADX; }
hasSHA()67306f32e7eSjoerg   bool hasSHA() const { return HasSHA; }
hasPRFCHW()674*da58b97aSjoerg   bool hasPRFCHW() const { return HasPRFCHW; }
hasPREFETCHWT1()67506f32e7eSjoerg   bool hasPREFETCHWT1() const { return HasPREFETCHWT1; }
hasPrefetchW()676*da58b97aSjoerg   bool hasPrefetchW() const {
677*da58b97aSjoerg     // The PREFETCHW instruction was added with 3DNow but later CPUs gave it
678*da58b97aSjoerg     // its own CPUID bit as part of deprecating 3DNow. Intel eventually added
679*da58b97aSjoerg     // it and KNL has another that prefetches to L2 cache. We assume the
680*da58b97aSjoerg     // L1 version exists if the L2 version does.
681*da58b97aSjoerg     return has3DNow() || hasPRFCHW() || hasPREFETCHWT1();
682*da58b97aSjoerg   }
hasSSEPrefetch()68306f32e7eSjoerg   bool hasSSEPrefetch() const {
68406f32e7eSjoerg     // We implicitly enable these when we have a write prefix supporting cache
68506f32e7eSjoerg     // level OR if we have prfchw, but don't already have a read prefetch from
68606f32e7eSjoerg     // 3dnow.
68706f32e7eSjoerg     return hasSSE1() || (hasPRFCHW() && !has3DNow()) || hasPREFETCHWT1();
68806f32e7eSjoerg   }
hasRDSEED()68906f32e7eSjoerg   bool hasRDSEED() const { return HasRDSEED; }
hasLAHFSAHF()690*da58b97aSjoerg   bool hasLAHFSAHF() const { return HasLAHFSAHF64 || !is64Bit(); }
hasMWAITX()69106f32e7eSjoerg   bool hasMWAITX() const { return HasMWAITX; }
hasCLZERO()69206f32e7eSjoerg   bool hasCLZERO() const { return HasCLZERO; }
hasCLDEMOTE()69306f32e7eSjoerg   bool hasCLDEMOTE() const { return HasCLDEMOTE; }
hasMOVDIRI()69406f32e7eSjoerg   bool hasMOVDIRI() const { return HasMOVDIRI; }
hasMOVDIR64B()69506f32e7eSjoerg   bool hasMOVDIR64B() const { return HasMOVDIR64B; }
hasPTWRITE()69606f32e7eSjoerg   bool hasPTWRITE() const { return HasPTWRITE; }
isSHLDSlow()69706f32e7eSjoerg   bool isSHLDSlow() const { return IsSHLDSlow; }
isPMULLDSlow()69806f32e7eSjoerg   bool isPMULLDSlow() const { return IsPMULLDSlow; }
isPMADDWDSlow()69906f32e7eSjoerg   bool isPMADDWDSlow() const { return IsPMADDWDSlow; }
isUnalignedMem16Slow()70006f32e7eSjoerg   bool isUnalignedMem16Slow() const { return IsUAMem16Slow; }
isUnalignedMem32Slow()70106f32e7eSjoerg   bool isUnalignedMem32Slow() const { return IsUAMem32Slow; }
hasSSEUnalignedMem()70206f32e7eSjoerg   bool hasSSEUnalignedMem() const { return HasSSEUnalignedMem; }
hasCmpxchg16b()70306f32e7eSjoerg   bool hasCmpxchg16b() const { return HasCmpxchg16b && is64Bit(); }
useLeaForSP()70406f32e7eSjoerg   bool useLeaForSP() const { return UseLeaForSP; }
hasPOPCNTFalseDeps()70506f32e7eSjoerg   bool hasPOPCNTFalseDeps() const { return HasPOPCNTFalseDeps; }
hasLZCNTFalseDeps()70606f32e7eSjoerg   bool hasLZCNTFalseDeps() const { return HasLZCNTFalseDeps; }
hasFastVariableShuffle()70706f32e7eSjoerg   bool hasFastVariableShuffle() const {
70806f32e7eSjoerg     return HasFastVariableShuffle;
70906f32e7eSjoerg   }
insertVZEROUPPER()710*da58b97aSjoerg   bool insertVZEROUPPER() const { return InsertVZEROUPPER; }
hasFastGather()71106f32e7eSjoerg   bool hasFastGather() const { return HasFastGather; }
hasFastScalarFSQRT()71206f32e7eSjoerg   bool hasFastScalarFSQRT() const { return HasFastScalarFSQRT; }
hasFastVectorFSQRT()71306f32e7eSjoerg   bool hasFastVectorFSQRT() const { return HasFastVectorFSQRT; }
hasFastLZCNT()71406f32e7eSjoerg   bool hasFastLZCNT() const { return HasFastLZCNT; }
hasFastSHLDRotate()71506f32e7eSjoerg   bool hasFastSHLDRotate() const { return HasFastSHLDRotate; }
hasFastBEXTR()71606f32e7eSjoerg   bool hasFastBEXTR() const { return HasFastBEXTR; }
hasFastHorizontalOps()71706f32e7eSjoerg   bool hasFastHorizontalOps() const { return HasFastHorizontalOps; }
hasFastScalarShiftMasks()71806f32e7eSjoerg   bool hasFastScalarShiftMasks() const { return HasFastScalarShiftMasks; }
hasFastVectorShiftMasks()71906f32e7eSjoerg   bool hasFastVectorShiftMasks() const { return HasFastVectorShiftMasks; }
hasFastMOVBE()720*da58b97aSjoerg   bool hasFastMOVBE() const { return HasFastMOVBE; }
hasMacroFusion()72106f32e7eSjoerg   bool hasMacroFusion() const { return HasMacroFusion; }
hasBranchFusion()72206f32e7eSjoerg   bool hasBranchFusion() const { return HasBranchFusion; }
hasERMSB()72306f32e7eSjoerg   bool hasERMSB() const { return HasERMSB; }
hasFSRM()724*da58b97aSjoerg   bool hasFSRM() const { return HasFSRM; }
hasSlowDivide32()72506f32e7eSjoerg   bool hasSlowDivide32() const { return HasSlowDivide32; }
hasSlowDivide64()72606f32e7eSjoerg   bool hasSlowDivide64() const { return HasSlowDivide64; }
padShortFunctions()72706f32e7eSjoerg   bool padShortFunctions() const { return PadShortFunctions; }
slowTwoMemOps()72806f32e7eSjoerg   bool slowTwoMemOps() const { return SlowTwoMemOps; }
LEAusesAG()72906f32e7eSjoerg   bool LEAusesAG() const { return LEAUsesAG; }
slowLEA()73006f32e7eSjoerg   bool slowLEA() const { return SlowLEA; }
slow3OpsLEA()73106f32e7eSjoerg   bool slow3OpsLEA() const { return Slow3OpsLEA; }
slowIncDec()73206f32e7eSjoerg   bool slowIncDec() const { return SlowIncDec; }
hasCDI()73306f32e7eSjoerg   bool hasCDI() const { return HasCDI; }
hasVPOPCNTDQ()73406f32e7eSjoerg   bool hasVPOPCNTDQ() const { return HasVPOPCNTDQ; }
hasPFI()73506f32e7eSjoerg   bool hasPFI() const { return HasPFI; }
hasERI()73606f32e7eSjoerg   bool hasERI() const { return HasERI; }
hasDQI()73706f32e7eSjoerg   bool hasDQI() const { return HasDQI; }
hasBWI()73806f32e7eSjoerg   bool hasBWI() const { return HasBWI; }
hasVLX()73906f32e7eSjoerg   bool hasVLX() const { return HasVLX; }
hasPKU()74006f32e7eSjoerg   bool hasPKU() const { return HasPKU; }
hasVNNI()74106f32e7eSjoerg   bool hasVNNI() const { return HasVNNI; }
hasBF16()74206f32e7eSjoerg   bool hasBF16() const { return HasBF16; }
hasVP2INTERSECT()74306f32e7eSjoerg   bool hasVP2INTERSECT() const { return HasVP2INTERSECT; }
hasBITALG()74406f32e7eSjoerg   bool hasBITALG() const { return HasBITALG; }
hasSHSTK()74506f32e7eSjoerg   bool hasSHSTK() const { return HasSHSTK; }
hasCLFLUSHOPT()74606f32e7eSjoerg   bool hasCLFLUSHOPT() const { return HasCLFLUSHOPT; }
hasCLWB()74706f32e7eSjoerg   bool hasCLWB() const { return HasCLWB; }
hasWBNOINVD()74806f32e7eSjoerg   bool hasWBNOINVD() const { return HasWBNOINVD; }
hasRDPID()74906f32e7eSjoerg   bool hasRDPID() const { return HasRDPID; }
hasWAITPKG()75006f32e7eSjoerg   bool hasWAITPKG() const { return HasWAITPKG; }
hasPCONFIG()75106f32e7eSjoerg   bool hasPCONFIG() const { return HasPCONFIG; }
hasSGX()75206f32e7eSjoerg   bool hasSGX() const { return HasSGX; }
hasINVPCID()75306f32e7eSjoerg   bool hasINVPCID() const { return HasINVPCID; }
hasENQCMD()75406f32e7eSjoerg   bool hasENQCMD() const { return HasENQCMD; }
hasKL()755*da58b97aSjoerg   bool hasKL() const { return HasKL; }
hasWIDEKL()756*da58b97aSjoerg   bool hasWIDEKL() const { return HasWIDEKL; }
hasHRESET()757*da58b97aSjoerg   bool hasHRESET() const { return HasHRESET; }
hasSERIALIZE()758*da58b97aSjoerg   bool hasSERIALIZE() const { return HasSERIALIZE; }
hasTSXLDTRK()759*da58b97aSjoerg   bool hasTSXLDTRK() const { return HasTSXLDTRK; }
hasUINTR()760*da58b97aSjoerg   bool hasUINTR() const { return HasUINTR; }
useRetpolineIndirectCalls()76106f32e7eSjoerg   bool useRetpolineIndirectCalls() const { return UseRetpolineIndirectCalls; }
useRetpolineIndirectBranches()76206f32e7eSjoerg   bool useRetpolineIndirectBranches() const {
76306f32e7eSjoerg     return UseRetpolineIndirectBranches;
76406f32e7eSjoerg   }
hasAVXVNNI()765*da58b97aSjoerg   bool hasAVXVNNI() const { return HasAVXVNNI; }
hasAMXTILE()766*da58b97aSjoerg   bool hasAMXTILE() const { return HasAMXTILE; }
hasAMXBF16()767*da58b97aSjoerg   bool hasAMXBF16() const { return HasAMXBF16; }
hasAMXINT8()768*da58b97aSjoerg   bool hasAMXINT8() const { return HasAMXINT8; }
useRetpolineExternalThunk()76906f32e7eSjoerg   bool useRetpolineExternalThunk() const { return UseRetpolineExternalThunk; }
770*da58b97aSjoerg 
771*da58b97aSjoerg   // These are generic getters that OR together all of the thunk types
772*da58b97aSjoerg   // supported by the subtarget. Therefore useIndirectThunk*() will return true
773*da58b97aSjoerg   // if any respective thunk feature is enabled.
useIndirectThunkCalls()774*da58b97aSjoerg   bool useIndirectThunkCalls() const {
775*da58b97aSjoerg     return useRetpolineIndirectCalls() || useLVIControlFlowIntegrity();
776*da58b97aSjoerg   }
useIndirectThunkBranches()777*da58b97aSjoerg   bool useIndirectThunkBranches() const {
778*da58b97aSjoerg     return useRetpolineIndirectBranches() || useLVIControlFlowIntegrity();
779*da58b97aSjoerg   }
780*da58b97aSjoerg 
preferMaskRegisters()78106f32e7eSjoerg   bool preferMaskRegisters() const { return PreferMaskRegisters; }
useGLMDivSqrtCosts()782*da58b97aSjoerg   bool useGLMDivSqrtCosts() const { return UseGLMDivSqrtCosts; }
useLVIControlFlowIntegrity()783*da58b97aSjoerg   bool useLVIControlFlowIntegrity() const { return UseLVIControlFlowIntegrity; }
useLVILoadHardening()784*da58b97aSjoerg   bool useLVILoadHardening() const { return UseLVILoadHardening; }
useSpeculativeExecutionSideEffectSuppression()785*da58b97aSjoerg   bool useSpeculativeExecutionSideEffectSuppression() const {
786*da58b97aSjoerg     return UseSpeculativeExecutionSideEffectSuppression;
787*da58b97aSjoerg   }
78806f32e7eSjoerg 
getPreferVectorWidth()78906f32e7eSjoerg   unsigned getPreferVectorWidth() const { return PreferVectorWidth; }
getRequiredVectorWidth()79006f32e7eSjoerg   unsigned getRequiredVectorWidth() const { return RequiredVectorWidth; }
79106f32e7eSjoerg 
79206f32e7eSjoerg   // Helper functions to determine when we should allow widening to 512-bit
79306f32e7eSjoerg   // during codegen.
79406f32e7eSjoerg   // TODO: Currently we're always allowing widening on CPUs without VLX,
79506f32e7eSjoerg   // because for many cases we don't have a better option.
canExtendTo512DQ()79606f32e7eSjoerg   bool canExtendTo512DQ() const {
79706f32e7eSjoerg     return hasAVX512() && (!hasVLX() || getPreferVectorWidth() >= 512);
79806f32e7eSjoerg   }
canExtendTo512BW()79906f32e7eSjoerg   bool canExtendTo512BW() const  {
80006f32e7eSjoerg     return hasBWI() && canExtendTo512DQ();
80106f32e7eSjoerg   }
80206f32e7eSjoerg 
80306f32e7eSjoerg   // If there are no 512-bit vectors and we prefer not to use 512-bit registers,
80406f32e7eSjoerg   // disable them in the legalizer.
useAVX512Regs()80506f32e7eSjoerg   bool useAVX512Regs() const {
80606f32e7eSjoerg     return hasAVX512() && (canExtendTo512DQ() || RequiredVectorWidth > 256);
80706f32e7eSjoerg   }
80806f32e7eSjoerg 
useBWIRegs()80906f32e7eSjoerg   bool useBWIRegs() const {
81006f32e7eSjoerg     return hasBWI() && useAVX512Regs();
81106f32e7eSjoerg   }
81206f32e7eSjoerg 
isXRaySupported()81306f32e7eSjoerg   bool isXRaySupported() const override { return is64Bit(); }
81406f32e7eSjoerg 
81506f32e7eSjoerg   /// TODO: to be removed later and replaced with suitable properties
isAtom()81606f32e7eSjoerg   bool isAtom() const { return X86ProcFamily == IntelAtom; }
isSLM()81706f32e7eSjoerg   bool isSLM() const { return X86ProcFamily == IntelSLM; }
useSoftFloat()81806f32e7eSjoerg   bool useSoftFloat() const { return UseSoftFloat; }
useAA()81906f32e7eSjoerg   bool useAA() const override { return UseAA; }
82006f32e7eSjoerg 
82106f32e7eSjoerg   /// Use mfence if we have SSE2 or we're on x86-64 (even if we asked for
82206f32e7eSjoerg   /// no-sse2). There isn't any reason to disable it if the target processor
82306f32e7eSjoerg   /// supports it.
hasMFence()82406f32e7eSjoerg   bool hasMFence() const { return hasSSE2() || is64Bit(); }
82506f32e7eSjoerg 
getTargetTriple()82606f32e7eSjoerg   const Triple &getTargetTriple() const { return TargetTriple; }
82706f32e7eSjoerg 
isTargetDarwin()82806f32e7eSjoerg   bool isTargetDarwin() const { return TargetTriple.isOSDarwin(); }
isTargetFreeBSD()82906f32e7eSjoerg   bool isTargetFreeBSD() const { return TargetTriple.isOSFreeBSD(); }
isTargetDragonFly()83006f32e7eSjoerg   bool isTargetDragonFly() const { return TargetTriple.isOSDragonFly(); }
isTargetSolaris()83106f32e7eSjoerg   bool isTargetSolaris() const { return TargetTriple.isOSSolaris(); }
isTargetPS4()83206f32e7eSjoerg   bool isTargetPS4() const { return TargetTriple.isPS4CPU(); }
83306f32e7eSjoerg 
isTargetELF()83406f32e7eSjoerg   bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); }
isTargetCOFF()83506f32e7eSjoerg   bool isTargetCOFF() const { return TargetTriple.isOSBinFormatCOFF(); }
isTargetMachO()83606f32e7eSjoerg   bool isTargetMachO() const { return TargetTriple.isOSBinFormatMachO(); }
83706f32e7eSjoerg 
isTargetLinux()83806f32e7eSjoerg   bool isTargetLinux() const { return TargetTriple.isOSLinux(); }
isTargetKFreeBSD()83906f32e7eSjoerg   bool isTargetKFreeBSD() const { return TargetTriple.isOSKFreeBSD(); }
isTargetGlibc()84006f32e7eSjoerg   bool isTargetGlibc() const { return TargetTriple.isOSGlibc(); }
isTargetAndroid()84106f32e7eSjoerg   bool isTargetAndroid() const { return TargetTriple.isAndroid(); }
isTargetNaCl()84206f32e7eSjoerg   bool isTargetNaCl() const { return TargetTriple.isOSNaCl(); }
isTargetNaCl32()84306f32e7eSjoerg   bool isTargetNaCl32() const { return isTargetNaCl() && !is64Bit(); }
isTargetNaCl64()84406f32e7eSjoerg   bool isTargetNaCl64() const { return isTargetNaCl() && is64Bit(); }
isTargetMCU()84506f32e7eSjoerg   bool isTargetMCU() const { return TargetTriple.isOSIAMCU(); }
isTargetFuchsia()84606f32e7eSjoerg   bool isTargetFuchsia() const { return TargetTriple.isOSFuchsia(); }
84706f32e7eSjoerg 
isTargetWindowsMSVC()84806f32e7eSjoerg   bool isTargetWindowsMSVC() const {
84906f32e7eSjoerg     return TargetTriple.isWindowsMSVCEnvironment();
85006f32e7eSjoerg   }
85106f32e7eSjoerg 
isTargetWindowsCoreCLR()85206f32e7eSjoerg   bool isTargetWindowsCoreCLR() const {
85306f32e7eSjoerg     return TargetTriple.isWindowsCoreCLREnvironment();
85406f32e7eSjoerg   }
85506f32e7eSjoerg 
isTargetWindowsCygwin()85606f32e7eSjoerg   bool isTargetWindowsCygwin() const {
85706f32e7eSjoerg     return TargetTriple.isWindowsCygwinEnvironment();
85806f32e7eSjoerg   }
85906f32e7eSjoerg 
isTargetWindowsGNU()86006f32e7eSjoerg   bool isTargetWindowsGNU() const {
86106f32e7eSjoerg     return TargetTriple.isWindowsGNUEnvironment();
86206f32e7eSjoerg   }
86306f32e7eSjoerg 
isTargetWindowsItanium()86406f32e7eSjoerg   bool isTargetWindowsItanium() const {
86506f32e7eSjoerg     return TargetTriple.isWindowsItaniumEnvironment();
86606f32e7eSjoerg   }
86706f32e7eSjoerg 
isTargetCygMing()86806f32e7eSjoerg   bool isTargetCygMing() const { return TargetTriple.isOSCygMing(); }
86906f32e7eSjoerg 
isOSWindows()87006f32e7eSjoerg   bool isOSWindows() const { return TargetTriple.isOSWindows(); }
87106f32e7eSjoerg 
isTargetWin64()87206f32e7eSjoerg   bool isTargetWin64() const { return In64BitMode && isOSWindows(); }
87306f32e7eSjoerg 
isTargetWin32()87406f32e7eSjoerg   bool isTargetWin32() const { return !In64BitMode && isOSWindows(); }
87506f32e7eSjoerg 
isPICStyleGOT()876*da58b97aSjoerg   bool isPICStyleGOT() const { return PICStyle == PICStyles::Style::GOT; }
isPICStyleRIPRel()877*da58b97aSjoerg   bool isPICStyleRIPRel() const { return PICStyle == PICStyles::Style::RIPRel; }
87806f32e7eSjoerg 
isPICStyleStubPIC()87906f32e7eSjoerg   bool isPICStyleStubPIC() const {
880*da58b97aSjoerg     return PICStyle == PICStyles::Style::StubPIC;
88106f32e7eSjoerg   }
88206f32e7eSjoerg 
883*da58b97aSjoerg   bool isPositionIndependent() const;
88406f32e7eSjoerg 
isCallingConvWin64(CallingConv::ID CC)88506f32e7eSjoerg   bool isCallingConvWin64(CallingConv::ID CC) const {
88606f32e7eSjoerg     switch (CC) {
88706f32e7eSjoerg     // On Win64, all these conventions just use the default convention.
88806f32e7eSjoerg     case CallingConv::C:
88906f32e7eSjoerg     case CallingConv::Fast:
89006f32e7eSjoerg     case CallingConv::Tail:
89106f32e7eSjoerg     case CallingConv::Swift:
892*da58b97aSjoerg     case CallingConv::SwiftTail:
89306f32e7eSjoerg     case CallingConv::X86_FastCall:
89406f32e7eSjoerg     case CallingConv::X86_StdCall:
89506f32e7eSjoerg     case CallingConv::X86_ThisCall:
89606f32e7eSjoerg     case CallingConv::X86_VectorCall:
89706f32e7eSjoerg     case CallingConv::Intel_OCL_BI:
89806f32e7eSjoerg       return isTargetWin64();
89906f32e7eSjoerg     // This convention allows using the Win64 convention on other targets.
90006f32e7eSjoerg     case CallingConv::Win64:
90106f32e7eSjoerg       return true;
90206f32e7eSjoerg     // This convention allows using the SysV convention on Windows targets.
90306f32e7eSjoerg     case CallingConv::X86_64_SysV:
90406f32e7eSjoerg       return false;
90506f32e7eSjoerg     // Otherwise, who knows what this is.
90606f32e7eSjoerg     default:
90706f32e7eSjoerg       return false;
90806f32e7eSjoerg     }
90906f32e7eSjoerg   }
91006f32e7eSjoerg 
91106f32e7eSjoerg   /// Classify a global variable reference for the current subtarget according
91206f32e7eSjoerg   /// to how we should reference it in a non-pcrel context.
91306f32e7eSjoerg   unsigned char classifyLocalReference(const GlobalValue *GV) const;
91406f32e7eSjoerg 
91506f32e7eSjoerg   unsigned char classifyGlobalReference(const GlobalValue *GV,
91606f32e7eSjoerg                                         const Module &M) const;
91706f32e7eSjoerg   unsigned char classifyGlobalReference(const GlobalValue *GV) const;
91806f32e7eSjoerg 
91906f32e7eSjoerg   /// Classify a global function reference for the current subtarget.
92006f32e7eSjoerg   unsigned char classifyGlobalFunctionReference(const GlobalValue *GV,
92106f32e7eSjoerg                                                 const Module &M) const;
92206f32e7eSjoerg   unsigned char classifyGlobalFunctionReference(const GlobalValue *GV) const;
92306f32e7eSjoerg 
92406f32e7eSjoerg   /// Classify a blockaddress reference for the current subtarget according to
92506f32e7eSjoerg   /// how we should reference it in a non-pcrel context.
92606f32e7eSjoerg   unsigned char classifyBlockAddressReference() const;
92706f32e7eSjoerg 
92806f32e7eSjoerg   /// Return true if the subtarget allows calls to immediate address.
92906f32e7eSjoerg   bool isLegalToCallImmediateAddr() const;
93006f32e7eSjoerg 
931*da58b97aSjoerg   /// If we are using indirect thunks, we need to expand indirectbr to avoid it
93206f32e7eSjoerg   /// lowering to an actual indirect jump.
enableIndirectBrExpand()93306f32e7eSjoerg   bool enableIndirectBrExpand() const override {
934*da58b97aSjoerg     return useIndirectThunkBranches();
93506f32e7eSjoerg   }
93606f32e7eSjoerg 
93706f32e7eSjoerg   /// Enable the MachineScheduler pass for all X86 subtargets.
enableMachineScheduler()93806f32e7eSjoerg   bool enableMachineScheduler() const override { return true; }
93906f32e7eSjoerg 
94006f32e7eSjoerg   bool enableEarlyIfConversion() const override;
94106f32e7eSjoerg 
94206f32e7eSjoerg   void getPostRAMutations(std::vector<std::unique_ptr<ScheduleDAGMutation>>
94306f32e7eSjoerg                               &Mutations) const override;
94406f32e7eSjoerg 
getAntiDepBreakMode()94506f32e7eSjoerg   AntiDepBreakMode getAntiDepBreakMode() const override {
94606f32e7eSjoerg     return TargetSubtargetInfo::ANTIDEP_CRITICAL;
94706f32e7eSjoerg   }
94806f32e7eSjoerg 
enableAdvancedRASplitCost()949*da58b97aSjoerg   bool enableAdvancedRASplitCost() const override { return false; }
95006f32e7eSjoerg };
95106f32e7eSjoerg 
95206f32e7eSjoerg } // end namespace llvm
95306f32e7eSjoerg 
95406f32e7eSjoerg #endif // LLVM_LIB_TARGET_X86_X86SUBTARGET_H
955