Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9945,6 +9945,10 @@ "%select{too many|too few}0 elements in vector initialization (expected %1 elements, have %2)">; def err_altivec_empty_initializer : Error<"expected initializer">; +def err_arm_invalid_dsb : Error< + "DSB argument value %0 is outside valid set {0-15, 16, 20, 24, 28}">; +def err_arm_invalid_dsb_xs : Error< + "DSB argument value %0 requires FEAT_XS support">; def err_invalid_neon_type_code : Error< "incompatible constant for this __builtin_neon function">; def err_argument_invalid_range : Error< Index: clang/lib/Basic/Targets/AArch64.h =================================================================== --- clang/lib/Basic/Targets/AArch64.h +++ clang/lib/Basic/Targets/AArch64.h @@ -55,6 +55,7 @@ bool HasMOPS; bool HasD128; bool HasRCPC; + bool HasXS; const llvm::AArch64::ArchInfo *ArchInfo = &llvm::AArch64::ARMV8A; Index: clang/lib/Basic/Targets/AArch64.cpp =================================================================== --- clang/lib/Basic/Targets/AArch64.cpp +++ clang/lib/Basic/Targets/AArch64.cpp @@ -515,6 +515,7 @@ .Case("neon", FPU & NeonMode) .Cases("sve", "sve2", "sve2-bitperm", "sve2-aes", "sve2-sha3", "sve2-sm4", "f64mm", "f32mm", "i8mm", "bf16", FPU & SveMode) .Case("ls64", HasLS64) + .Case("xs", HasXS) .Default(false); } @@ -563,6 +564,7 @@ HasMOPS = false; HasD128 = false; HasRCPC = false; + HasXS = false; for (const auto &Feature : Features) { if (Feature == "+neon") @@ -612,6 +614,8 @@ HasCRC = true; if (Feature == "+rcpc") HasRCPC = true; + if (Feature == "+xs") + HasXS = true; if (Feature == "+aes") HasAES = true; if (Feature == "+sha2") Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ clang/lib/Sema/SemaChecking.cpp @@ -3271,13 +3271,27 @@ if (CheckSVEBuiltinFunctionCall(BuiltinID, TheCall)) return true; + if (BuiltinID == AArch64::BI__builtin_arm_dsb) { + llvm::APSInt Result; + if (SemaBuiltinConstantArg(TheCall, 0, Result)) + return true; + if (Result >= 0 && Result <= 15) + return false; + else if (Result == 16 || Result == 20 || Result == 24 || Result == 28) + return TI.hasFeature("xs") + ? false + : Diag(TheCall->getBeginLoc(), diag::err_arm_invalid_dsb_xs) + << Result.getSExtValue(); + return Diag(TheCall->getBeginLoc(), diag::err_arm_invalid_dsb) + << Result.getSExtValue(); + } + // For intrinsics which take an immediate value as part of the instruction, // range check them here. unsigned i = 0, l = 0, u = 0; switch (BuiltinID) { default: return false; case AArch64::BI__builtin_arm_dmb: - case AArch64::BI__builtin_arm_dsb: case AArch64::BI__builtin_arm_isb: l = 0; u = 15; break; case AArch64::BI__builtin_arm_tcancel: l = 0; u = 65535; break; } Index: clang/test/Sema/builtins-arm64.c =================================================================== --- clang/test/Sema/builtins-arm64.c +++ clang/test/Sema/builtins-arm64.c @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -triple arm64-apple-ios -fsyntax-only -verify %s // RUN: %clang_cc1 -triple arm64-apple-ios -DTEST1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple arm64-apple-ios -target-feature +xs -DXS -fsyntax-only -verify %s #ifdef TEST1 void __clear_cache(void *start, void *end); @@ -19,10 +20,20 @@ void test_memory_barriers(void) { __builtin_arm_dmb(16); // expected-error-re {{argument value {{.*}} is outside the valid range}} - __builtin_arm_dsb(17); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_arm_dsb(17); // expected-error-re {{DSB argument value {{.*}} is outside valid set}} __builtin_arm_isb(18); // expected-error-re {{argument value {{.*}} is outside the valid range}} + +#ifdef XS + __builtin_arm_dsb(16); + __builtin_arm_dsb(20); + __builtin_arm_dsb(24); + __builtin_arm_dsb(28); +#else + __builtin_arm_dsb(20); // expected-error {{DSB argument value 20 requires FEAT_XS support}} +#endif } + void test_prefetch(void) { __builtin_arm_prefetch(0, 2, 0, 0, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_arm_prefetch(0, 0, 3, 0, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}} Index: llvm/include/llvm/Support/AArch64TargetParser.h =================================================================== --- llvm/include/llvm/Support/AArch64TargetParser.h +++ llvm/include/llvm/Support/AArch64TargetParser.h @@ -82,6 +82,7 @@ AEK_THE = 1ULL << 50, // FEAT_THE AEK_D128 = 1ULL << 51, // FEAT_D128 AEK_LSE128 = 1ULL << 52, // FEAT_LSE128 + AEK_XS = 1ULL << 53, // FEAT_XS }; // Represents an extension that can be enabled with -march=+. Index: llvm/include/llvm/Support/AArch64TargetParser.def =================================================================== --- llvm/include/llvm/Support/AArch64TargetParser.def +++ llvm/include/llvm/Support/AArch64TargetParser.def @@ -47,21 +47,21 @@ AArch64::AEK_SM4 | AArch64::AEK_SHA3 | AArch64::AEK_BF16 | AArch64::AEK_SHA2 | AArch64::AEK_AES | AArch64::AEK_I8MM)) AARCH64_ARCH(8, 7, AProfile, "armv8.7-a", ARMV8_7A, "+v8.7a", - (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_CRC | AArch64::AEK_FP | AArch64::AEK_SIMD | + AArch64::AEK_RAS | AArch64::AEK_LSE | AArch64::AEK_RDM | + AArch64::AEK_RCPC | AArch64::AEK_DOTPROD | AArch64::AEK_XS | AArch64::AEK_SM4 | AArch64::AEK_SHA3 | AArch64::AEK_BF16 | AArch64::AEK_SHA2 | AArch64::AEK_AES | AArch64::AEK_I8MM)) AARCH64_ARCH(8, 8, AProfile, "armv8.8-a", ARMV8_8A, "+v8.8a", - (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_CRC | AArch64::AEK_FP | AArch64::AEK_SIMD | + AArch64::AEK_RAS | AArch64::AEK_LSE | AArch64::AEK_RDM | + AArch64::AEK_RCPC | AArch64::AEK_DOTPROD | AArch64::AEK_XS | AArch64::AEK_SM4 | AArch64::AEK_SHA3 | AArch64::AEK_BF16 | AArch64::AEK_SHA2 | AArch64::AEK_AES | AArch64::AEK_I8MM)) AARCH64_ARCH(8, 9, AProfile, "armv8.9-a", ARMV8_9A, "+v8.9a", - (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_CRC | AArch64::AEK_FP | AArch64::AEK_SIMD | + AArch64::AEK_RAS | AArch64::AEK_LSE | AArch64::AEK_RDM | + AArch64::AEK_RCPC | AArch64::AEK_DOTPROD | AArch64::AEK_XS | AArch64::AEK_SM4 | AArch64::AEK_SHA3 | AArch64::AEK_BF16 | AArch64::AEK_SHA2 | AArch64::AEK_AES | AArch64::AEK_I8MM)) AARCH64_ARCH(9, 0, AProfile, "armv9-a", ARMV9A, "+v9a", @@ -75,19 +75,19 @@ AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD | AArch64::AEK_BF16 | AArch64::AEK_I8MM | AArch64::AEK_SVE2)) AARCH64_ARCH(9, 2, AProfile, "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_CRC | AArch64::AEK_FP | AArch64::AEK_SIMD | + AArch64::AEK_RAS | AArch64::AEK_LSE | AArch64::AEK_RDM | + AArch64::AEK_RCPC | AArch64::AEK_DOTPROD | AArch64::AEK_XS | AArch64::AEK_BF16 | AArch64::AEK_I8MM | AArch64::AEK_SVE2)) AARCH64_ARCH(9, 3, AProfile, "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_CRC | AArch64::AEK_FP | AArch64::AEK_SIMD | + AArch64::AEK_RAS | AArch64::AEK_LSE | AArch64::AEK_RDM | + AArch64::AEK_RCPC | AArch64::AEK_DOTPROD | AArch64::AEK_XS | AArch64::AEK_BF16 | AArch64::AEK_I8MM | AArch64::AEK_SVE2)) AARCH64_ARCH(9, 4, AProfile, "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_CRC | AArch64::AEK_FP | AArch64::AEK_SIMD | + AArch64::AEK_RAS | AArch64::AEK_LSE | AArch64::AEK_RDM | + AArch64::AEK_RCPC | AArch64::AEK_DOTPROD | AArch64::AEK_XS | AArch64::AEK_BF16 | AArch64::AEK_I8MM | AArch64::AEK_SVE2)) // For v8-R, we do not enable crypto and align with GCC that enables a more // minimal set of optional architecture extensions. @@ -155,6 +155,7 @@ AARCH64_ARCH_EXT_NAME("the", AArch64::AEK_THE, "+the", "-the") AARCH64_ARCH_EXT_NAME("d128", AArch64::AEK_D128, "+d128", "-d128") AARCH64_ARCH_EXT_NAME("lse128", AArch64::AEK_LSE128, "+lse128", "-lse128") +AARCH64_ARCH_EXT_NAME("xs", AArch64::AEK_XS, "+xs", "-xs") #undef AARCH64_ARCH_EXT_NAME #ifndef AARCH64_CPU_NAME Index: llvm/lib/Target/AArch64/AArch64InstrFormats.td =================================================================== --- llvm/lib/Target/AArch64/AArch64InstrFormats.td +++ llvm/lib/Target/AArch64/AArch64InstrFormats.td @@ -1021,6 +1021,14 @@ let ParserMatchClass = Imm0_255Operand; } +def DSBnXSXForm : SDNodeXFormgetTargetConstant((N->getZExtValue() & 0xc) | 3, SDLoc(N), MVT::i32); +}]>; + +def imm32_nXS : ImmLeaf; + // An arithmetic shifter operand: // {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr // {5-0} - imm6 Index: llvm/lib/Target/AArch64/AArch64InstrInfo.td =================================================================== --- llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -1000,7 +1000,8 @@ let Predicates = [HasTRACEV8_4]; } -def DSBnXS : CRmSystemI { +def DSBnXS : CRmSystemI { let CRm{1-0} = 0b11; let Inst{9-8} = 0b10; let Predicates = [HasXS]; Index: llvm/test/CodeGen/AArch64/dsb-xs.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/dsb-xs.ll @@ -0,0 +1,17 @@ +; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+xs %s -o - | FileCheck %s + +define void @test_barriers() { +; CHECK-LABEL: test_barriers: + +; CHECK: dsb oshnxs +; CHECK: dsb nshnxs +; CHECK: dsb ishnxs +; CHECK: dsb synxs + + call void @llvm.aarch64.dsb(i32 16) + call void @llvm.aarch64.dsb(i32 20) + call void @llvm.aarch64.dsb(i32 24) + call void @llvm.aarch64.dsb(i32 28) + ret void +} +declare void @llvm.aarch64.dsb(i32) Index: llvm/unittests/Support/TargetParserTest.cpp =================================================================== --- llvm/unittests/Support/TargetParserTest.cpp +++ llvm/unittests/Support/TargetParserTest.cpp @@ -1541,7 +1541,7 @@ AArch64::AEK_PERFMON, AArch64::AEK_SVE2p1, AArch64::AEK_SME2p1, AArch64::AEK_B16B16, AArch64::AEK_SMEF16F16, AArch64::AEK_CSSC, AArch64::AEK_RCPC3, AArch64::AEK_THE, AArch64::AEK_D128, - AArch64::AEK_LSE128, + AArch64::AEK_LSE128, AArch64::AEK_XS, }; std::vector Features;