[llvm-commits] [llvm] r134641 - in /llvm/trunk: lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h lib/Target/X86/X86.td lib/Target/X86/X86Subtarget.cpp lib/Target/X86/X86Subtarget.h lib/Target/X86/X86Ta

Eli Friedman eli.friedman at gmail.com
Fri Jul 8 13:03:59 PDT 2011


On Thu, Jul 7, 2011 at 2:06 PM, Evan Cheng <evan.cheng at apple.com> wrote:
> Author: evancheng
> Date: Thu Jul  7 16:06:52 2011
> New Revision: 134641
>
> URL: http://llvm.org/viewvc/llvm-project?rev=134641&view=rev
> Log:
> Add Mode64Bit feature and sink it down to MC layer.
>
> Modified:
>    llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
>    llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h
>    llvm/trunk/lib/Target/X86/X86.td
>    llvm/trunk/lib/Target/X86/X86Subtarget.cpp
>    llvm/trunk/lib/Target/X86/X86Subtarget.h
>    llvm/trunk/lib/Target/X86/X86TargetMachine.cpp
>    llvm/trunk/test/CodeGen/X86/2010-04-08-CoalescerBug.ll
>    llvm/trunk/test/CodeGen/X86/2010-06-25-CoalescerSubRegDefDead.ll
>    llvm/trunk/test/CodeGen/X86/2010-09-17-SideEffectsInChain.ll
>    llvm/trunk/test/CodeGen/X86/memcpy.ll
>    llvm/trunk/test/CodeGen/X86/tlv-1.ll
>
> Modified: llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp?rev=134641&r1=134640&r2=134641&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp (original)
> +++ llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp Thu Jul  7 16:06:52 2011
> @@ -16,6 +16,8 @@
>  #include "llvm/MC/MCRegisterInfo.h"
>  #include "llvm/MC/MCSubtargetInfo.h"
>  #include "llvm/Target/TargetRegistry.h"
> +#include "llvm/ADT/Triple.h"
> +#include "llvm/Support/Host.h"
>
>  #define GET_REGINFO_MC_DESC
>  #include "X86GenRegisterInfo.inc"
> @@ -28,6 +30,104 @@
>
>  using namespace llvm;
>
> +
> +std::string X86_MC::ParseX86Triple(StringRef TT) {
> +  Triple TheTriple(TT);
> +  if (TheTriple.getArch() == Triple::x86_64)
> +    return "+64bit-mode";
> +  return "";
> +}
> +
> +/// 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_MC::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"
> +         "cpuid\n\t"
> +         "xchgq\t%%rbx, %%rsi\n\t"
> +         : "=a" (*rEAX),
> +           "=S" (*rEBX),
> +           "=c" (*rECX),
> +           "=d" (*rEDX)
> +         :  "a" (value));
> +    return false;
> +  #elif defined(_MSC_VER)
> +    int registers[4];
> +    __cpuid(registers, value);
> +    *rEAX = registers[0];
> +    *rEBX = registers[1];
> +    *rECX = registers[2];
> +    *rEDX = registers[3];
> +    return false;
> +  #endif
> +#elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)
> +  #if defined(__GNUC__)
> +    asm ("movl\t%%ebx, %%esi\n\t"
> +         "cpuid\n\t"
> +         "xchgl\t%%ebx, %%esi\n\t"
> +         : "=a" (*rEAX),
> +           "=S" (*rEBX),
> +           "=c" (*rECX),
> +           "=d" (*rEDX)
> +         :  "a" (value));
> +    return false;
> +  #elif defined(_MSC_VER)
> +    __asm {
> +      mov   eax,value
> +      cpuid
> +      mov   esi,rEAX
> +      mov   dword ptr [esi],eax
> +      mov   esi,rEBX
> +      mov   dword ptr [esi],ebx
> +      mov   esi,rECX
> +      mov   dword ptr [esi],ecx
> +      mov   esi,rEDX
> +      mov   dword ptr [esi],edx
> +    }
> +    return false;
> +  #endif
> +#endif
> +  return true;
> +}
> +
> +void X86_MC::DetectFamilyModel(unsigned EAX, unsigned &Family,
> +                               unsigned &Model) {
> +  Family = (EAX >> 8) & 0xf; // Bits 8 - 11
> +  Model  = (EAX >> 4) & 0xf; // Bits 4 - 7
> +  if (Family == 6 || Family == 0xf) {
> +    if (Family == 0xf)
> +      // Examine extended family ID if family ID is F.
> +      Family += (EAX >> 20) & 0xff;    // Bits 20 - 27
> +    // Examine extended model ID if family ID is 6 or F.
> +    Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19
> +  }
> +}
> +
> +static bool hasX86_64() {
> +  // FIXME: Code duplication. See X86Subtarget::AutoDetectSubtargetFeatures.
> +  unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
> +  union {
> +    unsigned u[3];
> +    char     c[12];
> +  } text;
> +
> +  if (X86_MC::GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1))
> +    return false;
> +
> +  bool IsIntel = memcmp(text.c, "GenuineIntel", 12) == 0;
> +  bool IsAMD   = !IsIntel && memcmp(text.c, "AuthenticAMD", 12) == 0;
> +  if (IsIntel || IsAMD) {
> +    X86_MC::GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
> +    if ((EDX >> 29) & 0x1)
> +      return true;
> +  }
> +
> +  return false;
> +}
> +
>  MCInstrInfo *createX86MCInstrInfo() {
>   MCInstrInfo *X = new MCInstrInfo();
>   InitX86MCInstrInfo(X);
> @@ -42,8 +142,24 @@
>
>  MCSubtargetInfo *createX86MCSubtargetInfo(StringRef TT, StringRef CPU,
>                                           StringRef FS) {
> +  std::string ArchFS = X86_MC::ParseX86Triple(TT);
> +  if (!FS.empty()) {
> +    if (!ArchFS.empty())
> +      ArchFS = ArchFS + "," + FS.str();
> +    else
> +      ArchFS = FS;
> +  }
> +
> +  std::string CPUName = CPU;
> +  if (CPUName.empty())
> +    CPUName = sys::getHostCPUName();
> +
> +  if (ArchFS.empty() && CPUName.empty() && hasX86_64())
> +    // Auto-detect if host is 64-bit capable, it's the default if true.
> +    ArchFS = "+64bit-mode";
> +
>   MCSubtargetInfo *X = new MCSubtargetInfo();
> -  InitX86MCSubtargetInfo(X, CPU, FS);
> +  InitX86MCSubtargetInfo(X, CPU, ArchFS);
>   return X;
>  }
>
>
> Modified: llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h?rev=134641&r1=134640&r2=134641&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h (original)
> +++ llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h Thu Jul  7 16:06:52 2011
> @@ -14,10 +14,24 @@
>  #ifndef X86MCTARGETDESC_H
>  #define X86MCTARGETDESC_H
>
> +#include <string>
> +
>  namespace llvm {
>  class Target;
> +class StringRef;
>
>  extern Target TheX86_32Target, TheX86_64Target;
> +
> +namespace X86_MC {
> +  std::string ParseX86Triple(StringRef TT);
> +
> +  /// 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 GetCpuIDAndInfo(unsigned value, unsigned *rEAX,
> +                       unsigned *rEBX, unsigned *rECX, unsigned *rEDX);
> +
> +  void DetectFamilyModel(unsigned EAX, unsigned &Family, unsigned &Model);
> +}
>  } // End llvm namespace
>
>  // Defines symbolic names for X86 registers.  This defines a mapping from
>
> Modified: llvm/trunk/lib/Target/X86/X86.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86.td?rev=134641&r1=134640&r2=134641&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86.td (original)
> +++ llvm/trunk/lib/Target/X86/X86.td Thu Jul  7 16:06:52 2011
> @@ -17,6 +17,13 @@
>  include "llvm/Target/Target.td"
>
>  //===----------------------------------------------------------------------===//
> +// X86 Subtarget state.
> +//
> +
> +def Mode64Bit : SubtargetFeature<"64bit-mode", "In64BitMode", "true",
> +                                  "64-bit mode (x86_64)">;
> +
> +//===----------------------------------------------------------------------===//
>  // X86 Subtarget features.
>  //===----------------------------------------------------------------------===//
>
>
> Modified: llvm/trunk/lib/Target/X86/X86Subtarget.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86Subtarget.cpp?rev=134641&r1=134640&r2=134641&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86Subtarget.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86Subtarget.cpp Thu Jul  7 16:06:52 2011
> @@ -158,7 +158,7 @@
>  /// IsLegalToCallImmediateAddr - Return true if the subtarget allows calls
>  /// to immediate address.
>  bool X86Subtarget::IsLegalToCallImmediateAddr(const TargetMachine &TM) const {
> -  if (Is64Bit)
> +  if (In64BitMode)
>     return false;
>   return isTargetELF() || TM.getRelocationModel() == Reloc::Static;
>  }
> @@ -174,73 +174,6 @@
>   return 200;
>  }
>
> -/// 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.
> -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"
> -         "cpuid\n\t"
> -         "xchgq\t%%rbx, %%rsi\n\t"
> -         : "=a" (*rEAX),
> -           "=S" (*rEBX),
> -           "=c" (*rECX),
> -           "=d" (*rEDX)
> -         :  "a" (value));
> -    return false;
> -  #elif defined(_MSC_VER)
> -    int registers[4];
> -    __cpuid(registers, value);
> -    *rEAX = registers[0];
> -    *rEBX = registers[1];
> -    *rECX = registers[2];
> -    *rEDX = registers[3];
> -    return false;
> -  #endif
> -#elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)
> -  #if defined(__GNUC__)
> -    asm ("movl\t%%ebx, %%esi\n\t"
> -         "cpuid\n\t"
> -         "xchgl\t%%ebx, %%esi\n\t"
> -         : "=a" (*rEAX),
> -           "=S" (*rEBX),
> -           "=c" (*rECX),
> -           "=d" (*rEDX)
> -         :  "a" (value));
> -    return false;
> -  #elif defined(_MSC_VER)
> -    __asm {
> -      mov   eax,value
> -      cpuid
> -      mov   esi,rEAX
> -      mov   dword ptr [esi],eax
> -      mov   esi,rEBX
> -      mov   dword ptr [esi],ebx
> -      mov   esi,rECX
> -      mov   dword ptr [esi],ecx
> -      mov   esi,rEDX
> -      mov   dword ptr [esi],edx
> -    }
> -    return false;
> -  #endif
> -#endif
> -  return true;
> -}
> -
> -static void DetectFamilyModel(unsigned EAX, unsigned &Family, unsigned &Model) {
> -  Family = (EAX >> 8) & 0xf; // Bits 8 - 11
> -  Model  = (EAX >> 4) & 0xf; // Bits 4 - 7
> -  if (Family == 6 || Family == 0xf) {
> -    if (Family == 0xf)
> -      // Examine extended family ID if family ID is F.
> -      Family += (EAX >> 20) & 0xff;    // Bits 20 - 27
> -    // Examine extended model ID if family ID is 6 or F.
> -    Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19
> -  }
> -}
> -
>  void X86Subtarget::AutoDetectSubtargetFeatures() {
>   unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
>   union {
> @@ -248,10 +181,10 @@
>     char     c[12];
>   } text;
>
> -  if (GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1))
> +  if (X86_MC::GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1))
>     return;
>
> -  GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX);
> +  X86_MC::GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX);
>
>   if ((EDX >> 15) & 1) HasCMov = true;
>   if ((EDX >> 23) & 1) X86SSELevel = MMX;
> @@ -276,13 +209,13 @@
>     // Determine if bit test memory instructions are slow.
>     unsigned Family = 0;
>     unsigned Model  = 0;
> -    DetectFamilyModel(EAX, Family, Model);
> +    X86_MC::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;
>
> -    GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
> +    X86_MC::GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
>     HasX86_64 = (EDX >> 29) & 0x1;
>     HasSSE4A = IsAMD && ((ECX >> 6) & 0x1);
>     HasFMA4 = IsAMD && ((ECX >> 16) & 0x1);
> @@ -291,7 +224,7 @@
>
>  X86Subtarget::X86Subtarget(const std::string &TT, const std::string &CPU,
>                            const std::string &FS,
> -                           bool is64Bit, unsigned StackAlignOverride)
> +                           unsigned StackAlignOverride)
>   : X86GenSubtargetInfo(TT, CPU, FS)
>   , PICStyle(PICStyles::None)
>   , X86SSELevel(NoMMXSSE)
> @@ -312,15 +245,26 @@
>   // FIXME: this is a known good value for Yonah. How about others?
>   , MaxInlineSizeThreshold(128)
>   , TargetTriple(TT)
> -  , Is64Bit(is64Bit) {
> +  , In64BitMode(false) {
> +  // Insert the architecture feature derived from the target triple into the
> +  // feature string. This is important for setting features that are implied
> +  // based on the architecture version.
> +  std::string ArchFS = X86_MC::ParseX86Triple(TT);
> +  if (!FS.empty()) {
> +    if (!ArchFS.empty())
> +      ArchFS = ArchFS + "," + FS;
> +    else
> +      ArchFS = FS;
> +  }
> +
> +  std::string CPUName = CPU;
> +  if (CPUName.empty())
> +    CPUName = sys::getHostCPUName();
>
>   // Determine default and user specified characteristics
> -  if (!CPU.empty() || !FS.empty()) {
> +  if (!CPUName.empty() || !ArchFS.empty()) {
>     // If feature string is not empty, parse features string.
> -    std::string CPUName = CPU;
> -    if (CPUName.empty())
> -      CPUName = sys::getHostCPUName();
> -    ParseSubtargetFeatures(CPUName, FS);
> +    ParseSubtargetFeatures(CPUName, ArchFS);
>     // All X86-64 CPUs also have SSE2, however user might request no SSE via
>     // -mattr, so don't force SSELevel here.
>     if (HasAVX)
> @@ -328,14 +272,19 @@
>   } else {
>     // Otherwise, use CPUID to auto-detect feature set.
>     AutoDetectSubtargetFeatures();
> +
> +    // If CPU is 64-bit capable, default to 64-bit mode if not specified.
> +    In64BitMode = HasX86_64;
> +
>     // Make sure SSE2 is enabled; it is available on all X86-64 CPUs.
> -    if (Is64Bit && !HasAVX && X86SSELevel < SSE2)
> +    if (In64BitMode && !HasAVX && X86SSELevel < SSE2)
>       X86SSELevel = SSE2;
>   }
>
>   // If requesting codegen for X86-64, make sure that 64-bit features
>   // are enabled.
> -  if (Is64Bit) {
> +  // FIXME: Remove this feature since it's not actually being used.
> +  if (In64BitMode) {
>     HasX86_64 = true;
>
>     // All 64-bit cpus have cmov support.
> @@ -345,7 +294,7 @@
>   DEBUG(dbgs() << "Subtarget features: SSELevel " << X86SSELevel
>                << ", 3DNowLevel " << X863DNowLevel
>                << ", 64bit " << HasX86_64 << "\n");
> -  assert((!Is64Bit || HasX86_64) &&
> +  assert((!In64BitMode || HasX86_64) &&
>          "64-bit code requested on a subtarget that doesn't support it!");
>
>   // Stack alignment is 16 bytes on Darwin, FreeBSD, Linux and Solaris (both
> @@ -353,6 +302,6 @@
>   if (StackAlignOverride)
>     stackAlignment = StackAlignOverride;
>   else if (isTargetDarwin() || isTargetFreeBSD() || isTargetLinux() ||
> -           isTargetSolaris() || Is64Bit)
> +           isTargetSolaris() || In64BitMode)
>     stackAlignment = 16;
>  }

The bit of this change in X86Subtarget.cpp appears to break tests
anywhere that sys::getHostCPUName doesn't return the name of a known
64-bit-capable x86 CPU (ARM, older x86 CPUs, very new x86 CPUS).
Please fix or revert.

-Eli




More information about the llvm-commits mailing list