From a26eb5e1a7e36521caff281da687764a0c43e428 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Fri, 6 Oct 2006 09:17:41 +0000 Subject: [PATCH] Still need to support -mcpu=<> or cross compilation will fail. Doh. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30764 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/Makefile | 3 +- lib/Target/X86/X86.td | 73 ++++++++++++++++++++++ lib/Target/X86/X86Subtarget.cpp | 107 +++++++++++++++++++++++++++++++- lib/Target/X86/X86Subtarget.h | 19 +++++- 4 files changed, 195 insertions(+), 7 deletions(-) diff --git a/lib/Target/X86/Makefile b/lib/Target/X86/Makefile index b17703f23fb..a793a9d00ea 100644 --- a/lib/Target/X86/Makefile +++ b/lib/Target/X86/Makefile @@ -14,6 +14,7 @@ EXTRA_DIST = README.txt 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.td b/lib/Target/X86/X86.td index 7ed912bd9f1..c4b3d8635ff 100644 --- a/lib/Target/X86/X86.td +++ b/lib/Target/X86/X86.td @@ -16,6 +16,79 @@ // include "../Target.td" +//===----------------------------------------------------------------------===// +// X86 Subtarget features. +// + +def Feature64Bit : SubtargetFeature<"64bit", "HasX86_64", "true", + "Support 64-bit instructions">; +def FeatureMMX : SubtargetFeature<"mmx","X86SSELevel", "MMX", + "Enable MMX instructions">; +def FeatureSSE1 : SubtargetFeature<"sse", "X86SSELevel", "SSE1", + "Enable SSE instructions">; +def FeatureSSE2 : SubtargetFeature<"sse2", "X86SSELevel", "SSE2", + "Enable SSE2 instructions">; +def FeatureSSE3 : SubtargetFeature<"sse3", "X86SSELevel", "SSE3", + "Enable SSE3 instructions">; +def Feature3DNow : SubtargetFeature<"3dnow", "X863DNowLevel", "ThreeDNow", + "Enable 3DNow! instructions">; +def Feature3DNowA : SubtargetFeature<"3dnowa", "X863DNowLevel", "ThreeDNowA", + "Enable 3DNow! Athlon instructions">; + +//===----------------------------------------------------------------------===// +// X86 processors supported. +//===----------------------------------------------------------------------===// + +class Proc Features> + : Processor; + +def : Proc<"generic", []>; +def : Proc<"i386", []>; +def : Proc<"i486", []>; +def : Proc<"pentium", []>; +def : Proc<"pentium-mmx", [FeatureMMX]>; +def : Proc<"i686", []>; +def : Proc<"pentiumpro", []>; +def : Proc<"pentium2", [FeatureMMX]>; +def : Proc<"pentium3", [FeatureMMX, FeatureSSE1]>; +def : Proc<"pentium-m", [FeatureMMX, FeatureSSE1, FeatureSSE2]>; +def : Proc<"pentium4", [FeatureMMX, FeatureSSE1, FeatureSSE2]>; +def : Proc<"x86-64", [FeatureMMX, FeatureSSE1, FeatureSSE2, + Feature64Bit]>; +def : Proc<"yonah", [FeatureMMX, FeatureSSE1, FeatureSSE2, + FeatureSSE3]>; +def : Proc<"prescott", [FeatureMMX, FeatureSSE1, FeatureSSE2, + FeatureSSE3]>; +def : Proc<"nocona", [FeatureMMX, FeatureSSE1, FeatureSSE2, + FeatureSSE3, Feature64Bit]>; +def : Proc<"core2", [FeatureMMX, FeatureSSE1, 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, FeatureSSE1, Feature3DNow, + Feature3DNowA]>; +def : Proc<"athlon-xp", [FeatureMMX, FeatureSSE1, Feature3DNow, + Feature3DNowA]>; +def : Proc<"athlon-mp", [FeatureMMX, FeatureSSE1, Feature3DNow, + Feature3DNowA]>; +def : Proc<"k8", [FeatureMMX, FeatureSSE1, FeatureSSE2, + Feature3DNow, Feature3DNowA, Feature64Bit]>; +def : Proc<"opteron", [FeatureMMX, FeatureSSE1, FeatureSSE2, + Feature3DNow, Feature3DNowA, Feature64Bit]>; +def : Proc<"athlon64", [FeatureMMX, FeatureSSE1, FeatureSSE2, + Feature3DNow, Feature3DNowA, Feature64Bit]>; +def : Proc<"athlon-fx", [FeatureMMX, FeatureSSE1, FeatureSSE2, + Feature3DNow, Feature3DNowA, Feature64Bit]>; + +def : Proc<"winchip-c6", [FeatureMMX]>; +def : Proc<"winchip2", [FeatureMMX, Feature3DNow]>; +def : Proc<"c3", [FeatureMMX, Feature3DNow]>; +def : Proc<"c3-2", [FeatureMMX, FeatureSSE1]>; + //===----------------------------------------------------------------------===// // Register File Description //===----------------------------------------------------------------------===// diff --git a/lib/Target/X86/X86Subtarget.cpp b/lib/Target/X86/X86Subtarget.cpp index caa846bc59d..3fe25fdac4d 100644 --- a/lib/Target/X86/X86Subtarget.cpp +++ b/lib/Target/X86/X86Subtarget.cpp @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #include "X86Subtarget.h" -//#include "X86GenSubtarget.inc" +#include "X86GenSubtarget.inc" #include "llvm/Module.h" #include "llvm/Support/CommandLine.h" #include @@ -72,7 +72,7 @@ static inline bool GetCpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEB return true; } -void X86Subtarget::DetectSubtargetFeatures() { +void X86Subtarget::AutoDetectSubtargetFeatures() { unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; union { unsigned u[3]; @@ -96,6 +96,100 @@ void X86Subtarget::DetectSubtargetFeatures() { } } +static const char *GetCurrentX86CPU() { + unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; + if (GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX)) + return "generic"; + unsigned Family = (EAX >> 8) & 0xf; // Bits 8 - 11 + unsigned Model = (EAX >> 4) & 0xf; // Bits 4 - 7 + GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX); + bool Em64T = EDX & (1 << 29); + + union { + unsigned u[3]; + char c[12]; + } text; + + GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1); + if (memcmp(text.c, "GenuineIntel", 12) == 0) { + switch (Family) { + case 3: + return "i386"; + case 4: + return "i486"; + case 5: + switch (Model) { + case 4: return "pentium-mmx"; + default: return "pentium"; + } + case 6: + switch (Model) { + case 1: return "pentiumpro"; + case 3: + case 5: + case 6: return "pentium2"; + case 7: + case 8: + case 10: + case 11: return "pentium3"; + case 9: + case 13: return "pentium-m"; + case 14: return "yonah"; + case 15: return "core2"; + default: return "i686"; + } + case 15: { + switch (Model) { + case 3: + case 4: + return (Em64T) ? "nocona" : "prescott"; + default: + return (Em64T) ? "x86-64" : "pentium4"; + } + } + + default: + return "generic"; + } + } else if (memcmp(text.c, "AuthenticAMD", 12) == 0) { + // FIXME: this poorly matches the generated SubtargetFeatureKV table. There + // appears to be no way to generate the wide variety of AMD-specific targets + // from the information returned from CPUID. + switch (Family) { + case 4: + return "i486"; + case 5: + switch (Model) { + case 6: + case 7: return "k6"; + case 8: return "k6-2"; + case 9: + case 13: return "k6-3"; + default: return "pentium"; + } + case 6: + switch (Model) { + case 4: return "athlon-tbird"; + case 6: + case 7: + case 8: return "athlon-mp"; + case 10: return "athlon-xp"; + default: return "athlon"; + } + case 15: + switch (Model) { + case 5: return "athlon-fx"; // also opteron + default: return "athlon64"; + } + + default: + return "generic"; + } + } else { + return "generic"; + } +} + X86Subtarget::X86Subtarget(const Module &M, const std::string &FS, bool is64Bit) : AsmFlavor(AsmWriterFlavor) , X86SSELevel(NoMMXSSE) @@ -107,7 +201,14 @@ X86Subtarget::X86Subtarget(const Module &M, const std::string &FS, bool is64Bit) , TargetType(isELF) { // Default to ELF unless otherwise specified. // Determine default and user specified characteristics - DetectSubtargetFeatures(); + if (!FS.empty()) { + // If feature string is not empty, parse features string. + std::string CPU = GetCurrentX86CPU(); + ParseSubtargetFeatures(FS, CPU); + } else + // Otherwise, use CPUID to auto-detect feature set. + AutoDetectSubtargetFeatures(); + if (Is64Bit && !HasX86_64) { std::cerr << "Warning: Generation of 64-bit code for a 32-bit processor " "requested.\n"; diff --git a/lib/Target/X86/X86Subtarget.h b/lib/Target/X86/X86Subtarget.h index e781d9527c8..b4907b64cf4 100644 --- a/lib/Target/X86/X86Subtarget.h +++ b/lib/Target/X86/X86Subtarget.h @@ -32,12 +32,19 @@ protected: NoMMXSSE, MMX, SSE1, SSE2, SSE3 }; + enum X863DNowEnum { + NoThreeDNow, ThreeDNow, ThreeDNowA + }; + /// AsmFlavor - Which x86 asm dialect to use. AsmWriterFlavorTy AsmFlavor; /// X86SSELevel - MMX, SSE1, SSE2, SSE3, or none supported. X86SSEEnum X86SSELevel; + /// X863DNowLevel - 3DNow or 3DNow Athlon, or none supported. + X863DNowEnum X863DNowLevel; + /// HasX86_64 - True if the processor supports X86-64 instructions. bool HasX86_64; @@ -74,9 +81,13 @@ public: /// aligned. unsigned getMinRepStrSizeThreshold() const { return MinRepStrSizeThreshold; } - /// DetectSubtargetFeatures - Auto-detect CPU features using CPUID instruction. - /// - void DetectSubtargetFeatures(); + /// 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); + + /// AutoDetectSubtargetFeatures - Auto-detect CPU features using CPUID + /// instruction. + void AutoDetectSubtargetFeatures(); bool is64Bit() const { return Is64Bit; } @@ -84,6 +95,8 @@ public: bool hasSSE1() const { return X86SSELevel >= SSE1; } bool hasSSE2() const { return X86SSELevel >= SSE2; } bool hasSSE3() const { return X86SSELevel >= SSE3; } + bool has3DNow() const { return X863DNowLevel >= ThreeDNow; } + bool has3DNowA() const { return X863DNowLevel >= ThreeDNowA; } bool isFlavorAtt() const { return AsmFlavor == att; } bool isFlavorIntel() const { return AsmFlavor == intel; } -- 2.34.1