Author: Jack Styles Date: 2025-04-15T09:00:14+01:00 New Revision: 06da00ae2d116bb2c4063b124429c2d29eb69d87
URL: https://github.com/llvm/llvm-project/commit/06da00ae2d116bb2c4063b124429c2d29eb69d87 DIFF: https://github.com/llvm/llvm-project/commit/06da00ae2d116bb2c4063b124429c2d29eb69d87.diff LOG: [ARM][Clang] Make `+nosimd` functional for AArch32 Targets (#130623) `+simd` and `+nosimd` are used to enable or disable NEON Instructions when compiling for ARM Targets. However, up until now, using these has not been possible. To enable this, these options are mapped to the relevant LLVM backend option (`+neon` and `-neon`) so it can be both enabled and disabled successfully by the user. Tests have been added to ensure this behaviour is maintained in the future, along with updates to existing tests as behaviour has now changed relating to the use of `+simd` and `+nosimd`. As `simd` has been mapped within the ARMTargetParser.def, support for this extension is also added for the `--print-support-extensions` command when the target is AArch32. This will print the `simd` option, along with the description that relates to the Neon feature. This previously was not possible as `simd` did not have a related Feature or Negative Feature. To make this functional as intended, MVE and MVE.FP now rely on their own Enum identifier, rather than `AEK_SIMD`. While SIMD does refer to both Neon and Helium technologies, in terms of command line options, SIMD relates to Neon. Helium relates to MVE and MVE.FP. The Enum now reflects this too. Added: Modified: clang/docs/ReleaseNotes.rst clang/test/CodeGen/arm-target-features.c clang/test/Driver/print-supported-extensions-arm.c clang/test/Preprocessor/arm-target-features.c llvm/include/llvm/TargetParser/ARMTargetParser.def llvm/include/llvm/TargetParser/ARMTargetParser.h llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp llvm/lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp llvm/lib/TargetParser/ARMTargetParser.cpp llvm/unittests/TargetParser/TargetParserTest.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index f7f198f15a4e0..ccd9f70aa875d 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -525,6 +525,9 @@ X86 Support Arm and AArch64 Support ^^^^^^^^^^^^^^^^^^^^^^^ - For ARM targets, cc1as now considers the FPU's features for the selected CPU or Architecture. +- 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. Android Support ^^^^^^^^^^^^^^^ diff --git a/clang/test/CodeGen/arm-target-features.c b/clang/test/CodeGen/arm-target-features.c index ad4bfd45c408b..95ae27bd2db6c 100644 --- a/clang/test/CodeGen/arm-target-features.c +++ b/clang/test/CodeGen/arm-target-features.c @@ -119,4 +119,10 @@ // RUN: %clang_cc1 -triple thumbv9.3a-linux-gnueabihf -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ARCH93 // CHECK-ARCH93: "target-features"="+armv9.3-a,+thumb-mode,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8.7a,+v8.8a,+v9.1a,+v9.2a,+v9.3a,+v9a" +// RUN: %clang_cc1 -triple arm-none-eabi -target-cpu cortex-r52 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ARMSIMD-R52 +// CHECK-ARMSIMD-R52: "target-features"="+armv8-r,+crc,+d32,+dsp,+fp-armv8,+fp-armv8d16,+fp-armv8d16sp,+fp-armv8sp,+fp16,+fp64,+hwdiv,+hwdiv-arm,+neon,+vfp2,+vfp2sp,+vfp3,+vfp3d16,+vfp3d16sp,+vfp3sp,+vfp4,+vfp4d16,+vfp4d16sp,+vfp4sp,-thumb-mode" + +// RUN: %clang_cc1 -triple armv8-none-eabi -target-cpu cortex-a57 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ARMSIMD-A57 +// CHECK-ARMSIMD-A57: "target-features"="+aes,+armv8-a,+crc,+d32,+dsp,+fp-armv8,+fp-armv8d16,+fp-armv8d16sp,+fp-armv8sp,+fp16,+fp64,+hwdiv,+hwdiv-arm,+neon,+sha2,+vfp2,+vfp2sp,+vfp3,+vfp3d16,+vfp3d16sp,+vfp3sp,+vfp4,+vfp4d16,+vfp4d16sp,+vfp4sp,-thumb-mode" + void foo() {} diff --git a/clang/test/Driver/print-supported-extensions-arm.c b/clang/test/Driver/print-supported-extensions-arm.c index 0dc2e9fc69738..407adc5e9c384 100644 --- a/clang/test/Driver/print-supported-extensions-arm.c +++ b/clang/test/Driver/print-supported-extensions-arm.c @@ -12,6 +12,7 @@ // CHECK-NEXT: dsp Supports DSP instructions in ARM and/or Thumb2 // CHECK-NEXT: mve Support M-Class Vector Extension with integer ops // CHECK-NEXT: mve.fp Support M-Class Vector Extension with integer and floating ops +// CHECK-NEXT: simd Enable NEON instructions // CHECK-NEXT: fp16 Enable half-precision floating point // CHECK-NEXT: ras Enable Reliability, Availability and Serviceability extensions // CHECK-NEXT: fp16fml Enable full half-precision floating point fml instructions diff --git a/clang/test/Preprocessor/arm-target-features.c b/clang/test/Preprocessor/arm-target-features.c index 94dcfc2424bb1..7b2a0ecdf9040 100644 --- a/clang/test/Preprocessor/arm-target-features.c +++ b/clang/test/Preprocessor/arm-target-features.c @@ -1027,3 +1027,19 @@ // CHECK-R52-NEXT: #define __ARM_VFPV4__ 1 // CHECK-R52-NOT: #define __ARM_NEON 1 // CHECK-R52-NOT: #define __ARM_NEON__ + +// Check that on AArch32, Neon is correctly activated when the target supports the feature +// RUN: %clang -target arm-none-eabi -march=armv8-a -mfloat-abi=hard -x c -E -dM -o - %s | FileCheck -check-prefix=CHECK-SIMD %s +// RUN: %clang -target arm-none-eabi -mcpu=cortex-r52 -mfloat-abi=hard -x c -E -dM -o - %s | FileCheck -check-prefix=CHECK-SIMD %s +// RUN: %clang -target arm-none-eabi -mcpu=cortex-a57 -mfloat-abi=hard -x c -E -dM -o - %s | FileCheck -check-prefix=CHECK-SIMD %s +// CHECK-SIMD: #define __ARM_NEON 1 +// 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 +// 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_NEON 1 +// CHECK-NOSIMD-NOT: #define __ARM_NEON_FP 0x6 +// CHECK-NOSIMD-NOT: #define __ARM_NEON__ 1 diff --git a/llvm/include/llvm/TargetParser/ARMTargetParser.def b/llvm/include/llvm/TargetParser/ARMTargetParser.def index 6b96c3e83c8c4..ff53aa10b4481 100644 --- a/llvm/include/llvm/TargetParser/ARMTargetParser.def +++ b/llvm/include/llvm/TargetParser/ARMTargetParser.def @@ -224,12 +224,12 @@ ARM_ARCH_EXT_NAME("dotprod", ARM::AEK_DOTPROD, "+dotprod", "-dotprod") ARM_ARCH_EXT_NAME("dsp", ARM::AEK_DSP, "+dsp", "-dsp") ARM_ARCH_EXT_NAME("fp", ARM::AEK_FP, {}, {}) ARM_ARCH_EXT_NAME("fp.dp", ARM::AEK_FP_DP, {}, {}) -ARM_ARCH_EXT_NAME("mve", (ARM::AEK_DSP | ARM::AEK_SIMD), "+mve", "-mve") -ARM_ARCH_EXT_NAME("mve.fp", (ARM::AEK_DSP | ARM::AEK_SIMD | ARM::AEK_FP), +ARM_ARCH_EXT_NAME("mve", (ARM::AEK_DSP | ARM::AEK_MVE), "+mve", "-mve") +ARM_ARCH_EXT_NAME("mve.fp", (ARM::AEK_DSP | ARM::AEK_MVE | ARM::AEK_FP), "+mve.fp", "-mve.fp") ARM_ARCH_EXT_NAME("idiv", (ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB), {}, {}) ARM_ARCH_EXT_NAME("mp", ARM::AEK_MP, {}, {}) -ARM_ARCH_EXT_NAME("simd", ARM::AEK_SIMD, {}, {}) +ARM_ARCH_EXT_NAME("simd", ARM::AEK_SIMD, "+neon", "-neon") ARM_ARCH_EXT_NAME("sec", ARM::AEK_SEC, {}, {}) ARM_ARCH_EXT_NAME("virt", ARM::AEK_VIRT, {}, {}) ARM_ARCH_EXT_NAME("fp16", ARM::AEK_FP16, "+fullfp16", "-fullfp16") @@ -345,12 +345,12 @@ ARM_CPU_NAME("cortex-m33", ARMV8MMainline, FK_FPV5_SP_D16, false, ARM::AEK_DSP) ARM_CPU_NAME("star-mc1", ARMV8MMainline, FK_FPV5_SP_D16, false, ARM::AEK_DSP) ARM_CPU_NAME("cortex-m35p", ARMV8MMainline, FK_FPV5_SP_D16, false, ARM::AEK_DSP) ARM_CPU_NAME("cortex-m55", ARMV8_1MMainline, FK_FP_ARMV8_FULLFP16_D16, false, - (ARM::AEK_DSP | ARM::AEK_SIMD | ARM::AEK_FP | ARM::AEK_FP16)) + (ARM::AEK_DSP | ARM::AEK_MVE | ARM::AEK_FP | ARM::AEK_FP16)) ARM_CPU_NAME("cortex-m85", ARMV8_1MMainline, FK_FP_ARMV8_FULLFP16_D16, false, - (ARM::AEK_DSP | ARM::AEK_SIMD | ARM::AEK_FP | ARM::AEK_FP16 | + (ARM::AEK_DSP | ARM::AEK_MVE | ARM::AEK_FP | ARM::AEK_FP16 | ARM::AEK_RAS | ARM::AEK_PACBTI)) ARM_CPU_NAME("cortex-m52", ARMV8_1MMainline, FK_FP_ARMV8_FULLFP16_D16, false, - (ARM::AEK_DSP | ARM::AEK_SIMD | ARM::AEK_FP | ARM::AEK_FP16 | + (ARM::AEK_DSP | ARM::AEK_MVE | ARM::AEK_FP | ARM::AEK_FP16 | ARM::AEK_RAS | ARM::AEK_PACBTI)) ARM_CPU_NAME("cortex-a32", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) ARM_CPU_NAME("cortex-a35", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) diff --git a/llvm/include/llvm/TargetParser/ARMTargetParser.h b/llvm/include/llvm/TargetParser/ARMTargetParser.h index 5dbcfd3d2d693..b2403f42f1b79 100644 --- a/llvm/include/llvm/TargetParser/ARMTargetParser.h +++ b/llvm/include/llvm/TargetParser/ARMTargetParser.h @@ -61,6 +61,7 @@ enum ArchExtKind : uint64_t { AEK_CDECP6 = 1 << 28, AEK_CDECP7 = 1 << 29, AEK_PACBTI = 1 << 30, + AEK_MVE = 1ULL << 31, // Unsupported extensions. AEK_OS = 1ULL << 59, AEK_IWMMXT = 1ULL << 60, diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 456c3b5396fc9..956fc9680ee33 100644 --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -12970,7 +12970,7 @@ bool ARMAsmParser::enableArchExtFeature(StringRef Name, SMLoc &ExtLoc) { {ARM::AEK_CRYPTO, {Feature_HasV8Bit}, {ARM::FeatureCrypto, ARM::FeatureNEON, ARM::FeatureFPARMv8}}, - {(ARM::AEK_DSP | ARM::AEK_SIMD | ARM::AEK_FP), + {(ARM::AEK_DSP | ARM::AEK_MVE | ARM::AEK_FP), {Feature_HasV8_1MMainlineBit}, {ARM::HasMVEFloatOps}}, {ARM::AEK_FP, diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp index b0fa03a35ec04..632dbebf58f04 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp @@ -248,7 +248,7 @@ void ARMTargetStreamer::emitTargetAttributes(const MCSubtargetInfo &STI) { emitFPU(STI.hasFeature(ARM::FeatureFP64) ? ARM::FK_FPV5_D16 : ARM::FK_FPV5_SP_D16); if (STI.hasFeature(ARM::HasMVEFloatOps)) - emitArchExtension(ARM::AEK_SIMD | ARM::AEK_DSP | ARM::AEK_FP); + emitArchExtension(ARM::AEK_MVE | ARM::AEK_DSP | ARM::AEK_FP); } } else if (STI.hasFeature(ARM::FeatureVFP4_D16_SP)) emitFPU(STI.hasFeature(ARM::FeatureD32) diff --git a/llvm/lib/TargetParser/ARMTargetParser.cpp b/llvm/lib/TargetParser/ARMTargetParser.cpp index 8f9753775c204..a7a895d872668 100644 --- a/llvm/lib/TargetParser/ARMTargetParser.cpp +++ b/llvm/lib/TargetParser/ARMTargetParser.cpp @@ -657,6 +657,10 @@ void ARM::PrintSupportedExtensions(StringMap<StringRef> DescMap) { // Extensions without a feature cannot be used with -march. if (!Ext.Feature.empty()) { std::string Description = DescMap[Ext.Name].str(); + // With SIMD, this links to the NEON feature, so the description should be + // taken from here, as SIMD does not exist in TableGen. + if (Ext.Name == "simd") + Description = DescMap["neon"].str(); outs() << " " << format(Description.empty() ? "%s\n" : "%-20s%s\n", Ext.Name.str().c_str(), Description.c_str()); diff --git a/llvm/unittests/TargetParser/TargetParserTest.cpp b/llvm/unittests/TargetParser/TargetParserTest.cpp index dcffc9471705f..b3c470b774de7 100644 --- a/llvm/unittests/TargetParser/TargetParserTest.cpp +++ b/llvm/unittests/TargetParser/TargetParserTest.cpp @@ -507,17 +507,17 @@ INSTANTIATE_TEST_SUITE_P( "8-M.Mainline"), ARMCPUTestParams<uint64_t>( "cortex-m55", "armv8.1-m.main", "fp-armv8-fullfp16-d16", - ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_SIMD | ARM::AEK_FP | + ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_MVE | ARM::AEK_FP | ARM::AEK_RAS | ARM::AEK_LOB | ARM::AEK_FP16, "8.1-M.Mainline"), ARMCPUTestParams<uint64_t>( "cortex-m85", "armv8.1-m.main", "fp-armv8-fullfp16-d16", - ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_SIMD | ARM::AEK_FP | + ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_MVE | ARM::AEK_FP | ARM::AEK_RAS | ARM::AEK_LOB | ARM::AEK_FP16 | ARM::AEK_PACBTI, "8.1-M.Mainline"), ARMCPUTestParams<uint64_t>( "cortex-m52", "armv8.1-m.main", "fp-armv8-fullfp16-d16", - ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_SIMD | ARM::AEK_FP | + ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_MVE | ARM::AEK_FP | ARM::AEK_RAS | ARM::AEK_LOB | ARM::AEK_FP16 | ARM::AEK_PACBTI, "8.1-M.Mainline"), ARMCPUTestParams<uint64_t>("iwmmxt", "iwmmxt", "none", ARM::AEK_NONE, @@ -801,7 +801,7 @@ TEST(TargetParserTest, ARMArchExtFeature) { {"fp", "nofp", nullptr, nullptr}, {"idiv", "noidiv", nullptr, nullptr}, {"mp", "nomp", nullptr, nullptr}, - {"simd", "nosimd", nullptr, nullptr}, + {"simd", "nosimd", "+neon", "-neon"}, {"sec", "nosec", nullptr, nullptr}, {"virt", "novirt", nullptr, nullptr}, {"fp16", "nofp16", "+fullfp16", "-fullfp16"}, @@ -1046,7 +1046,6 @@ TEST(TargetParserTest, ARMPrintSupportedExtensions) { EXPECT_EQ(std::string::npos, captured.find("invalid")); // Should not include anything that lacks a feature name. Checking a few here // but not all as if one is hidden correctly the rest should be. - EXPECT_EQ(std::string::npos, captured.find("simd")); EXPECT_EQ(std::string::npos, captured.find("maverick")); EXPECT_EQ(std::string::npos, captured.find("xscale")); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits