Author: Jack Styles
Date: 2025-04-29T08:28:10+01:00
New Revision: ace8ceab736f7e265b206b583d218a7554bee864

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

LOG: [ARM][Driver] Ensure NEON is enabled and disabled correctly (#137595)

In #130623 support was added for `+nosimd` in the clang driver.
Following this PR, it was discovered that, if NEON is disabled in the
command line, it did not disable features that depend on this, such as
Crypto or AES. To achieve this, This PR does the following:
- Ensure that disabling NEON (e.g., via +nosimd) also disables dependent
features like Crypto and AES.
- Update the driver to automatically enable NEON when enabling features
that require it (e.g., AES).

This fixes inconsistent behavior where features relying on NEON could be
enabled without NEON itself being active, or where disabling NEON left
dependent features incorrectly enabled.

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/Driver/ToolChains/Arch/ARM.cpp
    clang/test/Driver/arm-features.c
    clang/test/Driver/arm-mfpu.c
    clang/test/Preprocessor/arm-target-features.c

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 3105d8b481560..0fc46fe10b585 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -608,6 +608,8 @@ Arm and AArch64 Support
 - The ``+nosimd`` attribute is now fully supported for ARM. Previously, this 
had no effect when being used with
   ARM targets, however this will now disable NEON instructions being 
generated. The ``simd`` option is
   also now printed when the ``--print-supported-extensions`` option is used.
+- When a feature that depends on NEON (``simd``) is used, NEON is now 
automatically enabled.
+- When NEON is disabled (``+nosimd``), all features that depend on NEON will 
now be disabled.
 
 -  Support for __ptrauth type qualifier has been added.
 

diff  --git a/clang/lib/Driver/ToolChains/Arch/ARM.cpp 
b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
index 5084058b3fef0..b6b1c2e28a96c 100644
--- a/clang/lib/Driver/ToolChains/Arch/ARM.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -781,6 +781,22 @@ llvm::ARM::FPUKind arm::getARMTargetFeatures(const Driver 
&D,
   if (FPUKind == llvm::ARM::FK_FPV5_D16 || FPUKind == 
llvm::ARM::FK_FPV5_SP_D16)
     Features.push_back("-mve.fp");
 
+  // If SIMD has been disabled and the selected FPU supports NEON, then 
features
+  // that rely on NEON instructions should also be disabled.
+  bool HasSimd = false;
+  const auto ItSimd =
+      llvm::find_if(llvm::reverse(Features),
+                    [](const StringRef F) { return F.contains("neon"); });
+  const bool FPUSupportsNeon = (llvm::ARM::FPUNames[FPUKind].NeonSupport ==
+                                llvm::ARM::NeonSupportLevel::Neon) ||
+                               (llvm::ARM::FPUNames[FPUKind].NeonSupport ==
+                                llvm::ARM::NeonSupportLevel::Crypto);
+  if (ItSimd != Features.rend())
+    HasSimd = ItSimd->starts_with("+");
+  if (!HasSimd && FPUSupportsNeon)
+    Features.insert(Features.end(),
+                    {"-sha2", "-aes", "-crypto", "-dotprod", "-bf16", 
"-imm8"});
+
   // For Arch >= ARMv8.0 && A or R profile:  crypto = sha2 + aes
   // Rather than replace within the feature vector, determine whether each
   // algorithm is enabled and append this to the end of the vector.
@@ -791,6 +807,9 @@ llvm::ARM::FPUKind arm::getARMTargetFeatures(const Driver 
&D,
   // FIXME: this needs reimplementation after the TargetParser rewrite
   bool HasSHA2 = false;
   bool HasAES = false;
+  bool HasBF16 = false;
+  bool HasDotprod = false;
+  bool HasI8MM = false;
   const auto ItCrypto =
       llvm::find_if(llvm::reverse(Features), [](const StringRef F) {
         return F.contains("crypto");
@@ -803,12 +822,25 @@ llvm::ARM::FPUKind arm::getARMTargetFeatures(const Driver 
&D,
       llvm::find_if(llvm::reverse(Features), [](const StringRef F) {
         return F.contains("crypto") || F.contains("aes");
       });
-  const bool FoundSHA2 = ItSHA2 != Features.rend();
-  const bool FoundAES = ItAES != Features.rend();
-  if (FoundSHA2)
-    HasSHA2 = ItSHA2->take_front() == "+";
-  if (FoundAES)
-    HasAES = ItAES->take_front() == "+";
+  const auto ItBF16 =
+      llvm::find_if(llvm::reverse(Features),
+                    [](const StringRef F) { return F.contains("bf16"); });
+  const auto ItDotprod =
+      llvm::find_if(llvm::reverse(Features),
+                    [](const StringRef F) { return F.contains("dotprod"); });
+  const auto ItI8MM =
+      llvm::find_if(llvm::reverse(Features),
+                    [](const StringRef F) { return F.contains("i8mm"); });
+  if (ItSHA2 != Features.rend())
+    HasSHA2 = ItSHA2->starts_with("+");
+  if (ItAES != Features.rend())
+    HasAES = ItAES->starts_with("+");
+  if (ItBF16 != Features.rend())
+    HasBF16 = ItBF16->starts_with("+");
+  if (ItDotprod != Features.rend())
+    HasDotprod = ItDotprod->starts_with("+");
+  if (ItI8MM != Features.rend())
+    HasI8MM = ItI8MM->starts_with("+");
   if (ItCrypto != Features.rend()) {
     if (HasSHA2 && HasAES)
       Features.push_back("+crypto");
@@ -823,6 +855,9 @@ llvm::ARM::FPUKind arm::getARMTargetFeatures(const Driver 
&D,
     else
       Features.push_back("-aes");
   }
+  // If any of these features are enabled, NEON should also be enabled.
+  if (HasAES || HasSHA2 || HasBF16 || HasDotprod || HasI8MM)
+    Features.push_back("+neon");
 
   if (HasSHA2 || HasAES) {
     StringRef ArchSuffix = arm::getLLVMArchSuffixForARM(

diff  --git a/clang/test/Driver/arm-features.c 
b/clang/test/Driver/arm-features.c
index eb424f5f61116..830bd54198e99 100644
--- a/clang/test/Driver/arm-features.c
+++ b/clang/test/Driver/arm-features.c
@@ -74,7 +74,7 @@
 // Check +crypto for M and R profiles:
 //
 // RUN: %clang -target arm-arm-none-eabi -march=armv8-r+crypto   -### -c %s 
2>&1 | FileCheck -check-prefix=CHECK-CRYPTO-R %s
-// CHECK-CRYPTO-R: "-cc1"{{.*}} "-target-cpu" "generic"{{.*}} 
"-target-feature" "+sha2" "-target-feature" "+aes"
+// CHECK-CRYPTO-R: "-cc1"{{.*}} "-target-cpu" "generic"{{.*}} 
"-target-feature" "+sha2" "-target-feature" "+aes" "-target-feature" "+neon"
 // RUN: %clang -target arm-arm-none-eabi -march=armv8-m.base+crypto -### -c %s 
2>&1 | FileCheck -check-prefix=CHECK-NOCRYPTO5 %s
 // RUN: %clang -target arm-arm-none-eabi -march=armv8-m.main+crypto -### -c %s 
2>&1 | FileCheck -check-prefix=CHECK-NOCRYPTO5 %s
 // RUN: %clang -target arm-arm-none-eabi -mcpu=cortex-m23+crypto -### -c %s 
2>&1 | FileCheck -check-prefix=CHECK-NOCRYPTO5 %s
@@ -97,3 +97,11 @@
 // CHECK-NOSHA-DAG: "-target-feature" "-sha2"
 // CHECK-NOAES-DAG: "-target-feature" "-aes"
 //
+// Check that adding features that depend on NEON enable the feature
+// RUN: %clang -target arm-none-none-eabi -march=armv8-r+sha2 -### -c %s 2>&1 
| FileCheck -check-prefix=CHECK-NEON-ENABLED-WITH-FEATURE %s
+// RUN: %clang -target arm-none-none-eabi -march=armv8-r+aes -### -c %s 2>&1 | 
FileCheck -check-prefix=CHECK-NEON-ENABLED-WITH-FEATURE %s
+// RUN: %clang -target arm-none-none-eabi -march=armv8-r+crypto -### -c %s 
2>&1 | FileCheck -check-prefix=CHECK-NEON-ENABLED-WITH-FEATURE %s
+// RUN: %clang -target arm-none-none-eabi -march=armv8-r+dotprod -### -c %s 
2>&1 | FileCheck -check-prefix=CHECK-NEON-ENABLED-WITH-FEATURE %s
+// RUN: %clang -target arm-none-none-eabi -march=armv8-r+bf16 -### -c %s 2>&1 
| FileCheck -check-prefix=CHECK-NEON-ENABLED-WITH-FEATURE %s
+// RUN: %clang -target arm-none-none-eabi -march=armv8-r+i8mm -### -c %s 2>&1 
| FileCheck -check-prefix=CHECK-NEON-ENABLED-WITH-FEATURE %s
+// CHECK-NEON-ENABLED-WITH-FEATURE: "-target-feature" "+neon"

diff  --git a/clang/test/Driver/arm-mfpu.c b/clang/test/Driver/arm-mfpu.c
index 640e1b35c84b8..b97cc7bf12545 100644
--- a/clang/test/Driver/arm-mfpu.c
+++ b/clang/test/Driver/arm-mfpu.c
@@ -407,7 +407,7 @@
 // CHECK-ARM8-ANDROID-FP-DEFAULT-DAG: "-target-feature" "+fp-armv8"
 // CHECK-ARM8-ANDROID-FP-DEFAULT-DAG: "-target-feature" "+aes"
 // CHECK-ARM8-ANDROID-FP-DEFAULT-DAG: "-target-feature" "+sha2"
-// CHECK-ARM8-ANDROID-FP-DEFAULT-NOT: "-target-feature" "+neon"
+// CHECK-ARM8-ANDROID-FP-DEFAULT-DAG: "-target-feature" "+neon"
 
 // RUN: %clang -target armv8-linux-android %s -### -c 2>&1 \
 // RUN:   | FileCheck --check-prefix=CHECK-ARM8-ANDROID-DEFAULT %s
@@ -416,7 +416,7 @@
 // CHECK-ARM8-ANDROID-DEFAULT-DAG: "-target-feature" "+fp-armv8"
 // CHECK-ARM8-ANDROID-DEFAULT-DAG: "-target-feature" "+aes"
 // CHECK-ARM8-ANDROID-DEFAULT-DAG: "-target-feature" "+sha2"
-// CHECK-ARM8-ANDROID-DEFAULT-NOT: "-target-feature" "+neon"
+// CHECK-ARM8-ANDROID-DEFAULT-DAG: "-target-feature" "+neon"
 
 // RUN: %clang -target armv7-linux-androideabi21 %s -mfpu=vfp3-d16 -### -c 
2>&1 \
 // RUN:   | FileCheck --check-prefix=CHECK-ARM7-ANDROID-FP-D16 %s

diff  --git a/clang/test/Preprocessor/arm-target-features.c 
b/clang/test/Preprocessor/arm-target-features.c
index 7b2a0ecdf9040..0f9063a27371e 100644
--- a/clang/test/Preprocessor/arm-target-features.c
+++ b/clang/test/Preprocessor/arm-target-features.c
@@ -1036,10 +1036,16 @@
 // CHECK-SIMD: #define __ARM_NEON_FP 0x6
 // CHECK-SIMD: #define __ARM_NEON__ 1
 
-// Check that on AArch32 appropriate targets, +nosimd correctly disables NEON 
instructions.
-// RUN:  %clang -target arm-none-eabi -march=armv8-a+nosimd -mfloat-abi=hard 
-x c -E -dM -o - %s | FileCheck -check-prefix=CHECK-NOSIMD %s
+// Check that on AArch32 appropriate targets, +nosimd correctly disables NEON 
instructions. All features that rely on NEON should also be disabled.
+// RUN:  %clang -target arm-none-eabi -march=armv9.6-a+nosimd -mfloat-abi=hard 
-x c -E -dM -o - %s | FileCheck -check-prefix=CHECK-NOSIMD %s
 // RUN:  %clang -target arm-none-eabi -mcpu=cortex-r52+nosimd -mfloat-abi=hard 
-x c -E -dM -o - %s | FileCheck -check-prefix=CHECK-NOSIMD %s
 // RUN:  %clang -target arm-none-eabi -mcpu=cortex-a57+nosimd -mfloat-abi=hard 
-x c -E -dM -o - %s | FileCheck -check-prefix=CHECK-NOSIMD %s
+// CHECK-NOSIMD-NOT: #define __ARM_FEATURE_BF16 1
+// CHECK-NOSIMD-NOT: #define __ARM_FEATURE_BF16_VECTOR_ARITHMETIC 1
+// CHECK-NOSIMD-NOT: #define __ARM_FEATURE_AES 1
+// CHECK-NOSIMD-NOT: #define __ARM_FEATURE_CRYPTO 1
+// CHECK-NOSIMD-NOT: #define __ARM_FEATURE_DOTPROD 1
+// CHECK-NOSIMD-NOT: #define __ARM_FEATURE_SHA2 1
 // CHECK-NOSIMD-NOT: #define __ARM_NEON 1
 // CHECK-NOSIMD-NOT: #define __ARM_NEON_FP 0x6
 // CHECK-NOSIMD-NOT: #define __ARM_NEON__ 1


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to