From 373ae071132bd80737d02e474230da7ecd865482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Tue, 20 Oct 2026 04:26:44 +0200 Subject: [PATCH] update_cpu_features: add and use cpu_overrides field It was really confusing that feature_overrides was pulling double duty for both features and models. Now there's a clean split between the two. The new cpu_overrides also subsumes omit_cpus. This in turn uncovered a bug where some x86 models were not getting the smep/smap features. --- lib/std/Target/x86.zig | 16 +- tools/update_cpu_features.zig | 529 +++++++++++++++++++++------------- 2 files changed, 344 insertions(+), 201 deletions(-) diff --git a/lib/std/Target/x86.zig b/lib/std/Target/x86.zig index 0bcc2638f16f0bb4cb553d35d3b94a3f7962b7ed..418ae155b721ddd87a550580dcb669247f7cbe58 100644 --- a/lib/std/Target/x86.zig +++ b/lib/std/Target/x86.zig @@ -3136,7 +3136,7 @@ pub const cpu = struct { }; pub const goldmont_plus: CpuModel = .{ .name = "goldmont_plus", - .llvm_name = "goldmont-plus", + .llvm_name = "goldmont_plus", .features = featureSet(&[_]Feature{ .@"64bit", .aes, @@ -3163,6 +3163,8 @@ pub const cpu = struct { .slow_incdec, .slow_lea, .slow_two_mem_ops, + .smap, + .smep, .sse4_2, .use_glm_div_sqrt_costs, .vzeroupper, @@ -3564,7 +3566,7 @@ pub const cpu = struct { }; pub const icelake_client: CpuModel = .{ .name = "icelake_client", - .llvm_name = "icelake-client", + .llvm_name = "icelake_client", .features = featureSet(&[_]Feature{ .@"64bit", .adx, @@ -3615,6 +3617,8 @@ pub const cpu = struct { .sahf, .sha, .slow_pmullq, + .smap, + .smep, .tuning_fast_imm_vector_shift, .vaes, .vpclmulqdq, @@ -3627,7 +3631,7 @@ pub const cpu = struct { }; pub const icelake_server: CpuModel = .{ .name = "icelake_server", - .llvm_name = "icelake-server", + .llvm_name = "icelake_server", .features = featureSet(&[_]Feature{ .@"64bit", .adx, @@ -3680,6 +3684,8 @@ pub const cpu = struct { .sahf, .sha, .slow_pmullq, + .smap, + .smep, .tuning_fast_imm_vector_shift, .vaes, .vpclmulqdq, @@ -4872,7 +4878,7 @@ pub const cpu = struct { }; pub const skylake_avx512: CpuModel = .{ .name = "skylake_avx512", - .llvm_name = "skylake-avx512", + .llvm_name = "skylake_avx512", .features = featureSet(&[_]Feature{ .@"64bit", .adx, @@ -4919,6 +4925,8 @@ pub const cpu = struct { .rdseed, .sahf, .slow_3ops_lea, + .smap, + .smep, .tuning_fast_imm_vector_shift, .vzeroupper, .x87, diff --git a/tools/update_cpu_features.zig b/tools/update_cpu_features.zig index 0f9296730ef43ce64bc3ea7ef36fd9abb0d7bbf4..3b1cc22b1281b844292fbd347753fb856572b93b 100644 --- a/tools/update_cpu_features.zig +++ b/tools/update_cpu_features.zig @@ -23,6 +23,16 @@ const FeatureOverride = struct { extra_deps: []const []const u8 = &.{}, }; +const CpuOverride = struct { + llvm_name: []const u8, + /// If true, completely omit the CPU; as if it does not exist. + omit: bool = false, + zig_name: ?[]const u8 = null, + desc: ?[]const u8 = null, + omit_deps: []const []const u8 = &.{}, + extra_deps: []const []const u8 = &.{}, +}; + const Cpu = struct { llvm_name: ?[]const u8, zig_name: []const u8, @@ -44,9 +54,9 @@ const ArchTarget = struct { td_name: []const u8, }, feature_overrides: []const FeatureOverride = &.{}, - extra_cpus: []const Cpu = &.{}, extra_features: []const Feature = &.{}, - omit_cpus: []const []const u8 = &.{}, + cpu_overrides: []const CpuOverride = &.{}, + extra_cpus: []const Cpu = &.{}, branch_quota: ?usize = null, }; @@ -432,6 +442,14 @@ const targets = [_]ArchTarget{ .flatten = true, }, }, + .cpu_overrides = &.{ + .{ + // Who thought this alias was a good idea? Upgrade your compiler and suddenly your + // programs SIGILL because this changed meaning. Brilliant. + .llvm_name = "apple-latest", + .omit = true, + }, + }, .extra_cpus = &.{ .{ .llvm_name = null, @@ -485,11 +503,6 @@ const targets = [_]ArchTarget{ }, }, }, - .omit_cpus = &.{ - // Who thought this alias was a good idea? Upgrade your compiler and suddenly your - // programs SIGILL because this changed meaning. Brilliant. - "apple-latest", - }, }, .{ .zig_name = "alpha", @@ -754,63 +767,6 @@ const targets = [_]ArchTarget{ .flatten = true, }, - .{ - .llvm_name = "cortex-m4", - .omit_deps = &.{"vfp4d16sp"}, - }, - .{ - .llvm_name = "cortex-m7", - .omit_deps = &.{"fp_armv8d16"}, - }, - .{ - .llvm_name = "cortex-m33", - .omit_deps = &.{ "dsp", "fp_armv8d16sp" }, - }, - .{ - .llvm_name = "cortex-m35p", - .omit_deps = &.{ "dsp", "fp_armv8d16sp" }, - }, - .{ - .llvm_name = "cortex-m52", - .omit_deps = &.{ "fp_armv8d16", "mve_fp", "pacbti" }, - }, - .{ - .llvm_name = "cortex-m55", - .omit_deps = &.{ "fp_armv8d16", "mve_fp" }, - }, - .{ - .llvm_name = "cortex-m85", - .omit_deps = &.{ "fp_armv8d16", "mve_fp", "pacbti" }, - }, - .{ - .llvm_name = "cortex-r5", - .omit_deps = &.{"vfp3d16"}, - }, - .{ - .llvm_name = "cortex-r7", - .omit_deps = &.{ "fp16", "vfp3d16" }, - }, - .{ - .llvm_name = "cortex-r8", - .omit_deps = &.{ "fp16", "vfp3d16" }, - }, - .{ - .llvm_name = "cortex-r52", - .omit_deps = &.{ "fp_armv8", "neon" }, - }, - .{ - .llvm_name = "cortex-r52plus", - .omit_deps = &.{ "fp_armv8", "neon" }, - }, - .{ - .llvm_name = "star-mc1", - .omit_deps = &.{ "dsp", "fp_armv8d16sp" }, - }, - .{ - .llvm_name = "star-mc3", - .omit_deps = &.{ "fp_armv8d16", "mve_fp", "pacbti" }, - }, - .{ .llvm_name = "armv2", .zig_name = "v2", @@ -1121,23 +1077,6 @@ const targets = [_]ArchTarget{ .zig_name = "has_v9_7a", }, }, - .extra_cpus = &.{ - .{ - .llvm_name = "generic", - .zig_name = "baseline", - .features = &.{"v7a"}, - }, - .{ - .llvm_name = null, - .zig_name = "exynos_m1", - .features = &.{ "v8a", "exynos" }, - }, - .{ - .llvm_name = null, - .zig_name = "exynos_m2", - .features = &.{ "v8a", "exynos" }, - }, - }, .extra_features = &.{ // LLVM removed support for v2 and v3 but zig wants to support targeting old hardware .{ @@ -1161,6 +1100,81 @@ const targets = [_]ArchTarget{ .deps = &.{"strict_align"}, }, }, + .cpu_overrides = &.{ + .{ + .llvm_name = "cortex-m4", + .omit_deps = &.{"vfp4d16sp"}, + }, + .{ + .llvm_name = "cortex-m7", + .omit_deps = &.{"fp_armv8d16"}, + }, + .{ + .llvm_name = "cortex-m33", + .omit_deps = &.{ "dsp", "fp_armv8d16sp" }, + }, + .{ + .llvm_name = "cortex-m35p", + .omit_deps = &.{ "dsp", "fp_armv8d16sp" }, + }, + .{ + .llvm_name = "cortex-m52", + .omit_deps = &.{ "fp_armv8d16", "mve_fp", "pacbti" }, + }, + .{ + .llvm_name = "cortex-m55", + .omit_deps = &.{ "fp_armv8d16", "mve_fp" }, + }, + .{ + .llvm_name = "cortex-m85", + .omit_deps = &.{ "fp_armv8d16", "mve_fp", "pacbti" }, + }, + .{ + .llvm_name = "cortex-r5", + .omit_deps = &.{"vfp3d16"}, + }, + .{ + .llvm_name = "cortex-r7", + .omit_deps = &.{ "fp16", "vfp3d16" }, + }, + .{ + .llvm_name = "cortex-r8", + .omit_deps = &.{ "fp16", "vfp3d16" }, + }, + .{ + .llvm_name = "cortex-r52", + .omit_deps = &.{ "fp_armv8", "neon" }, + }, + .{ + .llvm_name = "cortex-r52plus", + .omit_deps = &.{ "fp_armv8", "neon" }, + }, + .{ + .llvm_name = "star-mc1", + .omit_deps = &.{ "dsp", "fp_armv8d16sp" }, + }, + .{ + .llvm_name = "star-mc3", + .omit_deps = &.{ "fp_armv8d16", "mve_fp", "pacbti" }, + }, + }, + .extra_cpus = &.{ + .{ + .llvm_name = "generic", + .zig_name = "baseline", + .features = &.{"v7a"}, + }, + .{ + .llvm_name = null, + .zig_name = "exynos_m1", + .features = &.{ "v8a", "exynos" }, + }, + .{ + .llvm_name = null, + .zig_name = "exynos_m2", + .features = &.{ "v8a", "exynos" }, + }, + }, }, .{ .zig_name = "avr", @@ -1470,6 +1484,24 @@ const targets = [_]ArchTarget{ .name = "LoongArch", .td_name = "LoongArch", }, + .cpu_overrides = &.{ + .{ + .llvm_name = "generic", + .omit = true, + }, + .{ + .llvm_name = "generic-la64", + .omit = true, + }, + .{ + .llvm_name = "loongarch32", + .omit = true, + }, + .{ + .llvm_name = "loongarch64", + .omit = true, + }, + }, .extra_cpus = &.{ .{ .llvm_name = null, @@ -1521,12 +1553,6 @@ const targets = [_]ArchTarget{ }, }, }, - .omit_cpus = &.{ - "generic", - "generic-la64", - "loongarch32", - "loongarch64", - }, }, .{ .zig_name = "m68k", @@ -1607,6 +1633,12 @@ const targets = [_]ArchTarget{ .omit = true, }, }, + .cpu_overrides = &.{ + .{ + .llvm_name = "ppc32", + .omit = true, + }, + }, .extra_cpus = &.{ .{ .llvm_name = null, @@ -1643,9 +1675,6 @@ const targets = [_]ArchTarget{ }, }, }, - .omit_cpus = &.{ - "ppc32", - }, }, .{ .zig_name = "propeller", @@ -1744,6 +1773,12 @@ const targets = [_]ArchTarget{ .deps = &.{}, }, }, + .cpu_overrides = &.{ + .{ + .llvm_name = "generic", + .omit = true, + }, + }, .extra_cpus = &.{ .{ .llvm_name = null, @@ -1761,9 +1796,6 @@ const targets = [_]ArchTarget{ .features = &.{ "ve3", "vpu" }, }, }, - .omit_cpus = &.{ - "generic", - }, }, .{ .zig_name = "wasm", @@ -1798,6 +1830,16 @@ const targets = [_]ArchTarget{ .deps = &.{"bulk_memory_opt"}, }, }, + .cpu_overrides = &.{ + .{ + .llvm_name = "bleeding-edge", + .omit = true, + }, + .{ + .llvm_name = "generic", + .omit = true, + }, + }, .extra_cpus = &.{ .{ .llvm_name = null, @@ -1836,10 +1878,6 @@ const targets = [_]ArchTarget{ }, }, }, - .omit_cpus = &.{ - "bleeding-edge", - "generic", - }, }, .{ .zig_name = "x86", @@ -1865,21 +1903,59 @@ const targets = [_]ArchTarget{ .omit = true, }, .{ - .llvm_name = "alderlake", - .extra_deps = &.{ "smap", "smep" }, + .llvm_name = "sse4.2", + .extra_deps = &.{"crc32"}, }, + }, + .extra_features = &.{ + // Features removed from LLVM + .{ + .zig_name = "3dnow", + .desc = "Enable 3DNow! instructions", + .deps = &.{"mmx"}, + }, + .{ + .zig_name = "3dnowa", + .desc = "Enable 3DNow! Athlon instructions", + .deps = &.{"3dnow"}, + }, + .{ + .zig_name = "avx512er", + .desc = "Enable AVX-512 Exponential and Reciprocal Instructions", + .deps = &.{"avx512f"}, + }, + .{ + .zig_name = "avx512pf", + .desc = "Enable AVX-512 PreFetch Instructions", + .deps = &.{"avx512f"}, + }, + .{ + .zig_name = "prefetchwt1", + .desc = "Prefetch with Intent to Write and T1 Hint", + .deps = &.{}, + }, + // Custom Zig features + .{ + .zig_name = "bsf_bsr_0_clobbers_result", + .desc = "BSF/BSR may clobber the lower 32-bits of the result register when the source is zero", + .deps = &.{}, + }, + .{ + .zig_name = "smap", + .desc = "Enable Supervisor Mode Access Prevention", + .deps = &.{}, + }, + .{ + .zig_name = "smep", + .desc = "Enable Supervisor Mode Execution Prevention", + .deps = &.{}, + }, + }, + .cpu_overrides = &.{ .{ .llvm_name = "amdfam10", .extra_deps = &.{"3dnowa"}, }, - .{ - .llvm_name = "arrowlake", - .extra_deps = &.{ "smap", "smep" }, - }, - .{ - .llvm_name = "arrowlake-s", - .extra_deps = &.{ "smap", "smep" }, - }, .{ .llvm_name = "athlon", .extra_deps = &.{"3dnowa"}, @@ -2057,8 +2133,16 @@ const targets = [_]ArchTarget{ .extra_deps = &.{"3dnow"}, }, .{ - .llvm_name = "sse4.2", - .extra_deps = &.{"crc32"}, + .llvm_name = "alderlake", + .extra_deps = &.{ "smap", "smep" }, + }, + .{ + .llvm_name = "arrowlake", + .extra_deps = &.{ "smap", "smep" }, + }, + .{ + .llvm_name = "arrowlake-s", + .extra_deps = &.{ "smap", "smep" }, }, .{ .llvm_name = "znver1", @@ -2080,49 +2164,131 @@ const targets = [_]ArchTarget{ .llvm_name = "znver5", .extra_deps = &.{ "smap", "smep" }, }, - }, - .extra_features = &.{ - // Features removed from LLVM + + // LLVM defines a bunch of dumb aliases with foreach loops in X86.td. .{ - .zig_name = "3dnow", - .desc = "Enable 3DNow! instructions", - .deps = &.{"mmx"}, + .llvm_name = "pentium_mmx", + .omit = true, }, .{ - .zig_name = "3dnowa", - .desc = "Enable 3DNow! Athlon instructions", - .deps = &.{"3dnow"}, + .llvm_name = "pentium_pro", + .omit = true, }, .{ - .zig_name = "avx512er", - .desc = "Enable AVX-512 Exponential and Reciprocal Instructions", - .deps = &.{"avx512f"}, + .llvm_name = "pentium_ii", + .omit = true, }, .{ - .zig_name = "avx512pf", - .desc = "Enable AVX-512 PreFetch Instructions", - .deps = &.{"avx512f"}, + .llvm_name = "pentium_3m", + .omit = true, }, .{ - .zig_name = "prefetchwt1", - .desc = "Prefetch with Intent to Write and T1 Hint", - .deps = &.{}, + .llvm_name = "pentium_iii", + .omit = true, }, - // Custom Zig features .{ - .zig_name = "bsf_bsr_0_clobbers_result", - .desc = "BSF/BSR may clobber the lower 32-bits of the result register when the source is zero", - .deps = &.{}, + .llvm_name = "pentium_iii_no_xmm_regs", + .omit = true, }, .{ - .zig_name = "smap", - .desc = "Enable Supervisor Mode Access Prevention", - .deps = &.{}, + .llvm_name = "pentium_m", + .omit = true, }, .{ - .zig_name = "smep", - .desc = "Enable Supervisor Mode Execution Prevention", - .deps = &.{}, + .llvm_name = "pentium4m", + .omit = true, + }, + .{ + .llvm_name = "pentium_4", + .omit = true, + }, + .{ + .llvm_name = "pentium_4_sse3", + .omit = true, + }, + .{ + .llvm_name = "core_2_duo_ssse3", + .omit = true, + }, + .{ + .llvm_name = "core_2_duo_sse4_1", + .omit = true, + }, + .{ + .llvm_name = "atom_sse4_2", + .omit = true, + }, + .{ + .llvm_name = "goldmont-plus", + .omit = true, + }, + .{ + .llvm_name = "core_i7_sse4_2", + .omit = true, + }, + .{ + .llvm_name = "core_aes_pclmulqdq", + .omit = true, + }, + .{ + .llvm_name = "corei7-avx", + .omit = true, + }, + .{ + .llvm_name = "core_2nd_gen_avx", + .omit = true, + }, + .{ + .llvm_name = "core-avx-i", + .omit = true, + }, + .{ + .llvm_name = "core_3rd_gen_avx", + .omit = true, + }, + .{ + .llvm_name = "core-avx2", + .omit = true, + }, + .{ + .llvm_name = "core_4th_gen_avx", + .omit = true, + }, + .{ + .llvm_name = "core_4th_gen_avx_tsx", + .omit = true, + }, + .{ + .llvm_name = "core_5th_gen_avx", + .omit = true, + }, + .{ + .llvm_name = "core_5th_gen_avx_tsx", + .omit = true, + }, + .{ + .llvm_name = "mic_avx512", + .omit = true, + }, + .{ + .llvm_name = "skylake-avx512", + .omit = true, + }, + .{ + .llvm_name = "icelake-client", + .omit = true, + }, + .{ + .llvm_name = "icelake-server", + .omit = true, + }, + .{ + .llvm_name = "graniterapids_d", + .omit = true, + }, + .{ + .llvm_name = "arrowlake_s", + .omit = true, }, }, .extra_cpus = &.{ @@ -2132,40 +2298,6 @@ const targets = [_]ArchTarget{ .features = &.{"16bit_mode"}, }, }, - .omit_cpus = &.{ - // LLVM defines a bunch of dumb aliases with foreach loops in X86.td. - "pentium_mmx", - "pentium_pro", - "pentium_ii", - "pentium_3m", - "pentium_iii_no_xmm_regs", - "pentium_iii", - "pentium_m", - "pentium4m", - "pentium_4", - "pentium_4_sse3", - "core_2_duo_ssse3", - "core_2_duo_sse4_1", - "atom_sse4_2", - "goldmont_plus", - "core_i7_sse4_2", - "core_aes_pclmulqdq", - "corei7-avx", - "core_2nd_gen_avx", - "core-avx-i", - "core_3rd_gen_avx", - "core-avx2", - "core_4th_gen_avx", - "core_4th_gen_avx_tsx", - "core_5th_gen_avx", - "core_5th_gen_avx_tsx", - "mic_avx512", - "skylake_avx512", - "icelake_client", - "icelake_server", - "graniterapids_d", - "arrowlake_s", - }, }, .{ .zig_name = "xcore", @@ -2195,6 +2327,16 @@ const targets = [_]ArchTarget{ .deps = &.{"xs3"}, }, }, + .cpu_overrides = &.{ + .{ + .llvm_name = "generic", + .omit = true, + }, + .{ + .llvm_name = "xs1b-generic", + .omit = true, + }, + }, .extra_cpus = &.{ .{ .llvm_name = null, @@ -2212,10 +2354,6 @@ const targets = [_]ArchTarget{ .features = &.{ "fpu", "vpu" }, }, }, - .omit_cpus = &.{ - "generic", - "xs1b-generic", - }, }, .{ .zig_name = "xtensa", @@ -2491,28 +2629,25 @@ fn processOneTargetInner(io: Io, job: Job) !void { if (hasSuperclass(&kv.value_ptr.object, "Processor")) { const llvm_name = kv.value_ptr.object.get("Name").?.string; if (llvm_name.len == 0) continue; - const omitted = for (target.omit_cpus) |omit_cpu_name| { - if (mem.eql(u8, omit_cpu_name, llvm_name)) break true; + + var zig_name = try llvmNameToZigName(arena, llvm_name); + var deps = std.array_list.Managed([]const u8).init(arena); + var omit_deps: []const []const u8 = &.{}; + var extra_deps: []const []const u8 = &.{}; + const omitted = for (target.cpu_overrides) |cpu_override| { + if (mem.eql(u8, llvm_name, cpu_override.llvm_name)) { + if (cpu_override.omit) { + break true; + } + if (cpu_override.zig_name) |override_name| { + zig_name = override_name; + } + omit_deps = cpu_override.omit_deps; + extra_deps = cpu_override.extra_deps; + break false; + } } else false; if (omitted) continue; - - var zig_name = try llvmNameToZigName(arena, llvm_name); - var deps = std.array_list.Managed([]const u8).init(arena); - var omit_deps: []const []const u8 = &.{}; - var extra_deps: []const []const u8 = &.{}; - for (target.feature_overrides) |feature_override| { - if (mem.eql(u8, llvm_name, feature_override.llvm_name)) { - if (feature_override.omit) { - continue; - } - if (feature_override.zig_name) |override_name| { - zig_name = override_name; - } - omit_deps = feature_override.omit_deps; - extra_deps = feature_override.extra_deps; - break; - } - } const features = kv.value_ptr.object.get("Features").?.array; for (features.items) |feature| { const feature_key = feature.object.get("def").?.string; @@ -2554,8 +2689,8 @@ fn processOneTargetInner(io: Io, job: Job) !void { if (cpu_aliases.get(zig_name)) |aliases| { alias_it: for (aliases.items) |alias| { - for (target.omit_cpus) |omit_cpu_name| { - if (mem.eql(u8, omit_cpu_name, alias.llvm)) continue :alias_it; + for (target.cpu_overrides) |cpu_override| { + if (mem.eql(u8, alias.llvm, cpu_override.llvm_name) and cpu_override.omit) continue :alias_it; } try all_cpus.append(.{ -- 2.54.0