[llvm-branch-commits] [clang] [llvm] release/22.x: [AArch64][Driver] Allow runtime detection to override default features. (#176340) (PR #177171)
Ricardo Jesus via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Jan 21 06:01:03 PST 2026
https://github.com/rj-jesus created https://github.com/llvm/llvm-project/pull/177171
Backport https://github.com/llvm/llvm-project/pull/176340.
The initial cherry-pick failed due to the test change common with https://github.com/llvm/llvm-project/pull/166387.
If this is unsuitable to backport, please let me know.
>From 8ca4e48116797cba5e987c302cfa30661883b880 Mon Sep 17 00:00:00 2001
From: Ricardo Jesus <rjj at nvidia.com>
Date: Thu, 15 Jan 2026 06:31:26 -0800
Subject: [PATCH 1/2] [AArch64][Driver] Allow runtime detection to override
default feaures.
Currently, most extensions controlled through -march and -mcpu options
are handled in a bitset of AArch64::ExtensionSet. However, extensions
detected at runtime for native compilation are handled in a separate
list of CPU features; once most of the parsing logic has run, the bitset
is converted to a list of features, added after the features detected at
runtime, and the resulting list is used from there on.
This has the downside that runtime-detected features are unable to
override default CPU extensions. For example, if a CPU enables +aes in
its processor definition, but aes is not found at runtime, the feature
currently remains enabled---even though unsupported---because default
features are enabled after the runtime logic attempts to disable them.
This patch inserts runtime-detected features directly into the extension
set such that these options can take precedence over extensions enabled
by default. The general parsing order for mcpu=native becomes:
1. CPU defaults;
2. Runtime detection;
3. Further +featureA+nofeatureB options;
4. Other parsing decisions.
This allows features that are found to be unsupported at runtime to be
removed from the list of features supported by targets that enable them
by default.
---
clang/lib/Driver/ToolChains/Arch/AArch64.cpp | 80 +++++++++++---------
clang/test/Driver/aarch64-mcpu-native.c | 2 -
2 files changed, 43 insertions(+), 39 deletions(-)
diff --git a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
index 087ae9201a1a0..cc6e408f45e07 100644
--- a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
@@ -106,14 +106,33 @@ static bool DecodeAArch64Features(const Driver &D, StringRef text,
return true;
}
+static bool DecodeAArch64HostFeatures(llvm::AArch64::ExtensionSet &Extensions) {
+ llvm::StringMap<bool> HostFeatures = llvm::sys::getHostCPUFeatures();
+
+ for (auto &[Feature, Enabled] : HostFeatures) {
+ std::string F = ("+" + Feature).str();
+ if (auto AE = llvm::AArch64::targetFeatureToExtension(F)) {
+ if (Enabled)
+ Extensions.enable(AE->ID);
+ else
+ Extensions.disable(AE->ID);
+ continue;
+ }
+ return false;
+ }
+
+ return true;
+}
+
// Check if the CPU name and feature modifiers in -mcpu are legal. If yes,
// decode CPU and feature.
-static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,
+static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu,
llvm::AArch64::ExtensionSet &Extensions) {
std::pair<StringRef, StringRef> Split = Mcpu.split("+");
- CPU = Split.first;
+ StringRef CPU = Split.first;
+ const bool IsNative = CPU == "native";
- if (CPU == "native")
+ if (IsNative)
CPU = llvm::sys::getHostCPUName();
const std::optional<llvm::AArch64::CpuInfo> CpuInfo =
@@ -123,6 +142,9 @@ static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,
Extensions.addCPUDefaults(*CpuInfo);
+ if (IsNative && !DecodeAArch64HostFeatures(Extensions))
+ return false;
+
if (Split.second.size() &&
!DecodeAArch64Features(D, Split.second, Extensions))
return false;
@@ -153,40 +175,26 @@ getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March,
return true;
}
-static bool getAArch64ArchFeaturesFromMcpu(
- const Driver &D, StringRef Mcpu, const ArgList &Args,
- llvm::AArch64::ExtensionSet &Extensions, std::vector<StringRef> &Features) {
- StringRef CPU;
+static bool
+getAArch64ArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
+ const ArgList &Args,
+ llvm::AArch64::ExtensionSet &Extensions) {
std::string McpuLowerCase = Mcpu.lower();
- if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, Extensions))
- return false;
-
- if (Mcpu == "native") {
- llvm::StringMap<bool> HostFeatures = llvm::sys::getHostCPUFeatures();
- for (auto &[Feature, Enabled] : HostFeatures) {
- Features.push_back(Args.MakeArgString((Enabled ? "+" : "-") + Feature));
- }
- }
-
- return true;
+ return DecodeAArch64Mcpu(D, McpuLowerCase, Extensions);
}
-static bool
-getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune,
- const ArgList &Args,
- std::vector<StringRef> &Features) {
+static bool getAArch64MicroArchFeaturesFromMtune(const Driver &D,
+ StringRef Mtune,
+ const ArgList &Args) {
// Check CPU name is valid, but ignore any extensions on it.
std::string MtuneLowerCase = Mtune.lower();
llvm::AArch64::ExtensionSet Extensions;
- StringRef Tune;
- return DecodeAArch64Mcpu(D, MtuneLowerCase, Tune, Extensions);
+ return DecodeAArch64Mcpu(D, MtuneLowerCase, Extensions);
}
-static bool
-getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
- const ArgList &Args,
- std::vector<StringRef> &Features) {
- return getAArch64MicroArchFeaturesFromMtune(D, Mcpu, Args, Features);
+static bool getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
+ const ArgList &Args) {
+ return getAArch64MicroArchFeaturesFromMtune(D, Mcpu, Args);
}
void aarch64::getAArch64TargetFeatures(const Driver &D,
@@ -213,24 +221,22 @@ void aarch64::getAArch64TargetFeatures(const Driver &D,
success =
getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Extensions);
else if ((A = Args.getLastArg(options::OPT_mcpu_EQ)))
- success = getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Extensions,
- Features);
+ success =
+ getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Extensions);
else if (isCPUDeterminedByTriple(Triple))
success = getAArch64ArchFeaturesFromMcpu(
- D, getAArch64TargetCPU(Args, Triple, A), Args, Extensions, Features);
+ D, getAArch64TargetCPU(Args, Triple, A), Args, Extensions);
else
// Default to 'A' profile if the architecture is not specified.
success = getAArch64ArchFeaturesFromMarch(D, "armv8-a", Args, Extensions);
if (success && (A = Args.getLastArg(options::OPT_mtune_EQ)))
- success =
- getAArch64MicroArchFeaturesFromMtune(D, A->getValue(), Args, Features);
+ success = getAArch64MicroArchFeaturesFromMtune(D, A->getValue(), Args);
else if (success && (A = Args.getLastArg(options::OPT_mcpu_EQ)))
- success =
- getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
+ success = getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args);
else if (success && isCPUDeterminedByTriple(Triple))
success = getAArch64MicroArchFeaturesFromMcpu(
- D, getAArch64TargetCPU(Args, Triple, A), Args, Features);
+ D, getAArch64TargetCPU(Args, Triple, A), Args);
if (!success) {
auto Diag = D.Diag(diag::err_drv_unsupported_option_argument);
diff --git a/clang/test/Driver/aarch64-mcpu-native.c b/clang/test/Driver/aarch64-mcpu-native.c
index db410bf1e000d..e132081062851 100644
--- a/clang/test/Driver/aarch64-mcpu-native.c
+++ b/clang/test/Driver/aarch64-mcpu-native.c
@@ -33,12 +33,10 @@
// CHECK-FEAT-CA57: Extensions enabled for the given AArch64 target
// CHECK-FEAT-CA57-EMPTY:
// CHECK-FEAT-CA57: Architecture Feature(s) Description
-// CHECK-FEAT-CA57: FEAT_AES, FEAT_PMULL Enable AES support
// CHECK-FEAT-CA57: FEAT_AdvSIMD Enable Advanced SIMD instructions
// CHECK-FEAT-CA57: FEAT_CRC32 Enable Armv8.0-A CRC-32 checksum instructions
// CHECK-FEAT-CA57: FEAT_FP Enable Armv8.0-A Floating Point Extensions
// CHECK-FEAT-CA57: FEAT_PMUv3 Enable Armv8.0-A PMUv3 Performance Monitors extension
-// CHECK-FEAT-CA57: FEAT_SHA1, FEAT_SHA256 Enable SHA1 and SHA256 support
// RUN: export LLVM_CPUINFO=%S/Inputs/cpunative/cortex-a72
// RUN: %clang --target=aarch64 --print-enabled-extensions -mcpu=native | FileCheck --strict-whitespace --check-prefix=CHECK-FEAT-CA72 --implicit-check-not=FEAT_ %s
>From 959e75c3420c726ed813794452a5370e8379b48a Mon Sep 17 00:00:00 2001
From: Ricardo Jesus <rjj at nvidia.com>
Date: Mon, 19 Jan 2026 03:52:48 -0800
Subject: [PATCH 2/2] Include RNG fix for -mcpu=native.
---
clang/test/Driver/print-enabled-extensions/aarch64-grace.c | 5 +++--
llvm/lib/TargetParser/Host.cpp | 5 +++++
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/clang/test/Driver/print-enabled-extensions/aarch64-grace.c b/clang/test/Driver/print-enabled-extensions/aarch64-grace.c
index b66e649965489..18c428539796e 100644
--- a/clang/test/Driver/print-enabled-extensions/aarch64-grace.c
+++ b/clang/test/Driver/print-enabled-extensions/aarch64-grace.c
@@ -1,5 +1,6 @@
// REQUIRES: aarch64-registered-target,aarch64-host,system-linux
-// RUN: %clang --target=aarch64 --print-enabled-extensions -mcpu=grace | FileCheck --strict-whitespace --implicit-check-not=FEAT_ %s
+// FIXME: mcpu=grace should disable FEAT_RNG.
+// RUN: %clang --target=aarch64 --print-enabled-extensions -mcpu=grace | FileCheck --check-prefixes=CHECK,GRACE --strict-whitespace --implicit-check-not=FEAT_ %s
// RUN: env LLVM_CPUINFO=%S/../Inputs/cpunative/grace %clang --target=aarch64 --print-enabled-extensions -mcpu=native | FileCheck --strict-whitespace --implicit-check-not=FEAT_ %s
// CHECK: Extensions enabled for the given AArch64 target
@@ -42,7 +43,7 @@
// CHECK-NEXT: FEAT_PMUv3 Enable Armv8.0-A PMUv3 Performance Monitors extension
// CHECK-NEXT: FEAT_RAS, FEAT_RASv1p1 Enable Armv8.0-A Reliability, Availability and Serviceability Extensions
// CHECK-NEXT: FEAT_RDM Enable Armv8.1-A Rounding Double Multiply Add/Subtract instructions
-// CHECK-NEXT: FEAT_RNG Enable Random Number generation instructions
+// GRACE-NEXT: FEAT_RNG Enable Random Number generation instructions
// CHECK-NEXT: FEAT_SB Enable Armv8.5-A Speculation Barrier
// CHECK-NEXT: FEAT_SEL2 Enable Armv8.4-A Secure Exception Level 2 extension
// CHECK-NEXT: FEAT_SHA1, FEAT_SHA256 Enable SHA1 and SHA256 support
diff --git a/llvm/lib/TargetParser/Host.cpp b/llvm/lib/TargetParser/Host.cpp
index f545bbfad22b0..eebad66b2da47 100644
--- a/llvm/lib/TargetParser/Host.cpp
+++ b/llvm/lib/TargetParser/Host.cpp
@@ -2241,6 +2241,7 @@ StringMap<bool> sys::getHostCPUFeatures() {
.Case("fp", "fp-armv8")
.Case("crc32", "crc")
.Case("atomics", "lse")
+ .Case("rng", "rand")
.Case("sha3", "sha3")
.Case("sm4", "sm4")
.Case("sve", "sve")
@@ -2290,6 +2291,10 @@ StringMap<bool> sys::getHostCPUFeatures() {
// detect support at runtime.
if (!Features.contains("sve"))
Features["sve"] = false;
+
+ // Also disable RNG if we can't detect support at runtime.
+ if (!Features.contains("rand"))
+ Features["rand"] = false;
#endif
return Features;
More information about the llvm-branch-commits
mailing list