This is an automated email from the ASF dual-hosted git repository.
tqchen pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm.git
The following commit(s) were added to refs/heads/main by this push:
new 7a41af002b [FIX][LLVM] Use isCPUStringValid for mcpu validation
instead of enumerating processor descriptions (#18884)
7a41af002b is described below
commit 7a41af002bf1f77de7b22a7eb06333fa4ed0ceac
Author: Gabe Guralnick <[email protected]>
AuthorDate: Tue Mar 10 10:39:09 2026 -0500
[FIX][LLVM] Use isCPUStringValid for mcpu validation instead of enumerating
processor descriptions (#18884)
## Summary
Fix false rejection of `apple-m1`, `apple-m2`, and `apple-m3` as LLVM
CPU names when building TVM with LLVM 22+.
## Behavior
After following the [installation from source
instructions](https://tvm.apache.org/docs/install/from_source.html) and
building against LLVM 22, every `import tvm` produces spurious error
messages:
```
Error: Using LLVM 22.1.0 with `-mcpu=apple-m1` is not valid in
`-mtriple=arm64-apple-macos`, using default `-mcpu=generic`
Error: Using LLVM 22.1.0 with `-mcpu=apple-m2` is not valid in
`-mtriple=arm64-apple-macos`, using default `-mcpu=generic`
```
These are triggered by the Metal target tag registrations in
`python/tvm/target/tag_registry/metal.py`, which use `apple-m1` and
`apple-m2` as the host `-mcpu`. The CPUs are silently downgraded to
`generic`.
## Root cause
LLVM 22 reorganized its AArch64 processor table. `apple-m1` through
`apple-m3` are now CPU **aliases** — fully valid and accepted by
`createTargetMachine` and `isCPUStringValid()`, but no longer returned
by `MCSubtargetInfo::getAllProcessorDescriptions()`.
TVM's `LLVMTargetInfo` constructor validates `-mcpu` by enumerating
`getAllProcessorDescriptions()` and checking membership, so it misses
alias-only names.
## Fix
Replace the enumeration-based check with a new `IsValidCPU()` method
that uses `MCSubtargetInfo::isCPUStringValid()`, which correctly handles
both primary names and aliases. This API has been available since at
least LLVM 7, well before TVM's minimum supported version.
## Validation
- Built and tested on macOS (Apple Silicon) with LLVM 22.1.0
- `python -c "import tvm; print(tvm.__file__)"` produces clean output
with no error messages
---------
Co-authored-by: Gabriel Guralnick <[email protected]>
---
src/target/llvm/llvm_instance.cc | 21 ++++++++++++++++++---
src/target/llvm/llvm_instance.h | 7 +++++++
2 files changed, 25 insertions(+), 3 deletions(-)
diff --git a/src/target/llvm/llvm_instance.cc b/src/target/llvm/llvm_instance.cc
index 48fa1de406..90d3b65966 100644
--- a/src/target/llvm/llvm_instance.cc
+++ b/src/target/llvm/llvm_instance.cc
@@ -210,9 +210,7 @@ LLVMTargetInfo::LLVMTargetInfo(LLVMInstance& instance,
// llvm module target
if (Downcast<ffi::String>(target.Get("kind").value()) == "llvm") {
// legalize -mcpu with the target -mtriple
- auto arches = GetAllLLVMTargetArches();
- bool has_arch =
- std::any_of(arches.begin(), arches.end(), [&](const auto& var) {
return var == cpu_; });
+ bool has_arch = IsValidCPU(cpu_);
if (!has_arch) {
// Flag an error, but don't abort. This mimicks the behaviour of 'llc' to
// give the code a chance to run with a less-specific target.
@@ -442,6 +440,23 @@ llvm::TargetMachine*
LLVMTargetInfo::GetOrCreateTargetMachine(bool allow_missing
return target_machine_.get();
}
+bool LLVMTargetInfo::IsValidCPU(const std::string& cpu) const {
+ auto llvm_instance = CreateLLVMTargetInstance(triple_, true);
+ if (!llvm_instance) return false;
+ // Create MCSubtargetInfo directly instead of a full TargetMachine,
+ // since we only need isCPUStringValid which correctly handles CPU aliases
+ // (e.g. apple-m1 in LLVM 22+) that don't appear in
getAllProcessorDescriptions().
+#if TVM_LLVM_VERSION >= 220
+ llvm::Triple triple_obj(triple_);
+ std::unique_ptr<llvm::MCSubtargetInfo> mc_info(
+ llvm_instance->createMCSubtargetInfo(triple_obj, "", ""));
+#else
+ std::unique_ptr<llvm::MCSubtargetInfo> mc_info(
+ llvm_instance->createMCSubtargetInfo(triple_, "", ""));
+#endif
+ return mc_info && mc_info->isCPUStringValid(cpu);
+}
+
std::string LLVMTargetInfo::GetTargetFeatureString() const { //
return Join(",", attrs_);
}
diff --git a/src/target/llvm/llvm_instance.h b/src/target/llvm/llvm_instance.h
index 9fec366712..0cb141de99 100644
--- a/src/target/llvm/llvm_instance.h
+++ b/src/target/llvm/llvm_instance.h
@@ -317,6 +317,13 @@ class LLVMTargetInfo {
*/
const ffi::Array<ffi::String> GetAllLLVMTargetArches() const;
+ /*!
+ * \brief Check if a CPU name is valid for this target triple
+ * \param cpu The CPU name to validate
+ * \return true if the CPU is recognized (including aliases)
+ */
+ bool IsValidCPU(const std::string& cpu) const;
+
/*!
* \brief Get all CPU features from target
* \return Map with all valid cpu features as keys and empty string as
value. The Map