#ifndef X86SUBTARGET_H
#define X86SUBTARGET_H
#include "llvm/ADT/Triple.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/Target/TargetSubtargetInfo.h"
#include <string>
#define GET_SUBTARGETINFO_HEADER
#include "X86GenSubtargetInfo.inc"
namespace llvm {
class GlobalValue;
class StringRef;
class TargetMachine;
namespace PICStyles {
enum Style {
StubPIC, StubDynamicNoPIC, GOT, RIPRel, None };
}
class X86Subtarget : public X86GenSubtargetInfo {
protected:
enum X86SSEEnum {
NoMMXSSE, MMX, SSE1, SSE2, SSE3, SSSE3, SSE41, SSE42, AVX, AVX2, AVX512F
};
enum X863DNowEnum {
NoThreeDNow, ThreeDNow, ThreeDNowA
};
enum X86ProcFamilyEnum {
Others, IntelAtom, IntelSLM
};
X86ProcFamilyEnum X86ProcFamily;
PICStyles::Style PICStyle;
X86SSEEnum X86SSELevel;
X863DNowEnum X863DNowLevel;
bool HasCMov;
bool HasX86_64;
bool HasPOPCNT;
bool HasSSE4A;
bool HasAES;
bool HasPCLMUL;
bool HasFMA;
bool HasFMA4;
bool HasXOP;
bool HasTBM;
bool HasMOVBE;
bool HasRDRAND;
bool HasF16C;
bool HasFSGSBase;
bool HasLZCNT;
bool HasBMI;
bool HasBMI2;
bool HasRTM;
bool HasHLE;
bool HasADX;
bool HasSHA;
bool HasPRFCHW;
bool HasRDSEED;
bool IsBTMemSlow;
bool IsSHLDSlow;
bool IsUAMemFast;
bool HasVectorUAMem;
bool HasCmpxchg16b;
bool UseLeaForSP;
bool HasSlowDivide;
bool PostRAScheduler;
bool PadShortFunctions;
bool CallRegIndirect;
bool LEAUsesAG;
bool HasPFI;
bool HasERI;
bool HasCDI;
unsigned stackAlignment;
unsigned MaxInlineSizeThreshold;
Triple TargetTriple;
InstrItineraryData InstrItins;
private:
unsigned StackAlignOverride;
bool In64BitMode;
bool In32BitMode;
bool In16BitMode;
public:
X86Subtarget(const std::string &TT, const std::string &CPU,
const std::string &FS,
unsigned StackAlignOverride);
unsigned getStackAlignment() const { return stackAlignment; }
unsigned getMaxInlineSizeThreshold() const { return MaxInlineSizeThreshold; }
void ParseSubtargetFeatures(StringRef CPU, StringRef FS);
virtual void resetSubtargetFeatures(const MachineFunction *MF);
private:
void initializeEnvironment();
void resetSubtargetFeatures(StringRef CPU, StringRef FS);
public:
bool is64Bit() const {
return In64BitMode;
}
bool is32Bit() const {
return In32BitMode;
}
bool is16Bit() const {
return In16BitMode;
}
bool isTarget64BitILP32() const {
return In64BitMode && (TargetTriple.getEnvironment() == Triple::GNUX32 ||
TargetTriple.getOS() == Triple::NaCl);
}
bool isTarget64BitLP64() const {
return In64BitMode && (TargetTriple.getEnvironment() != Triple::GNUX32);
}
PICStyles::Style getPICStyle() const { return PICStyle; }
void setPICStyle(PICStyles::Style Style) { PICStyle = Style; }
bool hasCMov() const { return HasCMov; }
bool hasMMX() const { return X86SSELevel >= MMX; }
bool hasSSE1() const { return X86SSELevel >= SSE1; }
bool hasSSE2() const { return X86SSELevel >= SSE2; }
bool hasSSE3() const { return X86SSELevel >= SSE3; }
bool hasSSSE3() const { return X86SSELevel >= SSSE3; }
bool hasSSE41() const { return X86SSELevel >= SSE41; }
bool hasSSE42() const { return X86SSELevel >= SSE42; }
bool hasAVX() const { return X86SSELevel >= AVX; }
bool hasAVX2() const { return X86SSELevel >= AVX2; }
bool hasAVX512() const { return X86SSELevel >= AVX512F; }
bool hasFp256() const { return hasAVX(); }
bool hasInt256() const { return hasAVX2(); }
bool hasSSE4A() const { return HasSSE4A; }
bool has3DNow() const { return X863DNowLevel >= ThreeDNow; }
bool has3DNowA() const { return X863DNowLevel >= ThreeDNowA; }
bool hasPOPCNT() const { return HasPOPCNT; }
bool hasAES() const { return HasAES; }
bool hasPCLMUL() const { return HasPCLMUL; }
bool hasFMA() const { return HasFMA; }
bool hasFMA4() const { return HasFMA4 && !HasFMA; }
bool hasXOP() const { return HasXOP; }
bool hasTBM() const { return HasTBM; }
bool hasMOVBE() const { return HasMOVBE; }
bool hasRDRAND() const { return HasRDRAND; }
bool hasF16C() const { return HasF16C; }
bool hasFSGSBase() const { return HasFSGSBase; }
bool hasLZCNT() const { return HasLZCNT; }
bool hasBMI() const { return HasBMI; }
bool hasBMI2() const { return HasBMI2; }
bool hasRTM() const { return HasRTM; }
bool hasHLE() const { return HasHLE; }
bool hasADX() const { return HasADX; }
bool hasSHA() const { return HasSHA; }
bool hasPRFCHW() const { return HasPRFCHW; }
bool hasRDSEED() const { return HasRDSEED; }
bool isBTMemSlow() const { return IsBTMemSlow; }
bool isSHLDSlow() const { return IsSHLDSlow; }
bool isUnalignedMemAccessFast() const { return IsUAMemFast; }
bool hasVectorUAMem() const { return HasVectorUAMem; }
bool hasCmpxchg16b() const { return HasCmpxchg16b; }
bool useLeaForSP() const { return UseLeaForSP; }
bool hasSlowDivide() const { return HasSlowDivide; }
bool padShortFunctions() const { return PadShortFunctions; }
bool callRegIndirect() const { return CallRegIndirect; }
bool LEAusesAG() const { return LEAUsesAG; }
bool hasCDI() const { return HasCDI; }
bool hasPFI() const { return HasPFI; }
bool hasERI() const { return HasERI; }
bool isAtom() const { return X86ProcFamily == IntelAtom; }
const Triple &getTargetTriple() const { return TargetTriple; }
bool isTargetDarwin() const { return TargetTriple.isOSDarwin(); }
bool isTargetFreeBSD() const {
return TargetTriple.getOS() == Triple::FreeBSD;
}
bool isTargetSolaris() const {
return TargetTriple.getOS() == Triple::Solaris;
}
bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); }
bool isTargetCOFF() const { return TargetTriple.isOSBinFormatCOFF(); }
bool isTargetMacho() const { return TargetTriple.isOSBinFormatMachO(); }
bool isTargetLinux() const { return TargetTriple.isOSLinux(); }
bool isTargetNaCl() const { return TargetTriple.isOSNaCl(); }
bool isTargetNaCl32() const { return isTargetNaCl() && !is64Bit(); }
bool isTargetNaCl64() const { return isTargetNaCl() && is64Bit(); }
bool isTargetWindows() const { return TargetTriple.getOS() == Triple::Win32; }
bool isTargetMingw() const { return TargetTriple.getOS() == Triple::MinGW32; }
bool isTargetCygwin() const { return TargetTriple.getOS() == Triple::Cygwin; }
bool isTargetCygMing() const { return TargetTriple.isOSCygMing(); }
bool isOSWindows() const { return TargetTriple.isOSWindows(); }
bool isTargetWin64() const {
return In64BitMode && TargetTriple.isOSWindows();
}
bool isTargetWin32() const {
return !In64BitMode && (isTargetCygMing() || isTargetWindows());
}
bool isPICStyleSet() const { return PICStyle != PICStyles::None; }
bool isPICStyleGOT() const { return PICStyle == PICStyles::GOT; }
bool isPICStyleRIPRel() const { return PICStyle == PICStyles::RIPRel; }
bool isPICStyleStubPIC() const {
return PICStyle == PICStyles::StubPIC;
}
bool isPICStyleStubNoDynamic() const {
return PICStyle == PICStyles::StubDynamicNoPIC;
}
bool isPICStyleStubAny() const {
return PICStyle == PICStyles::StubDynamicNoPIC ||
PICStyle == PICStyles::StubPIC;
}
bool isCallingConvWin64(CallingConv::ID CC) const {
return (isTargetWin64() && CC != CallingConv::X86_64_SysV) ||
CC == CallingConv::X86_64_Win64;
}
unsigned char ClassifyGlobalReference(const GlobalValue *GV,
const TargetMachine &TM)const;
unsigned char ClassifyBlockAddressReference() const;
bool IsLegalToCallImmediateAddr(const TargetMachine &TM) const;
const char *getBZeroEntry() const;
bool hasSinCos() const;
bool enableMachineScheduler() const LLVM_OVERRIDE { return true; }
bool enablePostRAScheduler(CodeGenOpt::Level OptLevel,
TargetSubtargetInfo::AntiDepBreakMode& Mode,
RegClassVector& CriticalPathRCs) const;
bool postRAScheduler() const { return PostRAScheduler; }
const InstrItineraryData &getInstrItineraryData() const { return InstrItins; }
};
}
#endif