diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index 5db313813a76aa..a4b27bb64ab8de 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -736,17 +736,33 @@ bool AArch64TargetInfo::hasFeature(StringRef Feature) const { void AArch64TargetInfo::setFeatureEnabled(llvm::StringMap &Features, StringRef Name, bool Enabled) const { Features[Name] = Enabled; + + // If the feature is an architecture feature (like v8.2a), add all previous + // architecture versions and any dependant target features. llvm::AArch64::ArchKind AK = llvm::AArch64::getSubArchArchKind(Name); - // Add all previous architecture versions. + if (AK == llvm::AArch64::ArchKind::INVALID) + return; // In case of v9.x the v8.x counterparts are added too. if ("9" == getArchVersionString(AK)) for (llvm::AArch64::ArchKind I = llvm::AArch64::convertV9toV8(AK); I != llvm::AArch64::ArchKind::INVALID; --I) Features[llvm::AArch64::getSubArch(I)] = Enabled; - for (llvm::AArch64::ArchKind I = --AK; I != llvm::AArch64::ArchKind::INVALID; - --I) + llvm::AArch64::ArchKind I = AK; + for (--I; I != llvm::AArch64::ArchKind::INVALID; --I) Features[llvm::AArch64::getSubArch(I)] = Enabled; + + // Set any features implied by the architecture + uint64_t Extensions = llvm::AArch64::getDefaultExtensions("generic", AK); + std::vector CPUFeats; + if (llvm::AArch64::getExtensionFeatures(Extensions, CPUFeats)) { + for (auto F : CPUFeats) { + assert(F[0] == '+' && "Expected + in target feature!"); + if (F == "+crypto") + continue; + Features[F.drop_front(1)] = true; + } + } } bool AArch64TargetInfo::handleTargetFeatures(std::vector &Features, diff --git a/clang/test/CodeGen/aarch64-targetattr-arch.c b/clang/test/CodeGen/aarch64-targetattr-arch.c new file mode 100644 index 00000000000000..059036dfcc6fc7 --- /dev/null +++ b/clang/test/CodeGen/aarch64-targetattr-arch.c @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -triple aarch64-eabi -target-feature +v8a -verify -DHAS8 -S %s -o - +// RUN: %clang_cc1 -triple aarch64-eabi -target-feature +v8.1a -verify -DHAS81 -S %s -o - +// RUN: %clang_cc1 -triple aarch64-eabi -target-feature +v9a -verify -DHAS9 -S %s -o - + +#ifdef HAS9 +// expected-no-diagnostics +#endif + +#include +#include + +__attribute__((target("arch=armv8.1-a"))) +int test_crc_attr() +{ + return __crc32cd(1, 1); +} + +__attribute__((target("arch=armv9-a"))) +svint8_t test_svadd_attr(svbool_t pg, svint8_t op1, svint8_t op2) +{ + return svadd_s8_z(pg, op1, op2); +} + +svint8_t test_errors(svbool_t pg, svint8_t op1, svint8_t op2) +{ +#ifdef HAS8 +// expected-error@+2{{always_inline function '__crc32cd' requires target feature 'crc'}} +#endif + __crc32cd(1, 1); +#if defined(HAS8) || defined(HAS81) +// expected-error@+2{{'svadd_s8_z' needs target feature sve}} +#endif + return svadd_s8_z(pg, op1, op2); +} diff --git a/clang/test/CodeGen/aarch64-targetattr.c b/clang/test/CodeGen/aarch64-targetattr.c index 88af5cc5bc8da9..8730ecfbd1343e 100644 --- a/clang/test/CodeGen/aarch64-targetattr.c +++ b/clang/test/CodeGen/aarch64-targetattr.c @@ -89,10 +89,10 @@ void noneon() {} __attribute__((target("no-simd"))) void nosimd() {} -// CHECK: attributes #0 = { {{.*}} "target-features"="+v8.1a,+v8.2a,+v8a" } -// CHECK: attributes #1 = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+neon,+sve,+v8.1a,+v8.2a,+v8a" } -// CHECK: attributes #2 = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+neon,+sve,+sve2,+v8.1a,+v8.2a,+v8a" } -// CHECK: attributes #3 = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+neon,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" } +// CHECK: attributes #0 = { {{.*}} "target-features"="+crc,+fp-armv8,+lse,+neon,+ras,+rdm,+v8.1a,+v8.2a,+v8a" } +// CHECK: attributes #1 = { {{.*}} "target-features"="+crc,+fp-armv8,+fullfp16,+lse,+neon,+ras,+rdm,+sve,+v8.1a,+v8.2a,+v8a" } +// CHECK: attributes #2 = { {{.*}} "target-features"="+crc,+fp-armv8,+fullfp16,+lse,+neon,+ras,+rdm,+sve,+sve2,+v8.1a,+v8.2a,+v8a" } +// CHECK: attributes #3 = { {{.*}} "target-features"="+aes,+bf16,+crc,+dotprod,+fp-armv8,+fullfp16,+i8mm,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" } // CHECK: attributes #4 = { {{.*}} "target-cpu"="cortex-a710" "target-features"="+bf16,+crc,+dotprod,+flagm,+fp-armv8,+fp16fml,+i8mm,+lse,+mte,+neon,+pauth,+ras,+rcpc,+rdm,+sb,+sve,+sve2,+sve2-bitperm" } // CHECK: attributes #5 = { {{.*}} "tune-cpu"="cortex-a710" } // CHECK: attributes #6 = { {{.*}} "target-cpu"="generic" } @@ -104,6 +104,6 @@ void nosimd() {} // CHECK: attributes #12 = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+neon,+sve" } // CHECK: attributes #13 = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+neon,+sve,-sve2" } // CHECK: attributes #14 = { {{.*}} "target-features"="+fullfp16" } -// CHECK: attributes #15 = { {{.*}} "target-cpu"="neoverse-n1" "target-features"="+crc,+crypto,+dotprod,+fp-armv8,+fullfp16,+lse,+neon,+ras,+rcpc,+rdm,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" "tune-cpu"="cortex-a710" } -// CHECK: attributes #16 = { {{.*}} "branch-target-enforcement"="true" {{.*}} "target-cpu"="neoverse-n1" "target-features"="+crc,+crypto,+dotprod,+fp-armv8,+fullfp16,+lse,+neon,+ras,+rcpc,+rdm,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" "tune-cpu"="cortex-a710" } +// CHECK: attributes #15 = { {{.*}} "target-cpu"="neoverse-n1" "target-features"="+aes,+bf16,+crc,+crypto,+dotprod,+fp-armv8,+fullfp16,+i8mm,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" "tune-cpu"="cortex-a710" } +// CHECK: attributes #16 = { {{.*}} "branch-target-enforcement"="true" {{.*}} "target-features"="+aes,+bf16,+crc,+crypto,+dotprod,+fp-armv8,+fullfp16,+i8mm,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" "tune-cpu"="cortex-a710" } // CHECK: attributes #17 = { {{.*}} "target-features"="-neon" } diff --git a/llvm/include/llvm/TargetParser/AArch64TargetParser.def b/llvm/include/llvm/TargetParser/AArch64TargetParser.def index e7fadc98a9c0d7..570172ace990a5 100644 --- a/llvm/include/llvm/TargetParser/AArch64TargetParser.def +++ b/llvm/include/llvm/TargetParser/AArch64TargetParser.def @@ -69,28 +69,31 @@ AARCH64_ARCH("armv9-a", ARMV9A, "+v9a", (AArch64::AEK_CRC | AArch64::AEK_FP | AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE | AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD | - AArch64::AEK_SVE2)) + AArch64::AEK_SVE | AArch64::AEK_SVE2)) AARCH64_ARCH("armv9.1-a", ARMV9_1A, "+v9.1a", (AArch64::AEK_CRC | AArch64::AEK_FP | AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE | AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD | - AArch64::AEK_BF16 | AArch64::AEK_I8MM | AArch64::AEK_SVE2)) + AArch64::AEK_BF16 | AArch64::AEK_I8MM | AArch64::AEK_SVE | + AArch64::AEK_SVE2)) AARCH64_ARCH("armv9.2-a", ARMV9_2A, "+v9.2a", (AArch64::AEK_CRC | AArch64::AEK_FP | AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE | AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD | - AArch64::AEK_BF16 | AArch64::AEK_I8MM | AArch64::AEK_SVE2)) + AArch64::AEK_BF16 | AArch64::AEK_I8MM | AArch64::AEK_SVE | + AArch64::AEK_SVE2)) AARCH64_ARCH("armv9.3-a", ARMV9_3A, "+v9.3a", (AArch64::AEK_CRC | AArch64::AEK_FP | AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE | AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD | - AArch64::AEK_BF16 | AArch64::AEK_I8MM | AArch64::AEK_SVE2)) + AArch64::AEK_BF16 | AArch64::AEK_I8MM | AArch64::AEK_SVE | + AArch64::AEK_SVE2)) AARCH64_ARCH("armv9.4-a", ARMV9_4A, "+v9.4a", (AArch64::AEK_CRC | AArch64::AEK_FP | AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE | AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD | - AArch64::AEK_BF16 | AArch64::AEK_I8MM | AArch64::AEK_SVE2 | - AArch64::AEK_RASv2)) + AArch64::AEK_BF16 | AArch64::AEK_I8MM | AArch64::AEK_SVE | + AArch64::AEK_SVE2 | AArch64::AEK_RASv2)) // For v8-R, we do not enable crypto and align with GCC that enables a more // minimal set of optional architecture extensions. AARCH64_ARCH("armv8-r", ARMV8R, "+v8r",