diff --git a/lib/Target/X86/Makefile b/lib/Target/X86/Makefile index 67c5dc4d900..9c513d1ff65 100644 --- a/lib/Target/X86/Makefile +++ b/lib/Target/X86/Makefile @@ -13,7 +13,8 @@ TARGET = X86 BUILT_SOURCES = X86GenRegisterInfo.h.inc X86GenRegisterNames.inc \ X86GenRegisterInfo.inc X86GenInstrNames.inc \ X86GenInstrInfo.inc X86GenAsmWriter.inc \ - X86GenAsmWriter1.inc X86GenDAGISel.inc + X86GenAsmWriter1.inc X86GenDAGISel.inc \ + X86GenSubtarget.inc include $(LEVEL)/Makefile.common diff --git a/lib/Target/X86/X86.h b/lib/Target/X86/X86.h index 7163d346149..ff109c94269 100644 --- a/lib/Target/X86/X86.h +++ b/lib/Target/X86/X86.h @@ -26,7 +26,7 @@ class IntrinsicLowering; class MachineCodeEmitter; enum X86VectorEnum { - NoSSE, SSE, SSE2, SSE3 + AutoDetect, NoSSE, SSE, SSE2, SSE3 }; extern X86VectorEnum X86Vector; diff --git a/lib/Target/X86/X86.td b/lib/Target/X86/X86.td index 874391dda9f..a93d7822e26 100644 --- a/lib/Target/X86/X86.td +++ b/lib/Target/X86/X86.td @@ -16,6 +16,75 @@ // include "../Target.td" +//===----------------------------------------------------------------------===// +// X86 Subtarget features. +// + +def Feature64Bit : SubtargetFeature<"64bit", "bool", "Is64Bit", + "Enable 64-bit instructions">; +def FeatureMMX : SubtargetFeature<"mmx", "bool", "HasMMX", + "Enable MMX instructions">; +def FeatureSSE : SubtargetFeature<"sse", "bool", "HasSSE", + "Enable SSE instructions">; +def FeatureSSE2 : SubtargetFeature<"sse2", "bool", "HasSSE2", + "Enable SSE2 instructions">; +def FeatureSSE3 : SubtargetFeature<"sse3", "bool", "HasSSE3", + "Enable SSE3 instructions">; +def Feature3DNow : SubtargetFeature<"3dnow", "bool", "Has3DNow", + "Enable 3DNow! instructions">; +def Feature3DNowA : SubtargetFeature<"3dnowa", "bool", "Has3DNowA", + "Enable 3DNow! Athlon instructions">; + +//===----------------------------------------------------------------------===// +// X86 processors supported. +//===----------------------------------------------------------------------===// + +class Proc Features> + : Processor; + +def : Proc<"generic", []>; +def : Proc<"i386", []>; +def : Proc<"i486", []>; +def : Proc<"i586", []>; +def : Proc<"pentium", []>; +def : Proc<"pentium-mmx", [FeatureMMX]>; +def : Proc<"i686", []>; +def : Proc<"pentiumpro", []>; +def : Proc<"pentium2", [FeatureMMX]>; +def : Proc<"celeron", [FeatureMMX]>; +def : Proc<"pentium3", [FeatureMMX, FeatureSSE]>; +def : Proc<"pentium3m", [FeatureMMX, FeatureSSE]>; +def : Proc<"pentium-m", [FeatureMMX, FeatureSSE, FeatureSSE2]>; +def : Proc<"pentium4", [FeatureMMX, FeatureSSE, FeatureSSE2]>; +def : Proc<"pentium4m", [FeatureMMX, FeatureSSE, FeatureSSE2]>; +def : Proc<"prescott", [FeatureMMX, FeatureSSE, FeatureSSE2, + FeatureSSE3]>; +def : Proc<"x86-64", [FeatureMMX, FeatureSSE, FeatureSSE2, Feature64Bit]>; +def : Proc<"nocona", [FeatureMMX, FeatureSSE, FeatureSSE2, + FeatureSSE3, Feature64Bit]>; + +def : Proc<"k6", [FeatureMMX]>; +def : Proc<"k6-2", [FeatureMMX, Feature3DNow]>; +def : Proc<"k6-3", [FeatureMMX, Feature3DNow]>; +def : Proc<"athlon", [FeatureMMX, Feature3DNow, Feature3DNowA]>; +def : Proc<"athlon-tbird", [FeatureMMX, Feature3DNow, Feature3DNowA]>; +def : Proc<"athlon-4", [FeatureMMX, FeatureSSE, Feature3DNow, Feature3DNowA]>; +def : Proc<"athlon-xp", [FeatureMMX, FeatureSSE, Feature3DNow, Feature3DNowA]>; +def : Proc<"athlon-mp", [FeatureMMX, FeatureSSE, Feature3DNow, Feature3DNowA]>; +def : Proc<"k8", [FeatureMMX, FeatureSSE, FeatureSSE2, Feature3DNow, + Feature3DNowA, Feature64Bit]>; +def : Proc<"opteron", [FeatureMMX, FeatureSSE, FeatureSSE2, Feature3DNow, + Feature3DNowA, Feature64Bit]>; +def : Proc<"athlon64", [FeatureMMX, FeatureSSE, FeatureSSE2, Feature3DNow, + Feature3DNowA, Feature64Bit]>; +def : Proc<"athlon-fx", [FeatureMMX, FeatureSSE, FeatureSSE2, Feature3DNow, + Feature3DNowA, Feature64Bit]>; + +def : Proc<"winchip-c6", [FeatureMMX]>; +def : Proc<"winchip2", [FeatureMMX, Feature3DNow]>; +def : Proc<"c3", [FeatureMMX, Feature3DNow]>; +def : Proc<"c3-2", [FeatureMMX, FeatureSSE]>; + //===----------------------------------------------------------------------===// // Register File Description //===----------------------------------------------------------------------===// diff --git a/lib/Target/X86/X86Subtarget.cpp b/lib/Target/X86/X86Subtarget.cpp index 80f12b008cc..e523f1448e0 100644 --- a/lib/Target/X86/X86Subtarget.cpp +++ b/lib/Target/X86/X86Subtarget.cpp @@ -13,11 +13,64 @@ #include "X86Subtarget.h" #include "llvm/Module.h" +#include "X86GenSubtarget.inc" using namespace llvm; +#if defined(__APPLE__) +#include +#include +#include +#include + +/// GetCurrentX86CPU - Returns the current CPUs features. +static const char *GetCurrentX86CPU() { + host_basic_info_data_t hostInfo; + mach_msg_type_number_t infoCount; + + infoCount = HOST_BASIC_INFO_COUNT; + host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo, + &infoCount); + + if (hostInfo.cpu_type != CPU_TYPE_I386) return "generic"; + + switch(hostInfo.cpu_subtype) { + case CPU_SUBTYPE_386: return "i386"; + case CPU_SUBTYPE_486: + case CPU_SUBTYPE_486SX: return "i486"; + case CPU_SUBTYPE_PENT: return "pentium"; + case CPU_SUBTYPE_PENTPRO: return "pentiumpro"; + case CPU_SUBTYPE_PENTII_M3: return "pentium2"; + case CPU_SUBTYPE_PENTII_M5: return "pentium2"; + case CPU_SUBTYPE_CELERON: + case CPU_SUBTYPE_CELERON_MOBILE: return "celeron"; + case CPU_SUBTYPE_PENTIUM_3: return "pentium3"; + case CPU_SUBTYPE_PENTIUM_3_M: return "pentium3m"; + case CPU_SUBTYPE_PENTIUM_3_XEON: return "pentium3"; // FIXME: not sure. + case CPU_SUBTYPE_PENTIUM_M: return "pentium-m"; + case CPU_SUBTYPE_PENTIUM_4: return "pentium4"; + case CPU_SUBTYPE_PENTIUM_4_M: return "pentium4m"; + // FIXME: prescott, yonah? Check CPU_THREADTYPE_INTEL_HTT? + case CPU_SUBTYPE_XEON: + case CPU_SUBTYPE_XEON_MP: return "nocona"; + default: ; + } + + return "generic"; +} +#endif + X86Subtarget::X86Subtarget(const Module &M, const std::string &FS) : stackAlignment(8), indirectExternAndWeakGlobals(false) { + // Determine default and user specified characteristics + std::string CPU = "generic"; +#if defined(__APPLE__) + CPU = GetCurrentX86CPU(); +#endif + + // Parse features string. + ParseSubtargetFeatures(FS, CPU); + // Default to ELF unless otherwise specified. TargetType = isELF; diff --git a/lib/Target/X86/X86Subtarget.h b/lib/Target/X86/X86Subtarget.h index 22b611bfff0..072b54ede20 100644 --- a/lib/Target/X86/X86Subtarget.h +++ b/lib/Target/X86/X86Subtarget.h @@ -30,6 +30,14 @@ protected: /// Used by instruction selector bool indirectExternAndWeakGlobals; + /// Arch. features used by isel. + bool Is64Bit; + bool HasMMX; + bool HasSSE; + bool HasSSE2; + bool HasSSE3; + bool Has3DNow; + bool Has3DNowA; public: enum { isELF, isCygwin, isDarwin, isWindows @@ -51,6 +59,19 @@ public: bool getIndirectExternAndWeakGlobals() const { return indirectExternAndWeakGlobals; } + + /// ParseSubtargetFeatures - Parses features string setting specified + /// subtarget options. Definition of function is auto generated by tblgen. + void ParseSubtargetFeatures(const std::string &FS, const std::string &CPU); + + bool is64Bit() const { return Is64Bit; } + + bool hasMMX() const { return HasMMX; } + bool hasSSE() const { return HasSSE; } + bool hasSSE2() const { return HasSSE2; } + bool hasSSE3() const { return HasSSE3; } + bool has3DNow() const { return Has3DNow; } + bool has3DNowA() const { return Has3DNowA; } }; } // End llvm namespace diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp index 2893e3d491f..3e501fffe88 100644 --- a/lib/Target/X86/X86TargetMachine.cpp +++ b/lib/Target/X86/X86TargetMachine.cpp @@ -26,7 +26,7 @@ #include using namespace llvm; -X86VectorEnum llvm::X86Vector = NoSSE; +X86VectorEnum llvm::X86Vector = AutoDetect; bool llvm::X86ScalarSSE = false; bool llvm::X86DAGIsel = false; @@ -61,7 +61,7 @@ namespace { clEnumValN(SSE2, "sse2", " Enable SSE and SSE2 support"), clEnumValN(SSE3, "sse3", " Enable SSE, SSE2, and SSE3 support"), clEnumValEnd), - cl::location(X86Vector), cl::init(NoSSE)); + cl::location(X86Vector), cl::init(AutoDetect)); // Register the target. RegisterTarget X("x86", " IA-32 (Pentium and above)"); @@ -102,6 +102,16 @@ X86TargetMachine::X86TargetMachine(const Module &M, FrameInfo(TargetFrameInfo::StackGrowsDown, Subtarget.getStackAlignment(), -4), JITInfo(*this) { + if (X86Vector == AutoDetect) { + X86Vector = NoSSE; + if (Subtarget.hasSSE()) + X86Vector = SSE; + if (Subtarget.hasSSE2()) + X86Vector = SSE2; + if (Subtarget.hasSSE3()) + X86Vector = SSE3; + } + // Scalar SSE FP requires at least SSE2 X86ScalarSSE &= X86Vector >= SSE2;