authorgravatar for allisonalichay@gmail.comalichay <allisonalichay@gmail.com> 2020-03-05 22:12:15-06:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-06 18:52:09-05:00
logf19918256746ccc81b6ff11d17e98665b4853400
tree27cc0ce16501b11448ddfc7e724574d6c6077f2e
parente24f29bbadec8b22c11d876559cd80cd20ff623e
signaturelock-open Commit is signed but in an unrecognized format.

Cleaned up CPU detection and fixed incorrect detection bits.


3 files changed, 104 insertions(+), 178 deletions(-)

lib/std/zig/system.zig+17-9
...@@ -171,6 +171,8 @@ pub const NativeTargetInfo = struct {...@@ -171,6 +171,8 @@ pub const NativeTargetInfo = struct {
171171
172 dynamic_linker: DynamicLinker = DynamicLinker{},172 dynamic_linker: DynamicLinker = DynamicLinker{},
173173
174 cpu_detected: bool = false,
175
174 pub const DynamicLinker = Target.DynamicLinker;176 pub const DynamicLinker = Target.DynamicLinker;
175177
176 pub const DetectError = error{178 pub const DetectError = error{
...@@ -191,6 +193,9 @@ pub const NativeTargetInfo = struct {...@@ -191,6 +193,9 @@ pub const NativeTargetInfo = struct {
191 /// deinitialization method.193 /// deinitialization method.
192 /// TODO Remove the Allocator requirement from this function.194 /// TODO Remove the Allocator requirement from this function.
193 pub fn detect(allocator: *Allocator, cross_target: CrossTarget) DetectError!NativeTargetInfo {195 pub fn detect(allocator: *Allocator, cross_target: CrossTarget) DetectError!NativeTargetInfo {
196
197 var cpu_detected = true;
198
194 const cpu = switch (cross_target.cpu_model) {199 const cpu = switch (cross_target.cpu_model) {
195 .native => detectNativeCpuAndFeatures(cross_target),200 .native => detectNativeCpuAndFeatures(cross_target),
196 .baseline => baselineCpuAndFeatures(cross_target),201 .baseline => baselineCpuAndFeatures(cross_target),
...@@ -203,6 +208,11 @@ pub const NativeTargetInfo = struct {...@@ -203,6 +208,11 @@ pub const NativeTargetInfo = struct {
203 cross_target.updateCpuFeatures(&adjusted_model.features);208 cross_target.updateCpuFeatures(&adjusted_model.features);
204 break :blk adjusted_model;209 break :blk adjusted_model;
205 },210 },
211 } orelse backup_cpu_detection: {
212
213 // Temporarily use LLVM's cpu info as a backup
214 cpu_detected = false;
215 break :backup_cpu_detection baselineCpuAndFeatures(cross_target);
206 };216 };
207217
208 var os = Target.Os.defaultVersionRange(cross_target.getOsTag());218 var os = Target.Os.defaultVersionRange(cross_target.getOsTag());
...@@ -318,7 +328,9 @@ pub const NativeTargetInfo = struct {...@@ -318,7 +328,9 @@ pub const NativeTargetInfo = struct {
318 os.version_range.linux.glibc = glibc;328 os.version_range.linux.glibc = glibc;
319 }329 }
320330
321 return detectAbiAndDynamicLinker(allocator, cpu, os, cross_target);331 var target = try detectAbiAndDynamicLinker(allocator, cpu, os, cross_target);
332 target.cpu_detected = cpu_detected;
333 return target;
322 }334 }
323335
324 /// First we attempt to use the executable's own binary. If it is dynamically336 /// First we attempt to use the executable's own binary. If it is dynamically
...@@ -843,19 +855,15 @@ pub const NativeTargetInfo = struct {...@@ -843,19 +855,15 @@ pub const NativeTargetInfo = struct {
843 }855 }
844 }856 }
845857
846 fn detectNativeCpuAndFeatures(cross_target: CrossTarget) Target.Cpu {858 fn detectNativeCpuAndFeatures(cross_target: CrossTarget) ?Target.Cpu {
847
848 var baseline = baselineCpuAndFeatures(cross_target);
849859
850 switch(Target.current.cpu.arch) {860 switch(Target.current.cpu.arch) {
851 .x86_64, .i386 => {861 .x86_64, .i386 => {
852 const x86_detection = @import("system/x86.zig");862 return @import("system/x86.zig").detectNativeCpuAndFeatures(cross_target);
853 x86_detection.detectNativeCpuAndFeatures(&baseline);
854 return baseline;
855 },863 },
856 else => {864 else => {
857 // // TODO Detect native CPU model & features. Until that is implemented we use baseline.865 // TODO flesh out CPU detection for more than just x86.
858 return baseline;866 return null;
859 }867 }
860 }868 }
861 }869 }
lib/std/zig/system/x86.zig+86-167
...@@ -10,70 +10,66 @@ fn setFeature(cpu: *Target.Cpu, feature: Target.x86.Feature, enabled: bool) void...@@ -10,70 +10,66 @@ fn setFeature(cpu: *Target.Cpu, feature: Target.x86.Feature, enabled: bool) void
10 else cpu.features.removeFeature(idx);10 else cpu.features.removeFeature(idx);
11}11}
1212
13fn hasFeature(cpu: *Target.Cpu, feature: Target.x86.Feature) bool {
14 const idx = @as(Target.Cpu.Feature.Set.Index, @enumToInt(feature));
15 return cpu.features.isEnabled(idx);
16}
17
18inline fn bit(input: u32, offset: u5) bool {13inline fn bit(input: u32, offset: u5) bool {
19 return (input >> offset) & 1 != 0;14 return (input >> offset) & 1 != 0;
20}15}
2116
22pub fn detectNativeCpuAndFeatures(cpu: *Target.Cpu) void {17pub fn detectNativeCpuAndFeatures(cross_target: CrossTarget) Target.Cpu {
2318
24 defer {19 var arch = cross_target.getCpuArch();
25 // Whenever we find a model, add that model's featureset.
26 cpu.features.addFeatureSet(cpu.model.features);
27 }
2820
29 // When we can't identify a specific model,21 var cpu = Target.Cpu {
30 // we guess based on processor features.22 .arch = arch,
31 // This seems to be the accepted standard.23 .model = Target.Cpu.Model.baseline(arch),
24 .features = Target.Cpu.Feature.Set.empty,
25 };
3226
33 detectNativeFeatures(cpu);27 detectNativeFeatures(&cpu, cross_target.getOsTag());
3428
35 var leaf = cpuid(0, 0);29 var leaf = cpuid(0, 0);
36 const max_leaf = leaf.eax;30 const max_leaf = leaf.eax;
37 const vendor = leaf.ebx;31 const vendor = leaf.ebx;
38 if(max_leaf < 1) {
39 cpu.model = &Target.x86.cpu.generic;
40 return;
41 }
4232
43 leaf = cpuid(0x1, 0);33 if(max_leaf > 0) {
34
35 leaf = cpuid(0x1, 0);
4436
45 const brand_id = leaf.ebx & 0xff;37 const brand_id = leaf.ebx & 0xff;
46 var family: u32 = 0;38 var family: u32 = 0;
47 var model: u32 = 0;39 var model: u32 = 0;
4840
49 { // Detect model and family41 { // Detect model and family
50 family = (leaf.eax >> 8) & 0xf;42 family = (leaf.eax >> 8) & 0xf;
51 model = (leaf.eax >> 4) & 0xf;43 model = (leaf.eax >> 4) & 0xf;
52 if (family == 6 or family == 0xf) {44 if (family == 6 or family == 0xf) {
53 if (family == 0xf) {45 if (family == 0xf) {
54 family += (leaf.eax >> 20) & 0xff;46 family += (leaf.eax >> 20) & 0xff;
47 }
48 model += ((leaf.eax >> 16) & 0xf) << 4;
55 }49 }
56 model += ((leaf.eax >> 16) & 0xf) << 4;
57 }50 }
58 }
5951
60 switch(vendor) {52 switch(vendor) {
61 0x756e6547 => {53 0x756e6547 => {
62 detectIntelProcessor(cpu, family, model, brand_id);54 detectIntelProcessor(&cpu, family, model, brand_id);
63 },55 },
64 0x68747541 => {56 0x68747541 => {
65 detectAMDProcessor(cpu, family, model);57 detectAMDProcessor(&cpu, family, model);
66 },58 },
67 else => {59 else => {},
68 cpu.model = &Target.x86.cpu.generic;60 }
69 },
70 }61 }
7162
63 var model_features = cpu.model.features;
64 model_features.populateDependencies(cpu.arch.allFeaturesList());
65 cpu.features.addFeatureSet(model_features);
66
67 return cpu;
68
72}69}
7370
74fn detectIntelProcessor(cpu: *Target.Cpu, family: u32, model: u32, brand_id: u32) void {71fn detectIntelProcessor(cpu: *Target.Cpu, family: u32, model: u32, brand_id: u32) void {
75 if (brand_id != 0) {72 if (brand_id != 0) {
76 cpu.model = &Target.x86.cpu.generic;
77 return;73 return;
78 }74 }
79 switch(family) {75 switch(family) {
...@@ -86,7 +82,7 @@ fn detectIntelProcessor(cpu: *Target.Cpu, family: u32, model: u32, brand_id: u32...@@ -86,7 +82,7 @@ fn detectIntelProcessor(cpu: *Target.Cpu, family: u32, model: u32, brand_id: u32
86 return;82 return;
87 },83 },
88 5 => {84 5 => {
89 if(hasFeature(cpu, .mmx)) {85 if(Target.x86.featureSetHas(cpu.features, .mmx)) {
90 cpu.model = &Target.x86.cpu.pentium_mmx;86 cpu.model = &Target.x86.cpu.pentium_mmx;
91 return;87 return;
92 }88 }
...@@ -152,10 +148,10 @@ fn detectIntelProcessor(cpu: *Target.Cpu, family: u32, model: u32, brand_id: u32...@@ -152,10 +148,10 @@ fn detectIntelProcessor(cpu: *Target.Cpu, family: u32, model: u32, brand_id: u32
152 return;148 return;
153 },149 },
154 0x55 => {150 0x55 => {
155 if(hasFeature(cpu, .avx512bf16)) {151 if(Target.x86.featureSetHas(cpu.features, .avx512bf16)) {
156 cpu.model = &Target.x86.cpu.cooperlake;152 cpu.model = &Target.x86.cpu.cooperlake;
157 return;153 return;
158 } else if(hasFeature(cpu, .avx512vnni)) {154 } else if(Target.x86.featureSetHas(cpu.features, .avx512vnni)) {
159 cpu.model = &Target.x86.cpu.cascadelake;155 cpu.model = &Target.x86.cpu.cascadelake;
160 return;156 return;
161 } else {157 } else {
...@@ -204,114 +200,18 @@ fn detectIntelProcessor(cpu: *Target.Cpu, family: u32, model: u32, brand_id: u32...@@ -204,114 +200,18 @@ fn detectIntelProcessor(cpu: *Target.Cpu, family: u32, model: u32, brand_id: u32
204 return;200 return;
205 },201 },
206 else => {202 else => {
207 // Unknown, try to guess.203 // Unknown CPU.
208 // TODO detect tigerlake host204 // Default to baseline x86_64 or i386 cpu.
209 if(hasFeature(cpu, .avx512vp2intersect)) {
210 // TODO no tigerlake entry in Target.x86.cpu
211 //cpu.model = &Target.x86.cpu.tigerlake;
212 cpu.model = &Target.x86.cpu.nehalem;
213 return;
214 }
215 if(hasFeature(cpu, .avx512vbmi2)) {
216 cpu.model = &Target.x86.cpu.icelake_client;
217 return;
218 }
219 if(hasFeature(cpu, .avx512vbmi)) {
220 cpu.model = &Target.x86.cpu.cannonlake;
221 return;
222 }
223 if(hasFeature(cpu, .avx512bf16)) {
224 cpu.model = &Target.x86.cpu.cooperlake;
225 return;
226 }
227 if(hasFeature(cpu, .avx512vnni)) {
228 cpu.model = &Target.x86.cpu.cascadelake;
229 return;
230 }
231 if(hasFeature(cpu, .avx512vl)) {
232 cpu.model = &Target.x86.cpu.skylake_avx512;
233 return;
234 }
235 if(hasFeature(cpu, .avx512er)) {
236 cpu.model = &Target.x86.cpu.knl;
237 return;
238 }
239 if(hasFeature(cpu, .clflushopt)) {
240 if(hasFeature(cpu, .sha)) {
241 cpu.model = &Target.x86.cpu.goldmont;
242 return;
243 } else {
244 cpu.model = &Target.x86.cpu.skylake;
245 return;
246 }
247 }
248 if(hasFeature(cpu, .adx)) {
249 cpu.model = &Target.x86.cpu.broadwell;
250 return;
251 }
252 if(hasFeature(cpu, .avx2)) {
253 cpu.model = &Target.x86.cpu.haswell;
254 return;
255 }
256 if(hasFeature(cpu, .avx)) {
257 cpu.model = &Target.x86.cpu.sandybridge;
258 return;
259 }
260 if(hasFeature(cpu, .sse4_2)) {
261 if(hasFeature(cpu, .movbe)) {
262 cpu.model = &Target.x86.cpu.silvermont;
263 return;
264 } else {
265 cpu.model = &Target.x86.cpu.nehalem;
266 return;
267 }
268 }
269 if(hasFeature(cpu, .sse4_1)) {
270 cpu.model = &Target.x86.cpu.penryn;
271 return;
272 }
273 if(hasFeature(cpu, .sse3)) {
274 if(hasFeature(cpu, .movbe)) {
275 cpu.model = &Target.x86.cpu.bonnell;
276 return;
277 } else {
278 cpu.model = &Target.x86.cpu.core2;
279 return;
280 }
281 }
282
283 if(hasFeature(cpu, .@"64bit")) {
284 cpu.model = &Target.x86.cpu.core2;
285 return;
286 }
287
288 if(hasFeature(cpu, .sse3)) {
289 cpu.model = &Target.x86.cpu.yonah;
290 return;
291 }
292 if(hasFeature(cpu, .sse2)) {
293 cpu.model = &Target.x86.cpu.pentium_m;
294 return;
295 }
296 if(hasFeature(cpu, .sse)) {
297 cpu.model = &Target.x86.cpu.pentium3;
298 return;
299 }
300 if(hasFeature(cpu, .mmx)) {
301 cpu.model = &Target.x86.cpu.pentium2;
302 return;
303 }
304 cpu.model = &Target.x86.cpu.pentiumpro;
305 return;205 return;
306 },206 },
307 }207 }
308 },208 },
309 15 => {209 15 => {
310 if(hasFeature(cpu, .@"64bit")) {210 if(Target.x86.featureSetHas(cpu.features, .@"64bit")) {
311 cpu.model = &Target.x86.cpu.nocona;211 cpu.model = &Target.x86.cpu.nocona;
312 return;212 return;
313 }213 }
314 if(hasFeature(cpu, .sse3)) {214 if(Target.x86.featureSetHas(cpu.features, .sse3)) {
315 cpu.model = &Target.x86.cpu.prescott;215 cpu.model = &Target.x86.cpu.prescott;
316 return;216 return;
317 }217 }
...@@ -319,7 +219,8 @@ fn detectIntelProcessor(cpu: *Target.Cpu, family: u32, model: u32, brand_id: u32...@@ -319,7 +219,8 @@ fn detectIntelProcessor(cpu: *Target.Cpu, family: u32, model: u32, brand_id: u32
319 return;219 return;
320 },220 },
321 else => {221 else => {
322 cpu.model = &Target.x86.cpu.generic;222 // Unknown CPU.
223 // Default to baseline x86_64 or i386 cpu.
323 return;224 return;
324 }225 }
325 }226 }
...@@ -358,7 +259,7 @@ fn detectAMDProcessor(cpu: *Target.Cpu, family: u32, model: u32) void {...@@ -358,7 +259,7 @@ fn detectAMDProcessor(cpu: *Target.Cpu, family: u32, model: u32) void {
358 return;259 return;
359 },260 },
360 6 => {261 6 => {
361 if(hasFeature(cpu, .sse)) {262 if(Target.x86.featureSetHas(cpu.features, .sse)) {
362 cpu.model = &Target.x86.cpu.athlon_xp;263 cpu.model = &Target.x86.cpu.athlon_xp;
363 return;264 return;
364 }265 }
...@@ -366,7 +267,7 @@ fn detectAMDProcessor(cpu: *Target.Cpu, family: u32, model: u32) void {...@@ -366,7 +267,7 @@ fn detectAMDProcessor(cpu: *Target.Cpu, family: u32, model: u32) void {
366 return;267 return;
367 },268 },
368 15 => {269 15 => {
369 if(hasFeature(cpu, .sse3)) {270 if(Target.x86.featureSetHas(cpu.features, .sse3)) {
370 cpu.model = &Target.x86.cpu.k8_sse3;271 cpu.model = &Target.x86.cpu.k8_sse3;
371 return;272 return;
372 }273 }
...@@ -410,13 +311,12 @@ fn detectAMDProcessor(cpu: *Target.Cpu, family: u32, model: u32) void {...@@ -410,13 +311,12 @@ fn detectAMDProcessor(cpu: *Target.Cpu, family: u32, model: u32) void {
410 return;311 return;
411 },312 },
412 else => {313 else => {
413 cpu.model = &Target.x86.cpu.generic;
414 return;314 return;
415 }315 }
416 }316 }
417}317}
418318
419fn detectNativeFeatures(cpu: *Target.Cpu) void {319fn detectNativeFeatures(cpu: *Target.Cpu, os_type: Target.Os.Tag) void {
420320
421 var leaf = cpuid(0, 0);321 var leaf = cpuid(0, 0);
422322
...@@ -442,23 +342,42 @@ fn detectNativeFeatures(cpu: *Target.Cpu) void {...@@ -442,23 +342,42 @@ fn detectNativeFeatures(cpu: *Target.Cpu) void {
442 setFeature(cpu, .aes, bit(leaf.ecx, 25));342 setFeature(cpu, .aes, bit(leaf.ecx, 25));
443 setFeature(cpu, .rdrnd, bit(leaf.ecx, 30));343 setFeature(cpu, .rdrnd, bit(leaf.ecx, 30));
444344
445 const has_avx_save = bit(leaf.ecx, 27) and345 leaf.eax = getXCR0();
446 bit(leaf.ecx, 28) and346
447 ((leaf.eax & 0x6) == 0x6);347 const has_avx = bit(leaf.ecx, 27) and
348 bit(leaf.ecx, 28) and
349 ((leaf.eax & 0x6) == 0x6);
350
351 // LLVM approaches avx512_save by hardcoding it to true on Darwin,
352 // because the kernel saves the context even if the bit is not set.
353 // https://github.com/llvm/llvm-project/blob/bca373f73fc82728a8335e7d6cd164e8747139ec/llvm/lib/Support/Host.cpp#L1378
354 //
355 // Google approaches this by using a different series of checks and flags,
356 // and this may report the feature more accurately on a technically correct
357 // but ultimately less useful level.
358 // https://github.com/google/cpu_features/blob/b5c271c53759b2b15ff91df19bd0b32f2966e275/src/cpuinfo_x86.c#L113
359 // (called from https://github.com/google/cpu_features/blob/b5c271c53759b2b15ff91df19bd0b32f2966e275/src/cpuinfo_x86.c#L1052)
360 //
361 // Right now, we use LLVM's approach, because even if the target doesn't support
362 // the feature, the kernel should provide the same functionality transparently,
363 // so the implementation details don't make a difference.
364 // That said, this flag impacts other CPU features' availability,
365 // so until we can verify that this doesn't come with side affects,
366 // we'll say TODO verify this.
448367
449 // Darwin lazily saves the AVX512 context on first use: trust that the OS will368 // Darwin lazily saves the AVX512 context on first use: trust that the OS will
450 // save the AVX512 context if we use AVX512 instructions, even the bit is not369 // save the AVX512 context if we use AVX512 instructions, even if the bit is not
451 // set right now.370 // set right now.
452 const has_avx512_save = switch(Target.current.isDarwin()) {371 const has_avx512_save = switch(os_type.isDarwin()) {
453 true => true,372 true => true,
454 false => has_avx_save and ((leaf.eax & 0xE0) == 0xE0),373 false => has_avx and ((leaf.eax & 0xE0) == 0xE0),
455 };374 };
456375
457 setFeature(cpu, .avx, has_avx_save);376 setFeature(cpu, .avx, has_avx);
458 setFeature(cpu, .fma, has_avx_save and bit(leaf.ecx, 12));377 setFeature(cpu, .fma, has_avx and bit(leaf.ecx, 12));
459 // Only enable XSAVE if OS has enabled support for saving YMM state.378 // Only enable XSAVE if OS has enabled support for saving YMM state.
460 setFeature(cpu, .xsave, has_avx_save and bit(leaf.ecx, 26));379 setFeature(cpu, .xsave, has_avx and bit(leaf.ecx, 26));
461 setFeature(cpu, .f16c, has_avx_save and bit(leaf.ecx, 29));380 setFeature(cpu, .f16c, has_avx and bit(leaf.ecx, 29));
462381
463 leaf = cpuid(0x80000000, 0);382 leaf = cpuid(0x80000000, 0);
464 const max_ext_level = leaf.eax;383 const max_ext_level = leaf.eax;
...@@ -469,9 +388,9 @@ fn detectNativeFeatures(cpu: *Target.Cpu) void {...@@ -469,9 +388,9 @@ fn detectNativeFeatures(cpu: *Target.Cpu) void {
469 setFeature(cpu, .lzcnt, bit(leaf.ecx, 5));388 setFeature(cpu, .lzcnt, bit(leaf.ecx, 5));
470 setFeature(cpu, .sse4a, bit(leaf.ecx, 6));389 setFeature(cpu, .sse4a, bit(leaf.ecx, 6));
471 setFeature(cpu, .prfchw, bit(leaf.ecx, 8));390 setFeature(cpu, .prfchw, bit(leaf.ecx, 8));
472 setFeature(cpu, .xop, bit(leaf.ecx, 11) and has_avx_save);391 setFeature(cpu, .xop, bit(leaf.ecx, 11) and has_avx);
473 setFeature(cpu, .lwp, bit(leaf.ecx, 15));392 setFeature(cpu, .lwp, bit(leaf.ecx, 15));
474 setFeature(cpu, .fma4, bit(leaf.ecx, 16) and has_avx_save);393 setFeature(cpu, .fma4, bit(leaf.ecx, 16) and has_avx);
475 setFeature(cpu, .tbm, bit(leaf.ecx, 21));394 setFeature(cpu, .tbm, bit(leaf.ecx, 21));
476 setFeature(cpu, .mwaitx, bit(leaf.ecx, 29));395 setFeature(cpu, .mwaitx, bit(leaf.ecx, 29));
477 setFeature(cpu, .@"64bit", bit(leaf.edx, 29));396 setFeature(cpu, .@"64bit", bit(leaf.edx, 29));
...@@ -486,7 +405,7 @@ fn detectNativeFeatures(cpu: *Target.Cpu) void {...@@ -486,7 +405,7 @@ fn detectNativeFeatures(cpu: *Target.Cpu) void {
486405
487 // Misc. memory-related features.406 // Misc. memory-related features.
488 if(max_ext_level >= 0x80000008) {407 if(max_ext_level >= 0x80000008) {
489 leaf = cpuid(80000008, 0);408 leaf = cpuid(0x80000008, 0);
490 setFeature(cpu, .clzero, bit(leaf.ebx, 0));409 setFeature(cpu, .clzero, bit(leaf.ebx, 0));
491 setFeature(cpu, .wbnoinvd, bit(leaf.ebx, 9));410 setFeature(cpu, .wbnoinvd, bit(leaf.ebx, 9));
492 } else {411 } else {
...@@ -495,14 +414,14 @@ fn detectNativeFeatures(cpu: *Target.Cpu) void {...@@ -495,14 +414,14 @@ fn detectNativeFeatures(cpu: *Target.Cpu) void {
495 }414 }
496 }415 }
497416
498 if(max_level >= 7) {417 if(max_level >= 0x7) {
499 leaf = cpuid(0x7, 0);418 leaf = cpuid(0x7, 0);
500419
501 setFeature(cpu, .fsgsbase, bit(leaf.ebx, 0));420 setFeature(cpu, .fsgsbase, bit(leaf.ebx, 0));
502 setFeature(cpu, .sgx, bit(leaf.ebx, 2));421 setFeature(cpu, .sgx, bit(leaf.ebx, 2));
503 setFeature(cpu, .bmi, bit(leaf.ebx, 3));422 setFeature(cpu, .bmi, bit(leaf.ebx, 3));
504 // AVX2 is only supported if we have the OS save support from AVX.423 // AVX2 is only supported if we have the OS save support from AVX.
505 setFeature(cpu, .avx2, bit(leaf.ebx, 5) and has_avx_save);424 setFeature(cpu, .avx2, bit(leaf.ebx, 5) and has_avx);
506 setFeature(cpu, .bmi2, bit(leaf.ebx, 8));425 setFeature(cpu, .bmi2, bit(leaf.ebx, 8));
507 setFeature(cpu, .invpcid, bit(leaf.ebx, 10));426 setFeature(cpu, .invpcid, bit(leaf.ebx, 10));
508 setFeature(cpu, .rtm, bit(leaf.ebx, 11));427 setFeature(cpu, .rtm, bit(leaf.ebx, 11));
...@@ -528,8 +447,8 @@ fn detectNativeFeatures(cpu: *Target.Cpu) void {...@@ -528,8 +447,8 @@ fn detectNativeFeatures(cpu: *Target.Cpu) void {
528 setFeature(cpu, .avx512vbmi2, bit(leaf.ecx, 6) and has_avx512_save);447 setFeature(cpu, .avx512vbmi2, bit(leaf.ecx, 6) and has_avx512_save);
529 setFeature(cpu, .shstk, bit(leaf.ecx, 7));448 setFeature(cpu, .shstk, bit(leaf.ecx, 7));
530 setFeature(cpu, .gfni, bit(leaf.ecx, 8));449 setFeature(cpu, .gfni, bit(leaf.ecx, 8));
531 setFeature(cpu, .vaes, bit(leaf.ecx, 9) and has_avx_save);450 setFeature(cpu, .vaes, bit(leaf.ecx, 9) and has_avx);
532 setFeature(cpu, .vpclmulqdq, bit(leaf.ecx, 10) and has_avx_save);451 setFeature(cpu, .vpclmulqdq, bit(leaf.ecx, 10) and has_avx);
533 setFeature(cpu, .avx512vnni, bit(leaf.ecx, 11) and has_avx512_save);452 setFeature(cpu, .avx512vnni, bit(leaf.ecx, 11) and has_avx512_save);
534 setFeature(cpu, .avx512bitalg, bit(leaf.ecx, 12) and has_avx512_save);453 setFeature(cpu, .avx512bitalg, bit(leaf.ecx, 12) and has_avx512_save);
535 setFeature(cpu, .avx512vpopcntdq, bit(leaf.ecx, 14) and has_avx512_save);454 setFeature(cpu, .avx512vpopcntdq, bit(leaf.ecx, 14) and has_avx512_save);
...@@ -580,7 +499,7 @@ fn detectNativeFeatures(cpu: *Target.Cpu) void {...@@ -580,7 +499,7 @@ fn detectNativeFeatures(cpu: *Target.Cpu) void {
580 }499 }
581 }500 }
582501
583 if(max_level >= 0xD and has_avx_save) {502 if(max_level >= 0xD and has_avx) {
584 leaf = cpuid(0xD, 0x1);503 leaf = cpuid(0xD, 0x1);
585 // Only enable XSAVE if OS has enabled support for saving YMM state.504 // Only enable XSAVE if OS has enabled support for saving YMM state.
586 setFeature(cpu, .xsaveopt, bit(leaf.eax, 0));505 setFeature(cpu, .xsaveopt, bit(leaf.eax, 0));
src-self-hosted/stage2.zig+1-2
...@@ -1154,8 +1154,7 @@ fn enumInt(comptime Enum: type, int: c_int) Enum {...@@ -1154,8 +1154,7 @@ fn enumInt(comptime Enum: type, int: c_int) Enum {
11541154
1155fn crossTargetToTarget(cross_target: CrossTarget, dynamic_linker_ptr: *?[*:0]u8) !Target {1155fn crossTargetToTarget(cross_target: CrossTarget, dynamic_linker_ptr: *?[*:0]u8) !Target {
1156 var info = try std.zig.system.NativeTargetInfo.detect(std.heap.c_allocator, cross_target);1156 var info = try std.zig.system.NativeTargetInfo.detect(std.heap.c_allocator, cross_target);
1157 if ((cross_target.cpu_arch == null or cross_target.cpu_model == .native) and1157 if ((cross_target.cpu_arch == null or cross_target.cpu_model == .native) and !info.cpu_detected) {
1158 (Target.current.cpu.arch != .i386 and Target.current.cpu.arch != .x86_64)) {
1159 // TODO We want to just use detected_info.target but implementing1158 // TODO We want to just use detected_info.target but implementing
1160 // CPU model & feature detection is todo so here we rely on LLVM.1159 // CPU model & feature detection is todo so here we rely on LLVM.
1161 const llvm = @import("llvm.zig");1160 const llvm = @import("llvm.zig");