1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 03:33:20 +01:00

Add Mode64Bit feature and sink it down to MC layer.

llvm-svn: 134641
This commit is contained in:
Evan Cheng 2011-07-07 21:06:52 +00:00
parent 49b8e85286
commit bbed81df25
11 changed files with 183 additions and 98 deletions

View File

@ -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 @@ MCRegisterInfo *createX86MCRegisterInfo() {
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;
}

View File

@ -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

View File

@ -16,6 +16,13 @@
//
include "llvm/Target/Target.td"
//===----------------------------------------------------------------------===//
// X86 Subtarget state.
//
def Mode64Bit : SubtargetFeature<"64bit-mode", "In64BitMode", "true",
"64-bit mode (x86_64)">;
//===----------------------------------------------------------------------===//
// X86 Subtarget features.
//===----------------------------------------------------------------------===//

View File

@ -158,7 +158,7 @@ const char *X86Subtarget::getBZeroEntry() const {
/// 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 @@ unsigned X86Subtarget::getSpecialAddressLatency() const {
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 @@ void X86Subtarget::AutoDetectSubtargetFeatures() {
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 @@ void X86Subtarget::AutoDetectSubtargetFeatures() {
// 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 @@ void X86Subtarget::AutoDetectSubtargetFeatures() {
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 @@ X86Subtarget::X86Subtarget(const std::string &TT, const std::string &CPU,
// 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 @@ X86Subtarget::X86Subtarget(const std::string &TT, const std::string &CPU,
} 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 @@ X86Subtarget::X86Subtarget(const std::string &TT, const std::string &CPU,
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 @@ X86Subtarget::X86Subtarget(const std::string &TT, const std::string &CPU,
if (StackAlignOverride)
stackAlignment = StackAlignOverride;
else if (isTargetDarwin() || isTargetFreeBSD() || isTargetLinux() ||
isTargetSolaris() || Is64Bit)
isTargetSolaris() || In64BitMode)
stackAlignment = 16;
}

View File

@ -112,9 +112,8 @@ protected:
Triple TargetTriple;
private:
/// Is64Bit - True if the processor supports 64-bit instructions and
/// pointer size is 64 bit.
bool Is64Bit;
/// In64BitMode - True if compiling for 64-bit, false for 32-bit.
bool In64BitMode;
public:
@ -122,7 +121,7 @@ public:
/// of the specified triple.
///
X86Subtarget(const std::string &TT, const std::string &CPU,
const std::string &FS, bool is64Bit,
const std::string &FS,
unsigned StackAlignOverride);
/// getStackAlignment - Returns the minimum alignment known to hold of the
@ -142,7 +141,7 @@ public:
/// instruction.
void AutoDetectSubtargetFeatures();
bool is64Bit() const { return Is64Bit; }
bool is64Bit() const { return In64BitMode; }
PICStyles::Style getPICStyle() const { return PICStyle; }
void setPICStyle(PICStyles::Style Style) { PICStyle = Style; }
@ -200,7 +199,7 @@ public:
}
bool isTargetWin64() const {
return Is64Bit && (isTargetMingw() || isTargetWindows());
return In64BitMode && (isTargetMingw() || isTargetWindows());
}
bool isTargetEnvMacho() const {
@ -208,7 +207,7 @@ public:
}
bool isTargetWin32() const {
return !Is64Bit && (isTargetMingw() || isTargetWindows());
return !In64BitMode && (isTargetMingw() || isTargetWindows());
}
bool isPICStyleSet() const { return PICStyle != PICStyles::None; }

View File

@ -120,7 +120,7 @@ X86TargetMachine::X86TargetMachine(const Target &T, const std::string &TT,
const std::string &CPU,
const std::string &FS, bool is64Bit)
: LLVMTargetMachine(T, TT),
Subtarget(TT, CPU, FS, is64Bit, StackAlignmentOverride),
Subtarget(TT, CPU, FS, StackAlignmentOverride),
FrameLowering(*this, Subtarget),
ELFWriterInfo(is64Bit, true) {
DefRelocModel = getRelocationModel();

View File

@ -1,4 +1,4 @@
; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s
; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=core2 | FileCheck %s
; rdar://7842028
; Do not delete partially dead copy instructions.

View File

@ -1,4 +1,4 @@
; RUN: llc -O1 -mtriple=x86_64-unknown-linux-gnu -relocation-model=pic -disable-fp-elim < %s | FileCheck %s
; RUN: llc -O1 -mtriple=x86_64-unknown-linux-gnu -mcpu=core2 -relocation-model=pic -disable-fp-elim < %s | FileCheck %s
; <rdar://problem/8124405>
%struct.type = type { %struct.subtype*, i32, i8, i32, i8, i32, i32, i32, i32, i32, i8, i32, i32, i32, i32, i32, [256 x i32], i32, [257 x i32], [257 x i32], i32*, i16*, i8*, i32, i32, i32, i32, i32, [256 x i8], [16 x i8], [256 x i8], [4096 x i8], [16 x i32], [18002 x i8], [18002 x i8], [6 x [258 x i8]], [6 x [258 x i32]], [6 x [258 x i32]], [6 x [258 x i32]], [6 x i32], i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32*, i32*, i32* }

View File

@ -1,4 +1,4 @@
; RUN: llc < %s -combiner-alias-analysis -march=x86-64 | FileCheck %s
; RUN: llc < %s -combiner-alias-analysis -march=x86-64 -mcpu=core2 | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-apple-darwin10.4"

View File

@ -1,5 +1,5 @@
; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s -check-prefix=LINUX
; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s -check-prefix=DARWIN
; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=core2 | FileCheck %s -check-prefix=LINUX
; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=core2 | FileCheck %s -check-prefix=DARWIN
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind

View File

@ -1,4 +1,4 @@
; RUN: llc < %s -mtriple x86_64-apple-darwin | FileCheck %s
; RUN: llc < %s -mtriple x86_64-apple-darwin -mcpu=core2 | FileCheck %s
%struct.A = type { [48 x i8], i32, i32, i32 }