llvm.org GIT mirror llvm / release_23 lib / Target / X86 / X86Subtarget.cpp
release_23

Tree @release_23 (Download .tar.gz)

X86Subtarget.cpp @release_23

8c00f8c
fb5792f
 
 
4ee451d
 
fb5792f
 
 
 
 
 
 
 
a26eb5e
fb5792f
05a059d
2b2bc68
45709ae
fb5792f
 
05a059d
7f70559
05a059d
 
7f70559
 
cdb341d
05a059d
751c0e1
7784ebc
 
 
 
48c8e3d
2b2bc68
48c8e3d
7784ebc
b10308e
7c1c261
5032e5a
15fccf1
 
a99be51
49964d6
5032e5a
 
5cbf985
317848f
15fccf1
 
7c1c261
7784ebc
 
 
 
68d599d
 
 
 
 
 
 
 
 
 
 
 
 
 
1e39a15
 
751c0e1
 
25ab690
f896d1e
 
 
 
25ab690
 
 
 
 
 
 
559806f
aacf999
559806f
aacf999
41adb0d
 
 
 
559806f
1e39a15
41adb0d
 
 
 
 
 
 
 
 
 
 
 
 
 
559806f
 
1e39a15
559806f
97c7fc3
a26eb5e
b3a7e21
a349640
216d281
 
a349640
3b6f497
751c0e1
abc346c
 
3b5ee73
 
 
 
 
 
bb1ee05
63ec90a
 
41adb0d
c398709
 
 
 
 
97c7fc3
 
a26eb5e
 
751c0e1
a26eb5e
 
 
751c0e1
3cff9f8
a26eb5e
 
 
 
 
 
751c0e1
a26eb5e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3b5ee73
a26eb5e
 
 
 
 
 
 
 
 
 
 
25ab690
8e0055d
7f70559
25ab690
dc00858
25ab690
7ad92d8
94bbdc8
25ab690
 
fc05f40
25ab690
 
63307c3
97c7fc3
a26eb5e
 
 
 
3b6f497
 
 
 
 
 
 
 
 
 
 
25ab690
 
fb5792f
 
 
 
e51775d
7ad92d8
 
 
 
 
 
 
 
a779a98
600bf16
 
 
7ad92d8
e5600e5
7ad92d8
317848f
7ad92d8
e5600e5
508f0fd
 
7ad92d8
fb5792f
317848f
e5600e5
2b4f780
317848f
fb5792f
e5600e5
7ad92d8
 
 
 
 
 
2b4f780
e5600e5
a779a98
 
600bf16
 
fb5792f
 
 
cdb341d
 
7f70559
7ad92d8
 
cdb341d
 
890fe88
 
 
fb5792f
78c80fd
 
 
fb5792f
//===-- X86Subtarget.cpp - X86 Subtarget Information ------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the X86 specific subclass of TargetSubtarget.
//
//===----------------------------------------------------------------------===//

#include "X86Subtarget.h"
#include "X86GenSubtarget.inc"
#include "llvm/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
using namespace llvm;

cl::opt<X86Subtarget::AsmWriterFlavorTy>
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));


/// True if accessing the GV requires an extra load. For Windows, dllimported
/// symbols are indirect, loading the value at address GV rather then the
/// value of GV itself. This means that the GlobalAddress must be in the base
/// or index register of the address, not the GV offset field.
bool X86Subtarget::GVRequiresExtraLoad(const GlobalValue* GV,
                                       const TargetMachine& TM,
                                       bool isDirectCall) const
{
  // FIXME: PIC
  if (TM.getRelocationModel() != Reloc::Static) {
    if (isTargetDarwin()) {
      return (!isDirectCall &&
              (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() ||
               (GV->isDeclaration() && !GV->hasNotBeenReadFromBitcode())));
    } else if (isTargetELF()) {
      // Extra load is needed for all non-statics.
      return (!isDirectCall &&
              (GV->isDeclaration() || !GV->hasInternalLinkage()));
    } else if (isTargetCygMing() || isTargetWindows()) {
      return (GV->hasDLLImportLinkage());
    }
  }
  
  return false;
}

/// This function returns the name of a function which has an interface
/// like the non-standard bzero function, if such a function exists on
/// the current subtarget and it is considered prefereable over
/// memset with zero passed as the second argument. Otherwise it
/// returns null.
const char *X86Subtarget::getBZeroEntry() const {

  // Darwin 10 has a __bzero entry point for this purpose.
  if (getDarwinVers() >= 10)
    return "__bzero";

  return 0;
}

/// 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__)
  // 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(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 X86Subtarget::AutoDetectSubtargetFeatures() {
  unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
  union {
    unsigned u[3];
    char     c[12];
  } text;
  
  if (X86::GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1))
    return;

  X86::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 (memcmp(text.c, "GenuineIntel", 12) == 0 ||
      memcmp(text.c, "AuthenticAMD", 12) == 0) {
    X86::GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
    HasX86_64 = (EDX >> 29) & 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  = (EAX >> 8) & 0xf; // Bits 8 - 11
  unsigned Model   = (EAX >> 4) & 0xf; // Bits 4 - 7
  X86::GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
  bool Em64T = (EDX >> 29) & 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: 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 1:  return "opteron";
        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)
  , PICStyle(PICStyle::None)
  , X86SSELevel(NoMMXSSE)
  , X863DNowLevel(NoThreeDNow)
  , HasX86_64(false)
  , DarwinVers(0)
  , IsLinux(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.
    
  // Determine default and user specified characteristics
  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 requesting codegen for X86-64, make sure that 64-bit and SSE2 features
  // are enabled.  These are available on all x86-64 CPUs.
  if (Is64Bit) {
    HasX86_64 = true;
    if (X86SSELevel < SSE2)
      X86SSELevel = SSE2;
  }

  // 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.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)
    stackAlignment = 16;

  if (StackAlignment)
    stackAlignment = StackAlignment;
}