Some notes on better load folding we could do
[oota-llvm.git] / lib / Target / X86 / X86Subtarget.cpp
1 //===-- X86Subtarget.cpp - X86 Subtarget Information ------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by Nate Begeman and is distributed under the
6 // University of Illinois Open Source License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the X86 specific subclass of TargetSubtarget.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "X86Subtarget.h"
15 #include "llvm/Module.h"
16 #include "llvm/Support/CommandLine.h"
17 #include "X86GenSubtarget.inc"
18 using namespace llvm;
19
20 cl::opt<X86Subtarget::AsmWriterFlavorTy>
21 AsmWriterFlavor("x86-asm-syntax",
22   cl::desc("Choose style of code to emit from X86 backend:"),
23   cl::values(
24     clEnumValN(X86Subtarget::att,   "att",   "  Emit AT&T-style assembly"),
25     clEnumValN(X86Subtarget::intel, "intel", "  Emit Intel-style assembly"),
26     clEnumValEnd),
27 #ifdef _MSC_VER
28   cl::init(X86Subtarget::intel)
29 #else
30   cl::init(X86Subtarget::att)
31 #endif
32                 );
33
34 /// GetCpuIDAndInfo - Execute the specified cpuid and return the 4 values in the
35 /// specified arguments.  If we can't run cpuid on the host, return true.
36 static bool GetCpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,
37                             unsigned *rECX, unsigned *rEDX) {
38 #if defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)
39 #if defined(__GNUC__)
40   asm ("pushl\t%%ebx\n\t"
41        "cpuid\n\t"
42        "movl\t%%ebx, %%esi\n\t"
43        "popl\t%%ebx"
44        : "=a" (*rEAX),
45          "=S" (*rEBX),
46          "=c" (*rECX),
47          "=d" (*rEDX)
48        :  "a" (value));
49   return false;
50 #elif defined(_MSC_VER)
51   __asm {
52     mov   eax,value
53     cpuid
54     mov   esi,rEAX
55     mov   dword ptr [esi],eax
56     mov   esi,rEBX
57     mov   dword ptr [esi],ebx
58     mov   esi,rECX
59     mov   dword ptr [esi],ecx
60     mov   esi,rEDX
61     mov   dword ptr [esi],edx
62   }
63   return false;
64 #endif
65 #endif
66   return true;
67 }
68
69 static const char *GetCurrentX86CPU() {
70   unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
71   if (GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX))
72     return "generic";
73   unsigned Family  = (EAX & (0xffffffff >> (32 - 4)) << 8) >> 8; // Bits 8 - 11
74   unsigned Model   = (EAX & (0xffffffff >> (32 - 4)) << 4) >> 4; // Bits 4 - 7
75   GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
76   bool Em64T = EDX & (1 << 29);
77
78   union {
79     unsigned u[3];
80     char     c[12];
81   } text;
82
83   GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1);
84   if (memcmp(text.c, "GenuineIntel", 12) == 0) {
85     switch (Family) {
86       case 3:
87         return "i386";
88       case 4:
89         return "i486";
90       case 5:
91         switch (Model) {
92         case 4:  return "pentium-mmx";
93         default: return "pentium";
94         }
95       case 6:
96         switch (Model) {
97         case 1:  return "pentiumpro";
98         case 3:
99         case 5:
100         case 6:  return "pentium2";
101         case 7:
102         case 8:
103         case 10:
104         case 11: return "pentium3";
105         case 9:
106         case 13: return "pentium-m";
107         case 14: return "yonah";
108         default:
109           return (Model > 14) ? "yonah" : "i686";
110         }
111       case 15: {
112         switch (Model) {
113         case 3:  
114         case 4:
115           return (Em64T) ? "nocona" : "prescott";
116         default:
117           return (Em64T) ? "x86-64" : "pentium4";
118         }
119       }
120         
121     default:
122       return "generic";
123     }
124   } else if (memcmp(text.c, "AuthenticAMD", 12) == 0) {
125     // FIXME: this poorly matches the generated SubtargetFeatureKV table.  There
126     // appears to be no way to generate the wide variety of AMD-specific targets
127     // from the information returned from CPUID.
128     switch (Family) {
129       case 4:
130         return "i486";
131       case 5:
132         switch (Model) {
133         case 6:
134         case 7:  return "k6";
135         case 8:  return "k6-2";
136         case 9:
137         case 13: return "k6-3";
138         default: return "pentium";
139         }
140       case 6:
141         switch (Model) {
142         case 4:  return "athlon-tbird";
143         case 6:
144         case 7:
145         case 8:  return "athlon-mp";
146         case 10: return "athlon-xp";
147         default: return "athlon";
148         }
149       case 15:
150         switch (Model) {
151         case 5:  return "athlon-fx"; // also opteron
152         default: return "athlon64";
153         }
154
155     default:
156       return "generic";
157     }
158   } else {
159     return "generic";
160   }
161 }
162
163 X86Subtarget::X86Subtarget(const Module &M, const std::string &FS) {
164   stackAlignment = 8;
165   // FIXME: this is a known good value for Yonah. Not sure about others.
166   MinRepStrSizeThreshold = 128;
167   X86SSELevel = NoMMXSSE;
168   X863DNowLevel = NoThreeDNow;
169   AsmFlavor = AsmWriterFlavor;
170   Is64Bit = false;
171
172   // Determine default and user specified characteristics
173   std::string CPU = GetCurrentX86CPU();
174
175   // Parse features string.
176   ParseSubtargetFeatures(FS, CPU);
177
178   // Default to ELF unless otherwise specified.
179   TargetType = isELF;
180   
181   // Set the boolean corresponding to the current target triple, or the default
182   // if one cannot be determined, to true.
183   const std::string& TT = M.getTargetTriple();
184   if (TT.length() > 5) {
185     if (TT.find("cygwin") != std::string::npos ||
186         TT.find("mingw")  != std::string::npos)
187       TargetType = isCygwin;
188     else if (TT.find("darwin") != std::string::npos)
189       TargetType = isDarwin;
190     else if (TT.find("win32") != std::string::npos)
191       TargetType = isWindows;
192   } else if (TT.empty()) {
193 #if defined(__CYGWIN__) || defined(__MINGW32__)
194     TargetType = isCygwin;
195 #elif defined(__APPLE__)
196     TargetType = isDarwin;
197 #elif defined(_WIN32)
198     TargetType = isWindows;
199 #endif
200   }
201
202   if (TargetType == isDarwin || TargetType == isCygwin)
203     stackAlignment = 16;
204 }