X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FX86%2FX86Subtarget.cpp;h=0d02e5ee472bbfd51479efc715e45008c01b89d6;hb=d9e3385ced2dc887e2fe8e1c071bd2611e4d3ede;hp=2812fdbc72e734a6ac7816346924c71d8983159e;hpb=e2c920845a407957b8ae2600feae1f4c85a0d4d0;p=oota-llvm.git diff --git a/lib/Target/X86/X86Subtarget.cpp b/lib/Target/X86/X86Subtarget.cpp index 2812fdbc72e..0d02e5ee472 100644 --- a/lib/Target/X86/X86Subtarget.cpp +++ b/lib/Target/X86/X86Subtarget.cpp @@ -15,24 +15,33 @@ #include "X86Subtarget.h" #include "X86InstrInfo.h" #include "X86GenSubtarget.inc" -#include "llvm/Module.h" -#include "llvm/Support/CommandLine.h" +#include "llvm/GlobalValue.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/System/Host.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" +#include "llvm/ADT/SmallVector.h" using namespace llvm; #if defined(_MSC_VER) - #include +#include #endif -static cl::opt -AsmWriterFlavor("x86-asm-syntax", cl::init(X86Subtarget::Unset), - cl::desc("Choose style of code to emit from X86 backend:"), - cl::values( - clEnumValN(X86Subtarget::ATT, "att", "Emit AT&T-style assembly"), - clEnumValN(X86Subtarget::Intel, "intel", "Emit Intel-style assembly"), - clEnumValEnd)); +/// ClassifyBlockAddressReference - Classify a blockaddress reference for the +/// current subtarget according to how we should reference it in a non-pcrel +/// context. +unsigned char X86Subtarget:: +ClassifyBlockAddressReference() const { + if (isPICStyleGOT()) // 32-bit ELF targets. + return X86II::MO_GOTOFF; + + if (isPICStyleStubPIC()) // Darwin/32 in PIC mode. + return X86II::MO_PIC_BASE_OFFSET; + + // Direct static reference to label. + return X86II::MO_NO_FLAG; +} /// ClassifyGlobalReference - Classify a global variable reference for the /// current subtarget according to how we should reference it in a non-pcrel @@ -44,26 +53,33 @@ ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM) const { if (GV->hasDLLImportLinkage()) return X86II::MO_DLLIMPORT; + // Determine whether this is a reference to a definition or a declaration. + // Materializable GVs (in JIT lazy compilation mode) do not require an extra + // load from stub. + bool isDecl = GV->hasAvailableExternallyLinkage(); + if (GV->isDeclaration() && !GV->isMaterializable()) + isDecl = true; + // X86-64 in PIC mode. if (isPICStyleRIPRel()) { // Large model never uses stubs. if (TM.getCodeModel() == CodeModel::Large) return X86II::MO_NO_FLAG; - if (isTargetDarwin()) { - // If symbol visibility is hidden, the extra load is not needed if - // target is x86-64 or the symbol is definitely defined in the current - // translation unit. - if (GV->hasDefaultVisibility() && - (GV->isDeclaration() || GV->isWeakForLinker())) - return X86II::MO_GOTPCREL; - } else { - assert(isTargetELF() && "Unknown rip-relative target"); - - // Extra load is needed for all externally visible. - if (!GV->hasLocalLinkage() && GV->hasDefaultVisibility()) - return X86II::MO_GOTPCREL; - } + if (isTargetDarwin()) { + // If symbol visibility is hidden, the extra load is not needed if + // target is x86-64 or the symbol is definitely defined in the current + // translation unit. + if (GV->hasDefaultVisibility() && + (isDecl || GV->isWeakForLinker())) + return X86II::MO_GOTPCREL; + } else if (!isTargetWin64()) { + assert(isTargetELF() && "Unknown rip-relative target"); + + // Extra load is needed for all externally visible. + if (!GV->hasLocalLinkage() && GV->hasDefaultVisibility()) + return X86II::MO_GOTPCREL; + } return X86II::MO_NO_FLAG; } @@ -81,7 +97,7 @@ ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM) const { // If this is a strong reference to a definition, it is definitely not // through a stub. - if (!GV->isDeclaration() && !GV->isWeakForLinker()) + if (!isDecl && !GV->isWeakForLinker()) return X86II::MO_PIC_BASE_OFFSET; // Unless we have a symbol with hidden visibility, we have to go through a @@ -91,7 +107,7 @@ ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM) const { // If symbol visibility is hidden, we have a stub for common symbol // references and external declarations. - if (GV->isDeclaration() || GV->hasCommonLinkage()) { + if (isDecl || GV->hasCommonLinkage()) { // Hidden $non_lazy_ptr reference. return X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE; } @@ -105,21 +121,14 @@ ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM) const { // If this is a strong reference to a definition, it is definitely not // through a stub. - if (!GV->isDeclaration() && !GV->isWeakForLinker()) + if (!isDecl && !GV->isWeakForLinker()) return X86II::MO_NO_FLAG; // Unless we have a symbol with hidden visibility, we have to go through a // normal $non_lazy_ptr stub because this symbol might be resolved late. if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. return X86II::MO_DARWIN_NONLAZY; - - // If symbol visibility is hidden, we have a stub for common symbol - // references and external declarations. - if (GV->isDeclaration() || GV->hasCommonLinkage()) { - // Hidden $non_lazy_ptr reference. - return X86II::MO_DARWIN_HIDDEN_NONLAZY; - } - + // Otherwise, no stub. return X86II::MO_NO_FLAG; } @@ -162,9 +171,9 @@ unsigned X86Subtarget::getSpecialAddressLatency() const { /// GetCpuIDAndInfo - Execute the specified cpuid and return the 4 values in the /// specified arguments. If we can't run cpuid on the host, return true. -bool X86::GetCpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX, - unsigned *rECX, unsigned *rEDX) { -#if defined(__x86_64__) || defined(_M_AMD64) +static bool GetCpuIDAndInfo(unsigned value, unsigned *rEAX, + unsigned *rEBX, unsigned *rECX, unsigned *rEDX) { +#if defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64) #if defined(__GNUC__) // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually. asm ("movq\t%%rbx, %%rsi\n\t" @@ -234,24 +243,27 @@ void X86Subtarget::AutoDetectSubtargetFeatures() { char c[12]; } text; - if (X86::GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1)) + if (GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1)) return; - X86::GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX); + GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX); - if ((EDX >> 23) & 0x1) X86SSELevel = MMX; - if ((EDX >> 25) & 0x1) X86SSELevel = SSE1; - if ((EDX >> 26) & 0x1) X86SSELevel = SSE2; - if (ECX & 0x1) X86SSELevel = SSE3; - if ((ECX >> 9) & 0x1) X86SSELevel = SSSE3; - if ((ECX >> 19) & 0x1) X86SSELevel = SSE41; - if ((ECX >> 20) & 0x1) X86SSELevel = SSE42; + if ((EDX >> 15) & 1) HasCMov = true; + if ((EDX >> 23) & 1) X86SSELevel = MMX; + if ((EDX >> 25) & 1) X86SSELevel = SSE1; + if ((EDX >> 26) & 1) X86SSELevel = SSE2; + if (ECX & 0x1) X86SSELevel = SSE3; + if ((ECX >> 9) & 1) X86SSELevel = SSSE3; + if ((ECX >> 19) & 1) X86SSELevel = SSE41; + if ((ECX >> 20) & 1) X86SSELevel = SSE42; bool IsIntel = memcmp(text.c, "GenuineIntel", 12) == 0; bool IsAMD = !IsIntel && memcmp(text.c, "AuthenticAMD", 12) == 0; - HasFMA3 = IsIntel && ((ECX >> 12) & 0x1); - HasAVX = ((ECX >> 28) & 0x1); + HasCLMUL = IsIntel && ((ECX >> 1) & 0x1); + HasFMA3 = IsIntel && ((ECX >> 12) & 0x1); + HasAVX = ((ECX >> 28) & 0x1); + HasAES = IsIntel && ((ECX >> 25) & 0x1); if (IsIntel || IsAMD) { // Determine if bit test memory instructions are slow. @@ -259,148 +271,38 @@ void X86Subtarget::AutoDetectSubtargetFeatures() { unsigned Model = 0; DetectFamilyModel(EAX, Family, Model); IsBTMemSlow = IsAMD || (Family == 6 && Model >= 13); + // If it's Nehalem, unaligned memory access is fast. + if (Family == 15 && Model == 26) + IsUAMemFast = true; - X86::GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX); + GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX); HasX86_64 = (EDX >> 29) & 0x1; HasSSE4A = IsAMD && ((ECX >> 6) & 0x1); HasFMA4 = IsAMD && ((ECX >> 16) & 0x1); } } -static const char *GetCurrentX86CPU() { - unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; - if (X86::GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX)) - return "generic"; - unsigned Family = 0; - unsigned Model = 0; - DetectFamilyModel(EAX, Family, Model); - - X86::GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX); - bool Em64T = (EDX >> 29) & 0x1; - bool HasSSE3 = (ECX & 0x1); - - union { - unsigned u[3]; - char c[12]; - } text; - - X86::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: - case 22: // Celeron M 540 - return "core2"; - case 23: // 45nm: Penryn , Wolfdale, Yorkfield (XE) - return "penryn"; - default: return "i686"; - } - case 15: { - switch (Model) { - case 3: - case 4: - case 6: // same as 4, but 65nm - return (Em64T) ? "nocona" : "prescott"; - case 26: - return "corei7"; - case 28: - return "atom"; - 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: - if (HasSSE3) { - switch (Model) { - default: return "k8-sse3"; - } - } else { - switch (Model) { - case 1: return "opteron"; - case 5: return "athlon-fx"; // also opteron - default: return "athlon64"; - } - } - case 16: - switch (Model) { - default: return "amdfam10"; - } - default: - return "generic"; - } - } else { - return "generic"; - } -} - -X86Subtarget::X86Subtarget(const Module &M, const std::string &FS, bool is64Bit) - : AsmFlavor(AsmWriterFlavor) - , PICStyle(PICStyles::None) +X86Subtarget::X86Subtarget(const std::string &TT, const std::string &FS, + bool is64Bit) + : PICStyle(PICStyles::None) , X86SSELevel(NoMMXSSE) , X863DNowLevel(NoThreeDNow) + , HasCMov(false) , HasX86_64(false) , HasSSE4A(false) , HasAVX(false) + , HasAES(false) + , HasCLMUL(false) , HasFMA3(false) , HasFMA4(false) , IsBTMemSlow(false) - , DarwinVers(0) - , IsLinux(false) + , IsUAMemFast(false) + , HasVectorUAMem(false) , stackAlignment(8) // FIXME: this is a known good value for Yonah. How about others? , MaxInlineSizeThreshold(128) - , Is64Bit(is64Bit) - , TargetType(isELF) { // Default to ELF unless otherwise specified. + , TargetTriple(TT) + , Is64Bit(is64Bit) { // default to hard float ABI if (FloatABIType == FloatABI::Default) @@ -409,7 +311,7 @@ X86Subtarget::X86Subtarget(const Module &M, const std::string &FS, bool is64Bit) // Determine default and user specified characteristics if (!FS.empty()) { // If feature string is not empty, parse features string. - std::string CPU = GetCurrentX86CPU(); + std::string CPU = sys::getHostCPUName(); ParseSubtargetFeatures(FS, CPU); // All X86-64 CPUs also have SSE2, however user might request no SSE via // -mattr, so don't force SSELevel here. @@ -423,79 +325,47 @@ X86Subtarget::X86Subtarget(const Module &M, const std::string &FS, bool is64Bit) // If requesting codegen for X86-64, make sure that 64-bit features // are enabled. - if (Is64Bit) + if (Is64Bit) { HasX86_64 = true; - DOUT << "Subtarget features: SSELevel " << X86SSELevel - << ", 3DNowLevel " << X863DNowLevel - << ", 64bit " << HasX86_64 << "\n"; + // All 64-bit cpus have cmov support. + HasCMov = true; + } + + DEBUG(dbgs() << "Subtarget features: SSELevel " << X86SSELevel + << ", 3DNowLevel " << X863DNowLevel + << ", 64bit " << HasX86_64 << "\n"); assert((!Is64Bit || HasX86_64) && "64-bit code requested on a subtarget that doesn't support it!"); - // Set the boolean corresponding to the current target triple, or the default - // if one cannot be determined, to true. - const std::string& TT = M.getTargetTriple(); - if (TT.length() > 5) { - size_t Pos; - if ((Pos = TT.find("-darwin")) != std::string::npos) { - TargetType = isDarwin; - - // Compute the darwin version number. - if (isdigit(TT[Pos+7])) - DarwinVers = atoi(&TT[Pos+7]); - else - DarwinVers = 8; // Minimum supported darwin is Tiger. - } else if (TT.find("linux") != std::string::npos) { - // Linux doesn't imply ELF, but we don't currently support anything else. - TargetType = isELF; - IsLinux = true; - } else if (TT.find("cygwin") != std::string::npos) { - TargetType = isCygwin; - } else if (TT.find("mingw") != std::string::npos) { - TargetType = isMingw; - } else if (TT.find("win32") != std::string::npos) { - TargetType = isWindows; - } else if (TT.find("windows") != std::string::npos) { - TargetType = isWindows; - } - else if (TT.find("-cl") != std::string::npos) { - TargetType = isDarwin; - DarwinVers = 9; - } - } else if (TT.empty()) { -#if defined(__CYGWIN__) - TargetType = isCygwin; -#elif defined(__MINGW32__) || defined(__MINGW64__) - TargetType = isMingw; -#elif defined(__APPLE__) - TargetType = isDarwin; -#if __APPLE_CC__ > 5400 - DarwinVers = 9; // GCC 5400+ is Leopard. -#else - DarwinVers = 8; // Minimum supported darwin is Tiger. -#endif - -#elif defined(_WIN32) || defined(_WIN64) - TargetType = isWindows; -#elif defined(__linux__) - // Linux doesn't imply ELF, but we don't currently support anything else. - TargetType = isELF; - IsLinux = true; -#endif - } - - // If the asm syntax hasn't been overridden on the command line, use whatever - // the target wants. - if (AsmFlavor == X86Subtarget::Unset) { - AsmFlavor = (TargetType == isWindows) - ? X86Subtarget::Intel : X86Subtarget::ATT; - } - // Stack alignment is 16 bytes on Darwin (both 32 and 64 bit) and for all 64 // bit targets. - if (TargetType == isDarwin || Is64Bit) + if (isTargetDarwin() || Is64Bit) stackAlignment = 16; if (StackAlignment) stackAlignment = StackAlignment; } + +/// IsCalleePop - Determines whether the callee is required to pop its +/// own arguments. Callee pop is necessary to support tail calls. +bool X86Subtarget::IsCalleePop(bool IsVarArg, + CallingConv::ID CallingConv) const { + if (IsVarArg) + return false; + + switch (CallingConv) { + default: + return false; + case CallingConv::X86_StdCall: + return !is64Bit(); + case CallingConv::X86_FastCall: + return !is64Bit(); + case CallingConv::X86_ThisCall: + return !is64Bit(); + case CallingConv::Fast: + return GuaranteedTailCallOpt; + case CallingConv::GHC: + return GuaranteedTailCallOpt; + } +}