Replace hand-maintained CPU tables with cpufeatures library#61292
Replace hand-maintained CPU tables with cpufeatures library#61292
Conversation
c8feee0 to
305e39a
Compare
99ee2ec to
70a6976
Compare
src/processor_cpufeatures.cpp
Outdated
|
|
||
| #if defined(_CPU_X86_64_) || defined(_CPU_X86_) | ||
| // KNL/KNM special case | ||
| if (!(t.dis.flags & JL_TARGET_CLONE_ALL)) { |
There was a problem hiding this comment.
I don't think we care about knl
|
Haven't reviewed in detail, but directionally, this is exactly what I wanted. |
|
This makes the aarch64-linux-gnu tests error (more than usual, that is), because now this literally spamming everywhere. Edit: same for aarch64-darwin, which at least errors more loudly. |
|
Also, on an aarch64-linux system with big.LITTLE architecture Cortex-X925 + A725, this PR detects the CPU as the little variant: $ julia +nightly -E 'Sys.CPU_NAME'
"cortex-x925"
$ julia +pr61292 -E 'Sys.CPU_NAME'
'-contextidrel2' is not a recognized feature for this target (ignoring feature)
'-contextidrel2' is not a recognized feature for this target (ignoring feature)
'-contextidrel2' is not a recognized feature for this target (ignoring feature)
'-contextidrel2' is not a recognized feature for this target (ignoring feature)
'-contextidrel2' is not a recognized feature for this target (ignoring feature)
'-contextidrel2' is not a recognized feature for this target (ignoring feature)
'-contextidrel2' is not a recognized feature for this target (ignoring feature)
"cortex-a725" |
|
Is there a way to handle aliases? M1, M2, and M3 are aliases of their mobile a1x counterparts. julia> Base.BinaryPlatforms.CPUID._lookup_cpu("apple-a15")
Base.BinaryPlatforms.CPUID.ISA(Set(UInt32[0x00000002, 0x00000067, 0x00000073, 0x00000077, 0x0000005b, 0x0000002a, 0x000000a1, 0x0000003f, 0x00000057, 0x000000d1 … 0x0000009e, 0x0000000f, 0x000000e7, 0x000000e1, 0x00000047, 0x00000081, 0x000000e8, 0x000000da, 0x00000033, 0x00000009]))
julia> Base.BinaryPlatforms.CPUID._lookup_cpu("apple-m2")
Base.BinaryPlatforms.CPUID.ISA(Set{UInt32}()) |
|
My m2 is now properly detected and displayed on macOS and Linux! |
|
Should the Also, when I opened gbaraldi/cpufeatures#1, I had forgotten that the Also also, should |
|
That specific feature we manually filter because llvm doesn’t support it. I guess we can have some fallback logic. I’ll ask the robot if he has any implementation better than what we used to have, if not then we add that again. |
69c9134 to
a022ca0
Compare
4874b0d to
ce21259
Compare
|
With #61399 landed, this PR should be able to remove our last usage of |
ce21259 to
230d4f4
Compare
Replace the hand-maintained processor_x86.cpp, processor_arm.cpp, and processor_fallback.cpp with a single processor.cpp that uses the cpufeatures library for CPU detection, feature resolution, sysimage serialization, and target matching. cpufeatures extracts CPU tables from LLVM's TableGen at build time, so they stay in sync with the LLVM version Julia ships. This removes ~3600 lines of manually maintained feature lists and CPU definitions. Key changes: - src/processor.cpp: single file replacing three arch-specific backends - deps/cpufeatures.mk: new dependency (static library, no runtime dep) - base/cpuid.jl: cross-arch ISA queries via cpufeatures - base/loading.jl: updated ImageTarget for new serialization format - src/init.c: CPU target validation (unknown names, multi-target checks) - Removed LLVMTargetParser from libjulia-internal link Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove JL_TARGET_CLONE_* from processor.h — these flags were an intermediate bitfield mapping between cpufeatures' FeatureDiff and the per-function clone categories in multiversioning. Now: - jl_target_spec_t carries explicit bools (clone_all, opt_size, min_size) and a tp::FeatureDiff directly - JL_CLONE_* enum is file-local to llvm-multiversioning.cpp (only consumer) - TargetSpec::clone_flags() derives the per-function mask from FeatureDiff - Metadata serialization packs/unpacks the bools into a uint32_t Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update metadata flag values in the three multiversioning .ll tests to match the new packed_flags() format (clone_all=1<<0, opt_size=1<<1, has_new_math=1<<3, has_new_simd=1<<4, etc). Since clone_flags() now always includes LOOP and CPU categories, loop-containing functions get cloned for more targets. Consolidate CHECK lines in annotate-only test where multiple functions now share the same clone mask. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@giordano @christiangnrd @vchuravy @topolarity Could you folks give the PR a once over as well. I think it's in a quite good state. If possible as well to https://github.com/gbaraldi/cpufeatures. I would like to finally get this monkey of my back. Specially since #41924 was my first PR ever merged to Julia. So I guess it's fate |
|
What happens if a CPU that's in the cpufeatures generated table isn't in the LLVM version that Julia was built with? The current cpufeatures fallback only checks if the cpu is in the tables, not the runtime llvm. If the answer is "bad things", I need to remove the A18 detection that I prematurely added until llvm 21, and also would this prevent newer processors from running julia built with older llvm? Edit: I opened gbaraldi/cpufeatures#4. |
|
So we currently assume and check that you have the same LLVM version. So we do have to make sure that in cpufeatures we gate things on the LLVM version. #if defined(TARGET_TABLES_LLVM_VERSION_MAJOR) && defined(LLVM_VERSION_MAJOR)
static_assert(TARGET_TABLES_LLVM_VERSION_MAJOR == LLVM_VERSION_MAJOR,
"cpufeatures tables were generated with a different LLVM major version than Julia uses");
#endif |
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
To what level is building current julia on an older LLVM version supposed to be supported? Would the build process automatically select the cpufeatures branch based on the llvm version? |
|
It's kinda supported (but not really) and you would have to choose a specific commit and I think that's fine |
That sounds reasonable to me. Would it be worth adding a quick comment to the devdocs? I also just tried generating the tables over in cpufeatures down to llvm 17 since that's the lowest currently "supported". v19 worked (tests fail however), but generating the tables failed on llvm 17 and 18 |
|
Is this expected? Feels a bit verbose. |
|
The |
|
I though ssbs became default on armv8.5 though I’ll check |
|
It is very verbose because it prints once per package image. Though I'm not sure if there's another behavior. It's similar to JULIA_DEBUG=loading in that matter |
Picks up gbaraldi/cpufeatures#5 which blacklists FEAT_SSBS from hw_feature_mask. SSBS is a speculative execution mitigation that doesn't affect codegen but was inconsistently present across LLVM CPU definitions (apple-a16 has it, apple-m4 doesn't), causing false target mismatches on Apple Silicon. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
processor_x86.cpp,processor_arm.cpp,processor_fallback.cpp(~5000 lines of hand-maintained CPU/feature tables) with a unifiedprocessor_cpufeatures.cppthat uses the cpufeatures librarycpuid.jlnow queries feature sets from the C library instead of hardcoding themJULIA_DEBUG=cpufeaturesWhat is cpufeatures?
A standalone library that extracts CPU names, feature sets, and feature dependencies from LLVM's
MCSubtargetInfoat build time into generated C headers. The generated headers are committed to the repo, so a normal build only needs a C++17 compiler — no LLVM required. Supports x86_64, aarch64, and riscv64.Changes
New files:
deps/cpufeatures.mk,deps/cpufeatures.version— build system integrationsrc/processor_cpufeatures.cpp— unified processor implementationModified files:
src/processor.cpp— includes new file instead of arch-specific onessrc/processor.h— feature enum →uint32_ttypedef (indices from cpufeatures)src/Makefile— updated dependencies, link-ltarget_parsingsrc/crc32c.c— hardcode HWCAP bit instead of using removed enumbase/cpuid.jl— ISA sets from C queries, not hardcodedbase/Makefile—features_h.jlfrom cpufeatures headersdeps/Makefile— add cpufeatures toDEP_LIBSFiles to delete (follow-up):
src/processor_x86.cpp,src/processor_arm.cpp,src/processor_fallback.cppsrc/features_x86.h,src/features_aarch32.h,src/features_aarch64.hTest plan
make clean && make -jsucceeds (downloads, builds, links cpufeatures)generic;haswell;skylake-avx512): correct target selection-C haswellselects haswell target,-C genericselects genericBinaryPlatformsISA matching worksJULIA_DEBUG=cpufeaturesshows target selection detailsRelated
🤖 Generated with Claude Code