[clang] 3c00351 - [AArch64][Driver] Fix behaviour of +nofeat modifier on -mcpu

via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 11 04:58:56 PDT 2026


Author: yamash-fj
Date: 2026-09-11T12:58:49+01:00
New Revision: 3c003512ef20a066ee864fb20c31496859b75061

URL: https://github.com/llvm/llvm-project/commit/3c003512ef20a066ee864fb20c31496859b75061
DIFF: https://github.com/llvm/llvm-project/commit/3c003512ef20a066ee864fb20c31496859b75061.diff

LOG: [AArch64][Driver] Fix behaviour of +nofeat modifier on -mcpu

Honour explicit +no<feature> modifiers for features implied by a CPU's
base architecture, both in -mcpu and target("cpu=...") attributes.
For example, -mcpu=neoverse-v2+nosb now disables SB instead of silently
ignoring the modifier.

Fixes #192186.

Added: 
    clang/test/Driver/aarch64-mcpu-no-feat.c

Modified: 
    clang/test/CodeGen/AArch64/targetattr.c
    clang/test/Driver/arm-sb.c
    llvm/lib/TargetParser/AArch64TargetParser.cpp

Removed: 
    


################################################################################
diff  --git a/clang/test/CodeGen/AArch64/targetattr.c b/clang/test/CodeGen/AArch64/targetattr.c
index fb4f72411ed0c..30e3824ce422f 100644
--- a/clang/test/CodeGen/AArch64/targetattr.c
+++ b/clang/test/CodeGen/AArch64/targetattr.c
@@ -215,6 +215,38 @@ __attribute__((target("+sme")))
 //
 __arm_locally_streaming void plussmelocallystreaming(void)  {}
 
+__attribute__((target("cpu=neoverse-v2+nosve")))
+// CHECK-LABEL: define {{[^@]+}}@v2nosve
+// CHECK-SAME: () #[[ATTR21:[0-9]+]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    ret void
+//
+void v2nosve() {}
+
+__attribute__((target("cpu=neoverse-v2+norng")))
+// CHECK-LABEL: define {{[^@]+}}@v2norng
+// CHECK-SAME: () #[[ATTR22:[0-9]+]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    ret void
+//
+void v2norng() {}
+
+__attribute__((target("cpu=neoverse-v2+nosb")))
+// CHECK-LABEL: define {{[^@]+}}@v2nosb
+// CHECK-SAME: () #[[ATTR23:[0-9]+]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    ret void
+//
+void v2nosb() {}
+
+__attribute__((target("cpu=neoverse-v2+nosha2")))
+// CHECK-LABEL: define {{[^@]+}}@v2nosha2
+// CHECK-SAME: () #[[ATTR24:[0-9]+]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    ret void
+//
+void v2nosha2() {}
+
 //.
 // CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc,+fp-armv8,+lse,+neon,+ras,+rdm,+v8.1a,+v8.2a,+v8a" }
 // CHECK: attributes #[[ATTR1]] = { noinline nounwind optnone vscale_range(1,16) "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc,+fp-armv8,+fullfp16,+lse,+neon,+ras,+rdm,+sve,+v8.1a,+v8.2a,+v8a" }
@@ -237,6 +269,10 @@ __arm_locally_streaming void plussmelocallystreaming(void)  {}
 // CHECK: attributes #[[ATTR18]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="apple-m4" "target-features"="+aes,+bf16,+bti,+ccidx,+complxnum,+crc,+dit,+dotprod,+flagm,+fp-armv8,+fp16fml,+fpac,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+perfmon,+predres,+ras,+rcpc,+rdm,+sb,+sha2,+sha3,+sme,+sme-f64f64,+sme-i16i64,+sme2,+spe-eef,+ssbs,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8.7a,+v8a,+wfxt" }
 // CHECK: attributes #[[ATTR19]] = { noinline nounwind optnone vscale_range(1,16) "aarch64_pstate_sm_enabled" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+fp-armv8,+fullfp16,+neon,+sme" }
 // CHECK: attributes #[[ATTR20]] = { noinline nounwind optnone vscale_range(1,16) "aarch64_pstate_sm_body" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+fp-armv8,+fullfp16,+neon,+sme" }
+// CHECK: attributes #[[ATTR21]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-v2" "target-features"="+bf16,+bti,+ccidx,+complxnum,+crc,+dit,+dotprod,+ete,+flagm,+fp-armv8,+fp16fml,+fpac,+fullfp16,+i8mm,+jsconv,+lse,+mte,+neon,+pauth,+perfmon,+predres,+rand,+ras,+rcpc,+rdm,+sb,+spe,+ssbs,+trbe,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8a,+v9a,-sve,-sve-bitperm,-sve2" }
+// CHECK: attributes #[[ATTR22]] = { noinline nounwind optnone vscale_range(1,16) "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-v2" "target-features"="+bf16,+bti,+ccidx,+complxnum,+crc,+dit,+dotprod,+ete,+flagm,+fp-armv8,+fp16fml,+fpac,+fullfp16,+i8mm,+jsconv,+lse,+mte,+neon,+pauth,+perfmon,+predres,+ras,+rcpc,+rdm,+sb,+spe,+ssbs,+sve,+sve-bitperm,+sve2,+trbe,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8a,+v9a,-rand" }
+// CHECK: attributes #[[ATTR23]] = { noinline nounwind optnone vscale_range(1,16) "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-v2" "target-features"="+bf16,+bti,+ccidx,+complxnum,+crc,+dit,+dotprod,+ete,+flagm,+fp-armv8,+fp16fml,+fpac,+fullfp16,+i8mm,+jsconv,+lse,+mte,+neon,+pauth,+perfmon,+predres,+rand,+ras,+rcpc,+rdm,+spe,+ssbs,+sve,+sve-bitperm,+sve2,+trbe,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8a,+v9a,-sb" }
+// CHECK: attributes #[[ATTR24]] = { noinline nounwind optnone vscale_range(1,16) "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-v2" "target-features"="+bf16,+bti,+ccidx,+complxnum,+crc,+dit,+dotprod,+ete,+flagm,+fp-armv8,+fp16fml,+fpac,+fullfp16,+i8mm,+jsconv,+lse,+mte,+neon,+pauth,+perfmon,+predres,+rand,+ras,+rcpc,+rdm,+sb,+spe,+ssbs,+sve,+sve-bitperm,+sve2,+trbe,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8a,+v9a" }
 //.
 // CHECK: [[META0:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}
 //.

diff  --git a/clang/test/Driver/aarch64-mcpu-no-feat.c b/clang/test/Driver/aarch64-mcpu-no-feat.c
new file mode 100644
index 0000000000000..8be04400e3b70
--- /dev/null
+++ b/clang/test/Driver/aarch64-mcpu-no-feat.c
@@ -0,0 +1,23 @@
+// Check that explicit -mcpu=<cpu>+no<feature> preserves -<feature> option and removes the feature when the feature is implied by the CPU or its base architecture. 
+// SVE and RandGen are default features of neoverse-v2 (defined in AArch64Processors.td).
+// SVE and SB are default features of armv9 (defined in AArch64Features.td).
+// SHA2 is not part of the default feature set for either Neoverse V2 or Armv9.
+
+// RUN: %clang --target=aarch64-linux-gnu -mcpu=neoverse-v2+nosve %s -### 2>&1 | FileCheck %s --check-prefix=NEOVERSE-V2-NOSVE
+// NEOVERSE-V2-NOSVE: "-target-feature" "-sve"
+// NEOVERSE-V2-NOSVE-NOT: "-target-feature" "+sve"
+// NEOVERSE-V2-NOSVE: "-target-feature" "-sve2"
+// NEOVERSE-V2-NOSVE-NOT: "-target-feature" "+sve"
+// NEOVERSE-V2-NOSVE-NOT: "-target-feature" "+sve2"
+
+// RUN: %clang --target=aarch64-linux-gnu -mcpu=neoverse-v2+norng %s -### 2>&1 | FileCheck %s --check-prefix=NEOVERSE-V2-NORNG
+// NEOVERSE-V2-NORNG: "-target-feature" "-rand"
+// NEOVERSE-V2-NORNG-NOT: "-target-feature" "+rand"
+
+// RUN: %clang --target=aarch64-linux-gnu -mcpu=neoverse-v2+nosb %s -### 2>&1 | FileCheck %s --check-prefix=NEOVERSE-V2-NOSB
+// NEOVERSE-V2-NOSB: "-target-feature" "-sb"
+// NEOVERSE-V2-NOSB-NOT: "-target-feature" "+sb"
+
+// RUN: %clang --target=aarch64-linux-gnu -mcpu=neoverse-v2+nosha2 %s -### 2>&1 | FileCheck %s --check-prefix=NEOVERSE-V2-NOSHA2
+// NEOVERSE-V2-NOSHA2-NOT: "-target-feature" "+sha2"
+// NEOVERSE-V2-NOSHA2-NOT: "-target-feature" "-sha2"

diff  --git a/clang/test/Driver/arm-sb.c b/clang/test/Driver/arm-sb.c
index 9c0f381171cb6..a7987d582e2a6 100644
--- a/clang/test/Driver/arm-sb.c
+++ b/clang/test/Driver/arm-sb.c
@@ -14,3 +14,7 @@
 // RUN: %clang -### -target aarch64-none-elf -march=armv8.5a+nosb %s 2>&1 | FileCheck %s --check-prefix=NOSB
 // ABSENT-NOT: "-target-feature" "+sb"
 // ABSENT-NOT: "-target-feature" "-sb"
+
+// RUN: %clang -### -target aarch64-none-elf -mcpu=neoverse-v2+sb %s 2>&1 | FileCheck %s --check-prefix=REDUNDANT
+// REDUNDANT-NOT: "-target-feature" "+sb"
+// REDUNDANT-NOT: "-target-feature" "-sb"

diff  --git a/llvm/lib/TargetParser/AArch64TargetParser.cpp b/llvm/lib/TargetParser/AArch64TargetParser.cpp
index 5d1880b77fe16..b7ceb0bb403c3 100644
--- a/llvm/lib/TargetParser/AArch64TargetParser.cpp
+++ b/llvm/lib/TargetParser/AArch64TargetParser.cpp
@@ -352,6 +352,15 @@ void AArch64::ExtensionSet::addCPUDefaults(const CpuInfo &CPU) {
   for (const auto &E : Extensions)
     if (CPU.DefaultExtensions.test(E.ID))
       enable(E.ID);
+
+  // Workaround: mark extensions implied by the base architecture as Enabled
+  // so that an explicit "+nofeat" is not silently ignored. We set Enabled
+  // directly instead of calling enable() to keep them out of Touched,
+  // preserving the previous output as much as possible and avoiding a flood
+  // of redundant "+feat" entries.
+  for (const auto &E : Extensions)
+    if (BaseArch->DefaultExts.test(E.ID))
+      Enabled.set(E.ID);
 }
 
 void AArch64::ExtensionSet::addArchDefaults(const ArchInfo &Arch) {


        


More information about the cfe-commits mailing list