Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9972,6 +9972,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 @@ -76,6 +76,7 @@ bool HasNoNeon = false; bool HasNoSVE = false; bool HasFMV = true; + bool HasXS = false; 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 @@ -673,6 +673,7 @@ .Case("bti", HasBTI) .Cases("ls64", "ls64_v", "ls64_accdata", HasLS64) .Case("wfxt", HasWFxT) + .Case("xs", HasXS) .Default(false); } @@ -832,6 +833,8 @@ FPU |= NeonMode; HasSM4 = true; } + if (Feature == "+xs") + HasXS = true; if (Feature == "+strict-align") HasUnaligned = false; // All predecessor archs are added but select the latest one for ArchKind. Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ clang/lib/Sema/SemaChecking.cpp @@ -3333,13 +3333,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, 4, 0, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}} Index: llvm/include/llvm/TargetParser/AArch64TargetParser.h =================================================================== --- llvm/include/llvm/TargetParser/AArch64TargetParser.h +++ llvm/include/llvm/TargetParser/AArch64TargetParser.h @@ -147,6 +147,7 @@ AEK_SPECRES2 = 1ULL << 53, // FEAT_SPECRES2 AEK_RASv2 = 1ULL << 54, // FEAT_RASv2 AEK_ITE = 1ULL << 55, // FEAT_ITE + AEK_XS = 1ULL << 56, // FEAT_XS }; // clang-format on @@ -249,6 +250,7 @@ {"the", AArch64::AEK_THE, "+the", "-the", FEAT_MAX, "", 0}, {"tme", AArch64::AEK_TME, "+tme", "-tme", FEAT_MAX, "", 0}, {"wfxt", AArch64::AEK_NONE, {}, {}, FEAT_WFXT, "+wfxt", 550}, + {"xs", AArch64::AEK_XS, "+xs", "-xs", FEAT_MAX, "", 0}, // Special cases {"none", AArch64::AEK_NONE, {}, {}, FEAT_MAX, "", ExtensionInfo::MaxFMVPriority}, }; @@ -309,12 +311,12 @@ inline constexpr ArchInfo ARMV8_4A = { VersionTuple{8, 4}, AProfile, "armv8.4-a", "+v8.4a", (ARMV8_3A.DefaultExts | AArch64::AEK_DOTPROD)}; inline constexpr ArchInfo ARMV8_5A = { VersionTuple{8, 5}, AProfile, "armv8.5-a", "+v8.5a", (ARMV8_4A.DefaultExts)}; inline constexpr ArchInfo ARMV8_6A = { VersionTuple{8, 6}, AProfile, "armv8.6-a", "+v8.6a", (ARMV8_5A.DefaultExts | AArch64::AEK_BF16 | AArch64::AEK_I8MM)}; -inline constexpr ArchInfo ARMV8_7A = { VersionTuple{8, 7}, AProfile, "armv8.7-a", "+v8.7a", (ARMV8_6A.DefaultExts)}; +inline constexpr ArchInfo ARMV8_7A = { VersionTuple{8, 7}, AProfile, "armv8.7-a", "+v8.7a", (ARMV8_6A.DefaultExts | AArch64::AEK_XS)}; inline constexpr ArchInfo ARMV8_8A = { VersionTuple{8, 8}, AProfile, "armv8.8-a", "+v8.8a", (ARMV8_7A.DefaultExts | AArch64::AEK_MOPS | AArch64::AEK_HBC)}; inline constexpr ArchInfo ARMV8_9A = { VersionTuple{8, 9}, AProfile, "armv8.9-a", "+v8.9a", (ARMV8_8A.DefaultExts | AArch64::AEK_SPECRES2 | AArch64::AEK_CSSC | AArch64::AEK_RASv2)}; inline constexpr ArchInfo ARMV9A = { VersionTuple{9, 0}, AProfile, "armv9-a", "+v9a", (ARMV8_5A.DefaultExts | AArch64::AEK_FP16 | AArch64::AEK_SVE | AArch64::AEK_SVE2)}; inline constexpr ArchInfo ARMV9_1A = { VersionTuple{9, 1}, AProfile, "armv9.1-a", "+v9.1a", (ARMV9A.DefaultExts | AArch64::AEK_BF16 | AArch64::AEK_I8MM)}; -inline constexpr ArchInfo ARMV9_2A = { VersionTuple{9, 2}, AProfile, "armv9.2-a", "+v9.2a", (ARMV9_1A.DefaultExts)}; +inline constexpr ArchInfo ARMV9_2A = { VersionTuple{9, 2}, AProfile, "armv9.2-a", "+v9.2a", (ARMV9_1A.DefaultExts | AArch64::AEK_XS)}; inline constexpr ArchInfo ARMV9_3A = { VersionTuple{9, 3}, AProfile, "armv9.3-a", "+v9.3a", (ARMV9_2A.DefaultExts | AArch64::AEK_MOPS | AArch64::AEK_HBC)}; inline constexpr ArchInfo ARMV9_4A = { VersionTuple{9, 4}, AProfile, "armv9.4-a", "+v9.4a", (ARMV9_3A.DefaultExts | AArch64::AEK_SPECRES2 | AArch64::AEK_CSSC | 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. Index: llvm/lib/Target/AArch64/AArch64InstrFormats.td =================================================================== --- llvm/lib/Target/AArch64/AArch64InstrFormats.td +++ llvm/lib/Target/AArch64/AArch64InstrFormats.td @@ -1034,6 +1034,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 @@ -1023,7 +1023,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/TargetParser/TargetParserTest.cpp =================================================================== --- llvm/unittests/TargetParser/TargetParserTest.cpp +++ llvm/unittests/TargetParser/TargetParserTest.cpp @@ -1572,7 +1572,7 @@ AArch64::AEK_B16B16, AArch64::AEK_SMEF16F16, AArch64::AEK_CSSC, AArch64::AEK_RCPC3, AArch64::AEK_THE, AArch64::AEK_D128, AArch64::AEK_LSE128, AArch64::AEK_SPECRES2, AArch64::AEK_RASv2, - AArch64::AEK_ITE, + AArch64::AEK_ITE, AArch64::AEK_XS, }; std::vector Features;