[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
SamTebbs33 wrote: New PR at https://github.com/llvm/llvm-project/pull/75487 https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
SamTebbs33 wrote: Thanks for reporting that Nico. I've reverted the patch and will work on improving compile time. I like your idea Sander. https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
sdesmalen-arm wrote: > On my system, this increases the compilation time of SemaChecking.cpp from 7 > seconds to 2 minutes 46 seconds (using clang as a host compiler). That seems > excessive. Let's please find a way to not make compilation so slow, and let's > consider reverting this until a faster approach is found. I see the same with GCC. It seems that changing the generated table from: ``` case SVE::BI__builtin_sve_svaba_n_s16: BuiltinType = ArmStreamingCompatible; break; case SVE::BI__builtin_sve_svaba_n_s32: BuiltinType = ArmStreamingCompatible; break; case SVE::BI__builtin_sve_svaba_n_s64: BuiltinType = ArmStreamingCompatible; break; ... ``` to ``` case SVE::BI__builtin_sve_svacge_n_f16: case SVE::BI__builtin_sve_svacge_n_f32: case SVE::BI__builtin_sve_svacge_n_f64: ... BuiltinType = ArmStreamingCompatible; break; ``` resolves most of the issue without changing behaviours. Additionally, it might be good to make the most common streaming-mode for this file the default (which for arm_sve.h is streaming-compatible), so that the table only has to capture the intrinsics which are explicitly non-streaming or streaming. https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
nico wrote: On my system, this increases the compilation time of SemaChecking.cpp from 7 seconds to 2 minutes 46 seconds (using clang as a host compiler). That seems excessive. Let's please find a way to not make compilation so slow, and let's consider reverting this until a faster approach is found. https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
https://github.com/SamTebbs33 closed https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
https://github.com/sdesmalen-arm approved this pull request. https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -3168,9 +3167,60 @@ static void checkArmStreamingBuiltin(Sema , CallExpr *TheCall, << TheCall->getSourceRange() << "streaming compatible"; return; } + + if (FnType == ArmNonStreaming && BuiltinType == ArmStreaming) { +S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) +<< TheCall->getSourceRange() << "non-streaming"; + } +} + +bool Sema::CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { + if (const FunctionDecl *FD = getCurFunctionDecl()) { +ArmStreamingType BuiltinType; + +switch (BuiltinID) { +default: + BuiltinType = ArmNonStreaming; + break; +#define GET_SME_STREAMING_ATTRS +#include "clang/Basic/arm_sme_streaming_attrs.inc" +#undef GET_SME_STREAMING_ATTRS +#define GET_SVE_STREAMING_ATTRS +#include "clang/Basic/arm_sve_streaming_attrs.inc" SamTebbs33 wrote: Good spot, thanks. https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -1694,6 +1697,61 @@ void SVEEmitter::createSMERangeChecks(raw_ostream ) { OS << "#endif\n\n"; } +void SVEEmitter::createStreamingAttrs(raw_ostream , ACLEKind Kind) { + std::vector RV = Records.getAllDerivedDefinitions("Inst"); + SmallVector, 128> Defs; + for (auto *R : RV) +createIntrinsic(R, Defs); + + // The mappings must be sorted based on BuiltinID. + llvm::sort(Defs, [](const std::unique_ptr , + const std::unique_ptr ) { +return A->getMangledName() < B->getMangledName(); + }); + + switch (Kind) { SamTebbs33 wrote: That looks nice and clean to me. Thanks for the suggestion. https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -3168,9 +3167,60 @@ static void checkArmStreamingBuiltin(Sema , CallExpr *TheCall, << TheCall->getSourceRange() << "streaming compatible"; return; } + + if (FnType == ArmNonStreaming && BuiltinType == ArmStreaming) { +S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) +<< TheCall->getSourceRange() << "non-streaming"; + } +} + +bool Sema::CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { + if (const FunctionDecl *FD = getCurFunctionDecl()) { +ArmStreamingType BuiltinType; + +switch (BuiltinID) { +default: + BuiltinType = ArmNonStreaming; + break; +#define GET_SME_STREAMING_ATTRS +#include "clang/Basic/arm_sme_streaming_attrs.inc" +#undef GET_SME_STREAMING_ATTRS +#define GET_SVE_STREAMING_ATTRS +#include "clang/Basic/arm_sve_streaming_attrs.inc" +#undef GET_SVE_STREAMING_ATTRS +} + +if (BuiltinType) + checkArmStreamingBuiltin(*this, TheCall, FD, BuiltinType); + } + + // Range check SME intrinsics that take immediate values. + SmallVector, 3> ImmChecks; + + switch (BuiltinID) { + default: +return false; +#define GET_SME_IMMEDIATE_CHECK +#include "clang/Basic/arm_sme_sema_rangechecks.inc" sdesmalen-arm wrote: The SME range checks should be removed from `CheckSVEBuiltinFunctionCall` now. https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -3168,9 +3167,60 @@ static void checkArmStreamingBuiltin(Sema , CallExpr *TheCall, << TheCall->getSourceRange() << "streaming compatible"; return; } + + if (FnType == ArmNonStreaming && BuiltinType == ArmStreaming) { +S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) +<< TheCall->getSourceRange() << "non-streaming"; + } +} + +bool Sema::CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { + if (const FunctionDecl *FD = getCurFunctionDecl()) { +ArmStreamingType BuiltinType; + +switch (BuiltinID) { +default: + BuiltinType = ArmNonStreaming; + break; +#define GET_SME_STREAMING_ATTRS +#include "clang/Basic/arm_sme_streaming_attrs.inc" +#undef GET_SME_STREAMING_ATTRS +#define GET_SVE_STREAMING_ATTRS +#include "clang/Basic/arm_sve_streaming_attrs.inc" sdesmalen-arm wrote: The SVE streaming-mode attributes already checked in `CheckSVEBuiltinFunctionCall`, there is no need to include them here again. https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -1694,6 +1697,61 @@ void SVEEmitter::createSMERangeChecks(raw_ostream ) { OS << "#endif\n\n"; } +void SVEEmitter::createStreamingAttrs(raw_ostream , ACLEKind Kind) { + std::vector RV = Records.getAllDerivedDefinitions("Inst"); + SmallVector, 128> Defs; + for (auto *R : RV) +createIntrinsic(R, Defs); + + // The mappings must be sorted based on BuiltinID. + llvm::sort(Defs, [](const std::unique_ptr , + const std::unique_ptr ) { +return A->getMangledName() < B->getMangledName(); + }); + + switch (Kind) { sdesmalen-arm wrote: nit: Rather than having two of these switch statements, you could do: ``` StringRef ExtensionKind; switch (Kind) { case ACLEKind::SME: ExtensionKind = "SME"; break; case ACLEKind::SVE: ExtensionKind = "SVE"; break; } OS << "#ifdef GET_" << ExtensionKind << "_STREAMING_ATTRS\n"; ... for (...) { ... OS << "case " << ExtensionKind << "::BI_builtin_" << ExtensionKind.lower() << "_"; ... } ``` https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -500,6 +506,12 @@ bool ClangTableGenMain(raw_ostream , RecordKeeper ) { case GenArmSmeRangeChecks: EmitSmeRangeChecks(Records, OS); break; + case GenArmSmeStreamingAttrs: SamTebbs33 wrote: Done https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -20,3 +21,23 @@ int16x8_t incompat_neon_smc(int16x8_t splat) __arm_streaming_compatible { // expected-warning@+1 {{builtin call has undefined behaviour when called from a streaming compatible function}} return (int16x8_t)__builtin_neon_vqaddq_v((int8x16_t)splat, (int8x16_t)splat, 33); } + +void incompat_sme_norm(svbool_t pg, void const *ptr) __arm_shared_za { + // expected-warning@+1 {{builtin call has undefined behaviour when called from a non-streaming function}} + return __builtin_sme_svld1_hor_za128(0, 0, pg, ptr); SamTebbs33 wrote: I removed this test since, as you said, it wasn't testing anything different and after adding the SVE changes we have tests for SVE builtins anyway. https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -3168,11 +3168,70 @@ static void checkArmStreamingBuiltin(Sema , CallExpr *TheCall, << TheCall->getSourceRange() << "streaming compatible"; return; } + + if (FnType == ArmNonStreaming && BuiltinType == ArmStreaming) { +S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) +<< TheCall->getSourceRange() << "non-streaming"; + } +} SamTebbs33 wrote: I've removed the ZA state changes and added the SVE changes. Let me know what you think. https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -500,6 +506,12 @@ bool ClangTableGenMain(raw_ostream , RecordKeeper ) { case GenArmSmeRangeChecks: EmitSmeRangeChecks(Records, OS); break; + case GenArmSmeStreamingAttrs: SamTebbs33 wrote: I remember you suggesting that we have the SME and SVE changes in separate PRs but I can bring the SVE changes into this one. https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -1375,6 +1381,12 @@ void SVEEmitter::createHeader(raw_ostream ) { OS << "#define __aio static __inline__ __attribute__((__always_inline__, " "__nodebug__, __overloadable__))\n\n"; + OS << "#ifdef __ARM_FEATURE_SME\n"; + OS << "#define __asc __attribute__((arm_streaming_compatible))\n"; SamTebbs33 wrote: Omitting it works for me, cheers. https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -3168,11 +3168,70 @@ static void checkArmStreamingBuiltin(Sema , CallExpr *TheCall, << TheCall->getSourceRange() << "streaming compatible"; return; } + + if (FnType == ArmNonStreaming && BuiltinType == ArmStreaming) { +S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) +<< TheCall->getSourceRange() << "non-streaming"; + } +} + +static bool hasSMEZAState(const FunctionDecl *FD) { + if (FD->hasAttr()) +return true; + if (const auto *T = FD->getType()->getAs()) +if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateZASharedMask) + return true; + return false; +} + +static bool hasSMEZAState(unsigned BuiltinID) { + switch (BuiltinID) { + default: +return false; +#define GET_SME_BUILTIN_HAS_ZA_STATE +#include "clang/Basic/arm_sme_builtins_za_state.inc" +#undef GET_SME_BUILTIN_HAS_ZA_STATE + } +} + +bool Sema::CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { + if (const FunctionDecl *FD = getCurFunctionDecl()) { +std::optional BuiltinType; SamTebbs33 wrote: Sure thing. https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -18,7 +18,7 @@ // CHECK-CXX-NEXT:tail call void @llvm.aarch64.sme.zero(i32 0) // CHECK-CXX-NEXT:ret void // -void test_svzero_mask_za() { +__arm_new_za void test_svzero_mask_za() { SamTebbs33 wrote: I did try `__arm_shared_za` but got > '__arm_shared_za' only applies to non-K functions and > error: '__arm_shared_za' only applies to function types; type here is 'void > ()' https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -6,20 +6,21 @@ #include __attribute__((target("sme"))) -void test_sme(svbool_t pg, void *ptr) { +void test_sme(svbool_t pg, void *ptr) __arm_streaming __arm_shared_za { svld1_hor_za8(0, 0, pg, ptr); } __attribute__((target("arch=armv8-a+sme"))) -void test_arch_sme(svbool_t pg, void *ptr) { +void test_arch_sme(svbool_t pg, void *ptr) __arm_streaming __arm_shared_za { svld1_hor_vnum_za32(0, 0, pg, ptr, 0); } __attribute__((target("+sme"))) -void test_plus_sme(svbool_t pg, void *ptr) { +void test_plus_sme(svbool_t pg, void *ptr) __arm_streaming __arm_shared_za { svst1_ver_za16(0, 0, pg, ptr); } -void undefined(svbool_t pg, void *ptr) { - svst1_ver_vnum_za64(0, 0, pg, ptr, 0); // expected-error {{'svst1_ver_vnum_za64' needs target feature sme}} +__attribute__((target("+sme"))) +void undefined(svbool_t pg, void *ptr) __arm_shared_za { + svst1_ver_vnum_za64(0, 0, pg, ptr, 0); // expected-warning {{builtin call has undefined behaviour when called from a non-streaming function}} SamTebbs33 wrote: In a previous review you asked me to do so: > I think instead you want to compile this test with > __attribute__((target("+sme"))) but without the __arm_streaming to ensure you > get a diagnostic on the builtin call that the behaviour is undefined when the > (parent) function is not a streaming function. https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -20,3 +21,23 @@ int16x8_t incompat_neon_smc(int16x8_t splat) __arm_streaming_compatible { // expected-warning@+1 {{builtin call has undefined behaviour when called from a streaming compatible function}} return (int16x8_t)__builtin_neon_vqaddq_v((int8x16_t)splat, (int8x16_t)splat, 33); } + +void incompat_sme_norm(svbool_t pg, void const *ptr) __arm_shared_za { + // expected-warning@+1 {{builtin call has undefined behaviour when called from a non-streaming function}} + return __builtin_sme_svld1_hor_za128(0, 0, pg, ptr); SamTebbs33 wrote: > nit: returning a `void` value from a `void` function doesn't seem right. Agreed, I'll fix that. > Also, is `incompat_sme_norm` testing anything that `incompat_sme_sm` isn't > testing? > Or should this be a test where we'd call a non-streaming SVE/SME builtin from > a streaming-function? Yeah it doesn't look like it is. That would be better! https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -3058,6 +3058,11 @@ bool Sema::ParseSVEImmChecks( if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 1, 7)) HasError = true; break; +case SVETypeFlags::ImmCheck2_4_Mul2: SamTebbs33 wrote: I think you were looking at an old commit as I fixed that in [48ee745](https://github.com/llvm/llvm-project/pull/74064/commits/48ee745a815f0fda41cb1791f91d73db73e4aeba) https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -3168,11 +3168,70 @@ static void checkArmStreamingBuiltin(Sema , CallExpr *TheCall, << TheCall->getSourceRange() << "streaming compatible"; return; } + + if (FnType == ArmNonStreaming && BuiltinType == ArmStreaming) { +S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) +<< TheCall->getSourceRange() << "non-streaming"; + } +} + +static bool hasSMEZAState(const FunctionDecl *FD) { + if (FD->hasAttr()) +return true; + if (const auto *T = FD->getType()->getAs()) +if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateZASharedMask) + return true; + return false; +} + +static bool hasSMEZAState(unsigned BuiltinID) { + switch (BuiltinID) { + default: +return false; +#define GET_SME_BUILTIN_HAS_ZA_STATE +#include "clang/Basic/arm_sme_builtins_za_state.inc" +#undef GET_SME_BUILTIN_HAS_ZA_STATE + } +} + +bool Sema::CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { + if (const FunctionDecl *FD = getCurFunctionDecl()) { +std::optional BuiltinType; sdesmalen-arm wrote: Why is this `std::optional` rather than `ArmStreamingType` ? We could just set the `default:` case below to be `ArmNonStreaming`. https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -18,7 +18,7 @@ // CHECK-CXX-NEXT:tail call void @llvm.aarch64.sme.zero(i32 0) // CHECK-CXX-NEXT:ret void // -void test_svzero_mask_za() { +__arm_new_za void test_svzero_mask_za() { sdesmalen-arm wrote: Why are these `__arm_new_za` rather than `__arm_shared_za`? https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -6,20 +6,21 @@ #include __attribute__((target("sme"))) -void test_sme(svbool_t pg, void *ptr) { +void test_sme(svbool_t pg, void *ptr) __arm_streaming __arm_shared_za { svld1_hor_za8(0, 0, pg, ptr); } __attribute__((target("arch=armv8-a+sme"))) -void test_arch_sme(svbool_t pg, void *ptr) { +void test_arch_sme(svbool_t pg, void *ptr) __arm_streaming __arm_shared_za { svld1_hor_vnum_za32(0, 0, pg, ptr, 0); } __attribute__((target("+sme"))) -void test_plus_sme(svbool_t pg, void *ptr) { +void test_plus_sme(svbool_t pg, void *ptr) __arm_streaming __arm_shared_za { svst1_ver_za16(0, 0, pg, ptr); } -void undefined(svbool_t pg, void *ptr) { - svst1_ver_vnum_za64(0, 0, pg, ptr, 0); // expected-error {{'svst1_ver_vnum_za64' needs target feature sme}} +__attribute__((target("+sme"))) +void undefined(svbool_t pg, void *ptr) __arm_shared_za { + svst1_ver_vnum_za64(0, 0, pg, ptr, 0); // expected-warning {{builtin call has undefined behaviour when called from a non-streaming function}} sdesmalen-arm wrote: This test should not have changed. https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -3058,6 +3058,11 @@ bool Sema::ParseSVEImmChecks( if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 1, 7)) HasError = true; break; +case SVETypeFlags::ImmCheck2_4_Mul2: sdesmalen-arm wrote: This shouldn't have moved. https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -500,6 +506,12 @@ bool ClangTableGenMain(raw_ostream , RecordKeeper ) { case GenArmSmeRangeChecks: EmitSmeRangeChecks(Records, OS); break; + case GenArmSmeStreamingAttrs: sdesmalen-arm wrote: We also need to do this for SVE (you seem to have added the logic for it in SveEmitter.cpp, but are not using it otherwise). https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -20,3 +21,23 @@ int16x8_t incompat_neon_smc(int16x8_t splat) __arm_streaming_compatible { // expected-warning@+1 {{builtin call has undefined behaviour when called from a streaming compatible function}} return (int16x8_t)__builtin_neon_vqaddq_v((int8x16_t)splat, (int8x16_t)splat, 33); } + +void incompat_sme_norm(svbool_t pg, void const *ptr) __arm_shared_za { + // expected-warning@+1 {{builtin call has undefined behaviour when called from a non-streaming function}} + return __builtin_sme_svld1_hor_za128(0, 0, pg, ptr); sdesmalen-arm wrote: nit: returning a `void` value from a `void` function doesn't seem right. Also, is `incompat_sme_norm` testing anything that `incompat_sme_sm` isn't testing? Or should this be a test where we'd call a non-streaming SVE/SME builtin from a streaming-function? https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -1375,6 +1381,12 @@ void SVEEmitter::createHeader(raw_ostream ) { OS << "#define __aio static __inline__ __attribute__((__always_inline__, " "__nodebug__, __overloadable__))\n\n"; + OS << "#ifdef __ARM_FEATURE_SME\n"; + OS << "#define __asc __attribute__((arm_streaming_compatible))\n"; sdesmalen-arm wrote: A few things: * The `__attribute__((arm_streaming_compatible))` syntax is not supported. * `__asc` is not used/emitted anywhere * I'm not sure adding the attribute to the function prototype in the header file adds much value anyway. Better to just omit it. https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -3168,11 +3168,70 @@ static void checkArmStreamingBuiltin(Sema , CallExpr *TheCall, << TheCall->getSourceRange() << "streaming compatible"; return; } + + if (FnType == ArmNonStreaming && BuiltinType == ArmStreaming) { +S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) +<< TheCall->getSourceRange() << "non-streaming"; + } +} sdesmalen-arm wrote: I think this functionality is big enough to warrant it own PR, such that we have: * One PR for testing the compatibility of streaming-mode for both SVE and SME. * One PR for testing that the calling function of a ZA-using builtin has ZA state. https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -3183,6 +3140,114 @@ bool Sema::CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { return HasError; } +static ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD) { + if (FD->hasAttr()) +return ArmStreaming; + if (const auto *T = FD->getType()->getAs()) { +if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask) + return ArmStreaming; +if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMCompatibleMask) + return ArmStreamingCompatible; + } + return ArmNonStreaming; +} + +static void checkArmStreamingBuiltin(Sema , CallExpr *TheCall, + const FunctionDecl *FD, + ArmStreamingType BuiltinType) { + ArmStreamingType FnType = getArmStreamingFnType(FD); + + if (FnType == ArmStreaming && BuiltinType == ArmNonStreaming) { +S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) +<< TheCall->getSourceRange() << "streaming"; + } + + if (FnType == ArmStreamingCompatible && + BuiltinType != ArmStreamingCompatible) { +S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) +<< TheCall->getSourceRange() << "streaming compatible"; +return; + } + + if (FnType == ArmNonStreaming && BuiltinType == ArmStreaming) { +S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) +<< TheCall->getSourceRange() << "non-streaming"; + } +} + +static bool hasSMEZAState(const FunctionDecl *FD) { + if (FD->hasAttr()) +return true; + if (const auto *T = FD->getType()->getAs()) +if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateZASharedMask) + return true; + return false; +} + +static bool hasSMEZAState(unsigned BuiltinID) { + switch (BuiltinID) { + default: +return false; +#define GET_SME_BUILTIN_HAS_ZA_STATE +#include "clang/Basic/arm_sme_builtins_za_state.inc" +#undef GET_SME_BUILTIN_HAS_ZA_STATE + } +} + +bool Sema::CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { + if (const FunctionDecl *FD = getCurFunctionDecl()) { +std::optional BuiltinType; + +switch (BuiltinID) { +default: + break; +#define GET_SME_STREAMING_ATTRS +#include "clang/Basic/arm_sme_streaming_attrs.inc" +#undef GET_SME_STREAMING_ATTRS +} + +if (BuiltinType) + checkArmStreamingBuiltin(*this, TheCall, FD, *BuiltinType); + +if (hasSMEZAState(BuiltinID) && !hasSMEZAState(FD)) + Diag(TheCall->getBeginLoc(), + diag::warn_attribute_arm_za_builtin_no_za_state) + << TheCall->getSourceRange(); + } + + // Range check SME intrinsics that take immediate values. + SmallVector, 3> ImmChecks; + + switch (BuiltinID) { + default: +return false; +#define GET_SME_IMMEDIATE_CHECK +#include "clang/Basic/arm_sme_sema_rangechecks.inc" +#undef GET_SME_IMMEDIATE_CHECK + } + + return ParseSVEImmChecks(TheCall, ImmChecks); +} + +bool Sema::CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { SamTebbs33 wrote: Done! Rebased and should be ready for review again now. https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -3172,6 +3117,18 @@ bool Sema::CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, 255)) HasError = true; break; +case SVETypeFlags::ImmCheck1_1: SamTebbs33 wrote: I'm actually not sure. When building the compiler was telling me that these cases weren't being checked for so I added them. I'm not sure what caused them to disappear in the first place. I'll revert this chunk. https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -3183,6 +3140,114 @@ bool Sema::CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { return HasError; } +static ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD) { + if (FD->hasAttr()) +return ArmStreaming; + if (const auto *T = FD->getType()->getAs()) { +if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask) + return ArmStreaming; +if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMCompatibleMask) + return ArmStreamingCompatible; + } + return ArmNonStreaming; +} + +static void checkArmStreamingBuiltin(Sema , CallExpr *TheCall, + const FunctionDecl *FD, + ArmStreamingType BuiltinType) { + ArmStreamingType FnType = getArmStreamingFnType(FD); + + if (FnType == ArmStreaming && BuiltinType == ArmNonStreaming) { +S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) +<< TheCall->getSourceRange() << "streaming"; + } + + if (FnType == ArmStreamingCompatible && + BuiltinType != ArmStreamingCompatible) { +S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) +<< TheCall->getSourceRange() << "streaming compatible"; +return; + } + + if (FnType == ArmNonStreaming && BuiltinType == ArmStreaming) { +S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) +<< TheCall->getSourceRange() << "non-streaming"; + } +} + +static bool hasSMEZAState(const FunctionDecl *FD) { + if (FD->hasAttr()) +return true; + if (const auto *T = FD->getType()->getAs()) +if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateZASharedMask) + return true; + return false; +} + +static bool hasSMEZAState(unsigned BuiltinID) { + switch (BuiltinID) { + default: +return false; +#define GET_SME_BUILTIN_HAS_ZA_STATE +#include "clang/Basic/arm_sme_builtins_za_state.inc" +#undef GET_SME_BUILTIN_HAS_ZA_STATE + } +} + +bool Sema::CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { + if (const FunctionDecl *FD = getCurFunctionDecl()) { +std::optional BuiltinType; + +switch (BuiltinID) { +default: + break; +#define GET_SME_STREAMING_ATTRS +#include "clang/Basic/arm_sme_streaming_attrs.inc" +#undef GET_SME_STREAMING_ATTRS +} + +if (BuiltinType) + checkArmStreamingBuiltin(*this, TheCall, FD, *BuiltinType); + +if (hasSMEZAState(BuiltinID) && !hasSMEZAState(FD)) + Diag(TheCall->getBeginLoc(), + diag::warn_attribute_arm_za_builtin_no_za_state) + << TheCall->getSourceRange(); + } + + // Range check SME intrinsics that take immediate values. + SmallVector, 3> ImmChecks; + + switch (BuiltinID) { + default: +return false; +#define GET_SME_IMMEDIATE_CHECK +#include "clang/Basic/arm_sme_sema_rangechecks.inc" +#undef GET_SME_IMMEDIATE_CHECK + } + + return ParseSVEImmChecks(TheCall, ImmChecks); +} + +bool Sema::CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { SamTebbs33 wrote: Sure thing https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -3172,6 +3117,18 @@ bool Sema::CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, 255)) HasError = true; break; +case SVETypeFlags::ImmCheck1_1: sdesmalen-arm wrote: Why have these case statements moved? https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -3183,6 +3140,114 @@ bool Sema::CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { return HasError; } +static ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD) { + if (FD->hasAttr()) +return ArmStreaming; + if (const auto *T = FD->getType()->getAs()) { +if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask) + return ArmStreaming; +if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMCompatibleMask) + return ArmStreamingCompatible; + } + return ArmNonStreaming; +} + +static void checkArmStreamingBuiltin(Sema , CallExpr *TheCall, + const FunctionDecl *FD, + ArmStreamingType BuiltinType) { + ArmStreamingType FnType = getArmStreamingFnType(FD); + + if (FnType == ArmStreaming && BuiltinType == ArmNonStreaming) { +S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) +<< TheCall->getSourceRange() << "streaming"; + } + + if (FnType == ArmStreamingCompatible && + BuiltinType != ArmStreamingCompatible) { +S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) +<< TheCall->getSourceRange() << "streaming compatible"; +return; + } + + if (FnType == ArmNonStreaming && BuiltinType == ArmStreaming) { +S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) +<< TheCall->getSourceRange() << "non-streaming"; + } +} + +static bool hasSMEZAState(const FunctionDecl *FD) { + if (FD->hasAttr()) +return true; + if (const auto *T = FD->getType()->getAs()) +if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateZASharedMask) + return true; + return false; +} + +static bool hasSMEZAState(unsigned BuiltinID) { + switch (BuiltinID) { + default: +return false; +#define GET_SME_BUILTIN_HAS_ZA_STATE +#include "clang/Basic/arm_sme_builtins_za_state.inc" +#undef GET_SME_BUILTIN_HAS_ZA_STATE + } +} + +bool Sema::CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { + if (const FunctionDecl *FD = getCurFunctionDecl()) { +std::optional BuiltinType; + +switch (BuiltinID) { +default: + break; +#define GET_SME_STREAMING_ATTRS +#include "clang/Basic/arm_sme_streaming_attrs.inc" +#undef GET_SME_STREAMING_ATTRS +} + +if (BuiltinType) + checkArmStreamingBuiltin(*this, TheCall, FD, *BuiltinType); + +if (hasSMEZAState(BuiltinID) && !hasSMEZAState(FD)) + Diag(TheCall->getBeginLoc(), + diag::warn_attribute_arm_za_builtin_no_za_state) + << TheCall->getSourceRange(); + } + + // Range check SME intrinsics that take immediate values. + SmallVector, 3> ImmChecks; + + switch (BuiltinID) { + default: +return false; +#define GET_SME_IMMEDIATE_CHECK +#include "clang/Basic/arm_sme_sema_rangechecks.inc" +#undef GET_SME_IMMEDIATE_CHECK + } + + return ParseSVEImmChecks(TheCall, ImmChecks); +} + +bool Sema::CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { sdesmalen-arm wrote: Can you commit the change to move the immediate checks to `ParseSVEImmChecks` as an NFC patch and rebase this one? https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -3023,6 +3151,66 @@ static void checkArmStreamingBuiltin(Sema , CallExpr *TheCall, << TheCall->getSourceRange() << "streaming compatible"; return; } + + if (FnType == ArmNonStreaming && BuiltinType == ArmStreaming) { +S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) +<< TheCall->getSourceRange() << "non-streaming"; + } +} + +static bool hasSMEZAState(const FunctionDecl *FD) { + if (FD->hasAttr()) +return true; + if (const auto *T = FD->getType()->getAs()) +if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateZASharedMask) + return true; + return false; +} + +static bool hasSMEZAState(unsigned BuiltinID) { + switch (BuiltinID) { + default: +return false; +#define GET_SME_BUILTIN_HAS_ZA_STATE +#include "clang/Basic/arm_sme_builtins_za_state.inc" +#undef GET_SME_BUILTIN_HAS_ZA_STATE + } +} + +bool Sema::CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { + if (const FunctionDecl *FD = getCurFunctionDecl()) { +bool debug = FD->getDeclName().getAsString() == "incompat_sve_sm"; +std::optional BuiltinType; + +switch (BuiltinID) { +default: + break; +#define GET_SME_STREAMING_ATTRS +#include "clang/Basic/arm_sme_streaming_attrs.inc" SamTebbs33 wrote: Kept the function separate as per our offline discussion. https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -289,7 +283,7 @@ ARM_STREAMING_ATTR void test_svst1_ver_vnum_za64(uint32_t slice_base, svbool_t p // CHECK-CXX-NEXT:tail call void @llvm.aarch64.sme.st1q.vert( [[TMP0]], ptr [[TMP2]], i32 15, i32 [[SLICE_BASE]]) // CHECK-CXX-NEXT:ret void // -ARM_STREAMING_ATTR void test_svst1_ver_vnum_za128(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) { +void test_svst1_ver_vnum_za128(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) __arm_streaming { SamTebbs33 wrote: Done https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -6,20 +6,20 @@ #include __attribute__((target("sme"))) -void test_sme(svbool_t pg, void *ptr) { +void test_sme(svbool_t pg, void *ptr) __arm_streaming { svld1_hor_za8(0, 0, pg, ptr); } __attribute__((target("arch=armv8-a+sme"))) -void test_arch_sme(svbool_t pg, void *ptr) { +void test_arch_sme(svbool_t pg, void *ptr) __arm_streaming { svld1_hor_vnum_za32(0, 0, pg, ptr, 0); } __attribute__((target("+sme"))) -void test_plus_sme(svbool_t pg, void *ptr) { +void test_plus_sme(svbool_t pg, void *ptr) __arm_streaming { svst1_ver_za16(0, 0, pg, ptr); } -void undefined(svbool_t pg, void *ptr) { - svst1_ver_vnum_za64(0, 0, pg, ptr, 0); // expected-error {{'svst1_ver_vnum_za64' needs target feature sme}} +void undefined(svbool_t pg, void *ptr) __arm_streaming { // expected-error {{function executed in streaming-SVE mode requires 'sme'}} sdesmalen-arm wrote: Ah, I see that the actual message changed too. It's now complaining about `__arm_streaming` on a non-SME function, whereas before it was testing that the builtin was predicated with the correct attribute. This is already tested in `aarch64-sme-func-attrs-without-target-feature.cpp`. I think instead you want to compile this test with `__attribute__((target("+sme")))` but without the `__arm_streaming` to ensure you get a diagnostic on the builtin call that the behaviour is undefined when the (parent) function is not a streaming function. https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -2995,6 +2995,134 @@ static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext , enum ArmStreamingType { ArmNonStreaming, ArmStreaming, ArmStreamingCompatible }; +bool Sema::ParseSVEImmChecks( +CallExpr *TheCall, SmallVector, 3> ) { + // Perform all the immediate checks for this builtin call. + bool HasError = false; + for (auto : ImmChecks) { +int ArgNum, CheckTy, ElementSizeInBits; +std::tie(ArgNum, CheckTy, ElementSizeInBits) = I; + +typedef bool (*OptionSetCheckFnTy)(int64_t Value); + +// Function that checks whether the operand (ArgNum) is an immediate +// that is one of the predefined values. +auto CheckImmediateInSet = [&](OptionSetCheckFnTy CheckImm, + int ErrDiag) -> bool { + // We can't check the value of a dependent argument. + Expr *Arg = TheCall->getArg(ArgNum); + if (Arg->isTypeDependent() || Arg->isValueDependent()) +return false; + + // Check constant-ness first. + llvm::APSInt Imm; + if (SemaBuiltinConstantArg(TheCall, ArgNum, Imm)) +return true; + + if (!CheckImm(Imm.getSExtValue())) +return Diag(TheCall->getBeginLoc(), ErrDiag) << Arg->getSourceRange(); + return false; +}; + +switch ((SVETypeFlags::ImmCheckType)CheckTy) { +case SVETypeFlags::ImmCheck0_31: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, 31)) +HasError = true; + break; +case SVETypeFlags::ImmCheck0_13: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, 13)) +HasError = true; + break; +case SVETypeFlags::ImmCheck1_16: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 1, 16)) +HasError = true; + break; +case SVETypeFlags::ImmCheck0_7: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, 7)) +HasError = true; + break; +case SVETypeFlags::ImmCheckExtract: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, + (2048 / ElementSizeInBits) - 1)) +HasError = true; + break; +case SVETypeFlags::ImmCheckShiftRight: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 1, ElementSizeInBits)) +HasError = true; + break; +case SVETypeFlags::ImmCheckShiftRightNarrow: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 1, + ElementSizeInBits / 2)) +HasError = true; + break; +case SVETypeFlags::ImmCheckShiftLeft: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, + ElementSizeInBits - 1)) +HasError = true; + break; +case SVETypeFlags::ImmCheckLaneIndex: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, + (128 / (1 * ElementSizeInBits)) - 1)) +HasError = true; + break; +case SVETypeFlags::ImmCheckLaneIndexCompRotate: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, + (128 / (2 * ElementSizeInBits)) - 1)) +HasError = true; + break; +case SVETypeFlags::ImmCheckLaneIndexDot: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, + (128 / (4 * ElementSizeInBits)) - 1)) +HasError = true; + break; +case SVETypeFlags::ImmCheckComplexRot90_270: + if (CheckImmediateInSet([](int64_t V) { return V == 90 || V == 270; }, + diag::err_rotation_argument_to_cadd)) +HasError = true; + break; +case SVETypeFlags::ImmCheckComplexRotAll90: + if (CheckImmediateInSet( + [](int64_t V) { +return V == 0 || V == 90 || V == 180 || V == 270; + }, + diag::err_rotation_argument_to_cmla)) +HasError = true; + break; +case SVETypeFlags::ImmCheck0_1: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, 1)) +HasError = true; + break; +case SVETypeFlags::ImmCheck0_2: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, 2)) +HasError = true; + break; +case SVETypeFlags::ImmCheck0_3: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, 3)) +HasError = true; + break; +case SVETypeFlags::ImmCheck0_0: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, 0)) +HasError = true; + break; +case SVETypeFlags::ImmCheck0_15: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, 15)) +HasError = true; + break; +case SVETypeFlags::ImmCheck0_255: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, 255)) +HasError = true; + break; +case SVETypeFlags::ImmCheck2_4_Mul2: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 2, 4) || + SemaBuiltinConstantArgMultiple(TheCall, ArgNum, 2)) +HasError = true; + break; SamTebbs33 wrote: I think it can :+1:
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -6,20 +6,20 @@ #include __attribute__((target("sme"))) -void test_sme(svbool_t pg, void *ptr) { +void test_sme(svbool_t pg, void *ptr) __arm_streaming { svld1_hor_za8(0, 0, pg, ptr); } __attribute__((target("arch=armv8-a+sme"))) -void test_arch_sme(svbool_t pg, void *ptr) { +void test_arch_sme(svbool_t pg, void *ptr) __arm_streaming { svld1_hor_vnum_za32(0, 0, pg, ptr, 0); } __attribute__((target("+sme"))) -void test_plus_sme(svbool_t pg, void *ptr) { +void test_plus_sme(svbool_t pg, void *ptr) __arm_streaming { svst1_ver_za16(0, 0, pg, ptr); } -void undefined(svbool_t pg, void *ptr) { - svst1_ver_vnum_za64(0, 0, pg, ptr, 0); // expected-error {{'svst1_ver_vnum_za64' needs target feature sme}} +void undefined(svbool_t pg, void *ptr) __arm_streaming { // expected-error {{function executed in streaming-SVE mode requires 'sme'}} SamTebbs33 wrote: With the streaming attribute added, the error is thrown for the function signature line, so it has to be on this line. https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -289,7 +283,7 @@ ARM_STREAMING_ATTR void test_svst1_ver_vnum_za64(uint32_t slice_base, svbool_t p // CHECK-CXX-NEXT:tail call void @llvm.aarch64.sme.st1q.vert( [[TMP0]], ptr [[TMP2]], i32 15, i32 [[SLICE_BASE]]) // CHECK-CXX-NEXT:ret void // -ARM_STREAMING_ATTR void test_svst1_ver_vnum_za128(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) { +void test_svst1_ver_vnum_za128(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) __arm_streaming { SamTebbs33 wrote: Sure thing. https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
https://github.com/sdesmalen-arm edited https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -289,7 +283,7 @@ ARM_STREAMING_ATTR void test_svst1_ver_vnum_za64(uint32_t slice_base, svbool_t p // CHECK-CXX-NEXT:tail call void @llvm.aarch64.sme.st1q.vert( [[TMP0]], ptr [[TMP2]], i32 15, i32 [[SLICE_BASE]]) // CHECK-CXX-NEXT:ret void // -ARM_STREAMING_ATTR void test_svst1_ver_vnum_za128(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) { +void test_svst1_ver_vnum_za128(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) __arm_streaming { sdesmalen-arm wrote: Could you commit these test changes (where you remove the __attribute__ syntax and the macro) separately and rebase this patch? https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -3023,6 +3151,66 @@ static void checkArmStreamingBuiltin(Sema , CallExpr *TheCall, << TheCall->getSourceRange() << "streaming compatible"; return; } + + if (FnType == ArmNonStreaming && BuiltinType == ArmStreaming) { +S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) +<< TheCall->getSourceRange() << "non-streaming"; + } +} + +static bool hasSMEZAState(const FunctionDecl *FD) { + if (FD->hasAttr()) +return true; + if (const auto *T = FD->getType()->getAs()) +if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateZASharedMask) + return true; + return false; +} + +static bool hasSMEZAState(unsigned BuiltinID) { + switch (BuiltinID) { + default: +return false; +#define GET_SME_BUILTIN_HAS_ZA_STATE +#include "clang/Basic/arm_sme_builtins_za_state.inc" +#undef GET_SME_BUILTIN_HAS_ZA_STATE + } +} + +bool Sema::CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { + if (const FunctionDecl *FD = getCurFunctionDecl()) { +bool debug = FD->getDeclName().getAsString() == "incompat_sve_sm"; +std::optional BuiltinType; + +switch (BuiltinID) { +default: + break; +#define GET_SME_STREAMING_ATTRS +#include "clang/Basic/arm_sme_streaming_attrs.inc" sdesmalen-arm wrote: Is it not worth merging this into `CheckSVEBuitinFunctionCall` ? That avoids the need to move out the immediate checks altogether. https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -6,20 +6,20 @@ #include __attribute__((target("sme"))) -void test_sme(svbool_t pg, void *ptr) { +void test_sme(svbool_t pg, void *ptr) __arm_streaming { svld1_hor_za8(0, 0, pg, ptr); } __attribute__((target("arch=armv8-a+sme"))) -void test_arch_sme(svbool_t pg, void *ptr) { +void test_arch_sme(svbool_t pg, void *ptr) __arm_streaming { svld1_hor_vnum_za32(0, 0, pg, ptr, 0); } __attribute__((target("+sme"))) -void test_plus_sme(svbool_t pg, void *ptr) { +void test_plus_sme(svbool_t pg, void *ptr) __arm_streaming { svst1_ver_za16(0, 0, pg, ptr); } -void undefined(svbool_t pg, void *ptr) { - svst1_ver_vnum_za64(0, 0, pg, ptr, 0); // expected-error {{'svst1_ver_vnum_za64' needs target feature sme}} +void undefined(svbool_t pg, void *ptr) __arm_streaming { // expected-error {{function executed in streaming-SVE mode requires 'sme'}} sdesmalen-arm wrote: Should the `// expected-error {{ ... }}` not be on the next line? (I would expect the test fails now, because the line doesn't match up) https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
@@ -2995,6 +2995,134 @@ static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext , enum ArmStreamingType { ArmNonStreaming, ArmStreaming, ArmStreamingCompatible }; +bool Sema::ParseSVEImmChecks( +CallExpr *TheCall, SmallVector, 3> ) { + // Perform all the immediate checks for this builtin call. + bool HasError = false; + for (auto : ImmChecks) { +int ArgNum, CheckTy, ElementSizeInBits; +std::tie(ArgNum, CheckTy, ElementSizeInBits) = I; + +typedef bool (*OptionSetCheckFnTy)(int64_t Value); + +// Function that checks whether the operand (ArgNum) is an immediate +// that is one of the predefined values. +auto CheckImmediateInSet = [&](OptionSetCheckFnTy CheckImm, + int ErrDiag) -> bool { + // We can't check the value of a dependent argument. + Expr *Arg = TheCall->getArg(ArgNum); + if (Arg->isTypeDependent() || Arg->isValueDependent()) +return false; + + // Check constant-ness first. + llvm::APSInt Imm; + if (SemaBuiltinConstantArg(TheCall, ArgNum, Imm)) +return true; + + if (!CheckImm(Imm.getSExtValue())) +return Diag(TheCall->getBeginLoc(), ErrDiag) << Arg->getSourceRange(); + return false; +}; + +switch ((SVETypeFlags::ImmCheckType)CheckTy) { +case SVETypeFlags::ImmCheck0_31: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, 31)) +HasError = true; + break; +case SVETypeFlags::ImmCheck0_13: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, 13)) +HasError = true; + break; +case SVETypeFlags::ImmCheck1_16: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 1, 16)) +HasError = true; + break; +case SVETypeFlags::ImmCheck0_7: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, 7)) +HasError = true; + break; +case SVETypeFlags::ImmCheckExtract: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, + (2048 / ElementSizeInBits) - 1)) +HasError = true; + break; +case SVETypeFlags::ImmCheckShiftRight: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 1, ElementSizeInBits)) +HasError = true; + break; +case SVETypeFlags::ImmCheckShiftRightNarrow: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 1, + ElementSizeInBits / 2)) +HasError = true; + break; +case SVETypeFlags::ImmCheckShiftLeft: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, + ElementSizeInBits - 1)) +HasError = true; + break; +case SVETypeFlags::ImmCheckLaneIndex: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, + (128 / (1 * ElementSizeInBits)) - 1)) +HasError = true; + break; +case SVETypeFlags::ImmCheckLaneIndexCompRotate: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, + (128 / (2 * ElementSizeInBits)) - 1)) +HasError = true; + break; +case SVETypeFlags::ImmCheckLaneIndexDot: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, + (128 / (4 * ElementSizeInBits)) - 1)) +HasError = true; + break; +case SVETypeFlags::ImmCheckComplexRot90_270: + if (CheckImmediateInSet([](int64_t V) { return V == 90 || V == 270; }, + diag::err_rotation_argument_to_cadd)) +HasError = true; + break; +case SVETypeFlags::ImmCheckComplexRotAll90: + if (CheckImmediateInSet( + [](int64_t V) { +return V == 0 || V == 90 || V == 180 || V == 270; + }, + diag::err_rotation_argument_to_cmla)) +HasError = true; + break; +case SVETypeFlags::ImmCheck0_1: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, 1)) +HasError = true; + break; +case SVETypeFlags::ImmCheck0_2: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, 2)) +HasError = true; + break; +case SVETypeFlags::ImmCheck0_3: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, 3)) +HasError = true; + break; +case SVETypeFlags::ImmCheck0_0: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, 0)) +HasError = true; + break; +case SVETypeFlags::ImmCheck0_15: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, 15)) +HasError = true; + break; +case SVETypeFlags::ImmCheck0_255: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, 255)) +HasError = true; + break; +case SVETypeFlags::ImmCheck2_4_Mul2: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 2, 4) || + SemaBuiltinConstantArgMultiple(TheCall, ArgNum, 2)) +HasError = true; + break; kmclaughlin-arm wrote: Can
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
github-actions[bot] wrote: :warning: C/C++ code formatter, clang-format found issues in your code. :warning: You can test this locally with the following command: ``bash git-clang-format --diff 9468de48fcd413aa0895a78bd6f1aeb161b39294 f6a990a000b555d7f8ef0b2a99e3fea98420e899 -- clang/include/clang/Sema/Sema.h clang/lib/Sema/SemaChecking.cpp clang/test/Sema/aarch64-incompat-sm-builtin-calls.c clang/utils/TableGen/SveEmitter.cpp clang/utils/TableGen/TableGen.cpp clang/utils/TableGen/TableGenBackends.h `` View the diff from clang-format here. ``diff diff --git a/clang/utils/TableGen/TableGen.cpp b/clang/utils/TableGen/TableGen.cpp index 9ba2fb07f1..3031a0dd5e 100644 --- a/clang/utils/TableGen/TableGen.cpp +++ b/clang/utils/TableGen/TableGen.cpp @@ -285,11 +285,14 @@ cl::opt Action( "Generate riscv_vector_builtin_cg.inc for clang"), clEnumValN(GenRISCVVectorBuiltinSema, "gen-riscv-vector-builtin-sema", "Generate riscv_vector_builtin_sema.inc for clang"), -clEnumValN(GenRISCVSiFiveVectorBuiltins, "gen-riscv-sifive-vector-builtins", +clEnumValN(GenRISCVSiFiveVectorBuiltins, + "gen-riscv-sifive-vector-builtins", "Generate riscv_sifive_vector_builtins.inc for clang"), -clEnumValN(GenRISCVSiFiveVectorBuiltinCG, "gen-riscv-sifive-vector-builtin-codegen", +clEnumValN(GenRISCVSiFiveVectorBuiltinCG, + "gen-riscv-sifive-vector-builtin-codegen", "Generate riscv_sifive_vector_builtin_cg.inc for clang"), -clEnumValN(GenRISCVSiFiveVectorBuiltinSema, "gen-riscv-sifive-vector-builtin-sema", +clEnumValN(GenRISCVSiFiveVectorBuiltinSema, + "gen-riscv-sifive-vector-builtin-sema", "Generate riscv_sifive_vector_builtin_sema.inc for clang"), clEnumValN(GenAttrDocs, "gen-attr-docs", "Generate attribute documentation"), `` https://github.com/llvm/llvm-project/pull/74064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
llvmbot wrote: @llvm/pr-subscribers-clang Author: Sam Tebbs (SamTebbs33) Changes This PR adds a warning that's emitted when a non-streaming or non-streaming-compatible builtin is called in an unsuitable function. Uses work by Kerry McLaughlin. --- Full diff: https://github.com/llvm/llvm-project/pull/74064.diff 8 Files Affected: - (modified) clang/include/clang/Basic/CMakeLists.txt (+6) - (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+3) - (modified) clang/include/clang/Sema/Sema.h (+3) - (modified) clang/lib/Sema/SemaChecking.cpp (+191) - (modified) clang/test/Sema/aarch64-incompat-sm-builtin-calls.c (+21) - (modified) clang/utils/TableGen/SveEmitter.cpp (+68) - (modified) clang/utils/TableGen/TableGen.cpp (+9) - (modified) clang/utils/TableGen/TableGenBackends.h (+1) ``diff diff --git a/clang/include/clang/Basic/CMakeLists.txt b/clang/include/clang/Basic/CMakeLists.txt index 085e316fcc671df..bdd72d1d63c431b 100644 --- a/clang/include/clang/Basic/CMakeLists.txt +++ b/clang/include/clang/Basic/CMakeLists.txt @@ -97,6 +97,12 @@ clang_tablegen(arm_sme_builtin_cg.inc -gen-arm-sme-builtin-codegen clang_tablegen(arm_sme_sema_rangechecks.inc -gen-arm-sme-sema-rangechecks SOURCE arm_sme.td TARGET ClangARMSmeSemaRangeChecks) +clang_tablegen(arm_sme_streaming_attrs.inc -gen-arm-sme-streaming-attrs + SOURCE arm_sme.td + TARGET ClangARMSmeStreamingAttrs) +clang_tablegen(arm_sme_builtins_za_state.inc -gen-arm-sme-builtin-za-state + SOURCE arm_sme.td + TARGET ClangARMSmeBuiltinsZAState) clang_tablegen(arm_cde_builtins.inc -gen-arm-cde-builtin-def SOURCE arm_cde.td TARGET ClangARMCdeBuiltinsDef) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 6dfb2d7195203a3..c7036fc881a13e1 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3151,6 +3151,9 @@ def err_attribute_arm_feature_sve_bits_unsupported : Error< def warn_attribute_arm_sm_incompat_builtin : Warning< "builtin call has undefined behaviour when called from a %0 function">, InGroup>; +def warn_attribute_arm_za_builtin_no_za_state : Warning< + "builtin call is not valid when calling from a function without active ZA state">, + InGroup>; def err_sve_vector_in_non_sve_target : Error< "SVE vector type %0 cannot be used in a target without sve">; def err_attribute_riscv_rvv_bits_unsupported : Error< diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 6de1a098e067a38..c13c6942c219700 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -13845,7 +13845,10 @@ class Sema final { bool CheckNeonBuiltinFunctionCall(const TargetInfo , unsigned BuiltinID, CallExpr *TheCall); bool CheckMVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + bool ParseSVEImmChecks(CallExpr *TheCall, + SmallVector, 3> ); bool CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + bool CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); bool CheckCDEBuiltinFunctionCall(const TargetInfo , unsigned BuiltinID, CallExpr *TheCall); bool CheckARMCoprocessorImmediate(const TargetInfo , const Expr *CoprocArg, diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 77c8334f3ca25d3..f27eb8ad95cc703 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2995,6 +2995,134 @@ static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext , enum ArmStreamingType { ArmNonStreaming, ArmStreaming, ArmStreamingCompatible }; +bool Sema::ParseSVEImmChecks( +CallExpr *TheCall, SmallVector, 3> ) { + // Perform all the immediate checks for this builtin call. + bool HasError = false; + for (auto : ImmChecks) { +int ArgNum, CheckTy, ElementSizeInBits; +std::tie(ArgNum, CheckTy, ElementSizeInBits) = I; + +typedef bool (*OptionSetCheckFnTy)(int64_t Value); + +// Function that checks whether the operand (ArgNum) is an immediate +// that is one of the predefined values. +auto CheckImmediateInSet = [&](OptionSetCheckFnTy CheckImm, + int ErrDiag) -> bool { + // We can't check the value of a dependent argument. + Expr *Arg = TheCall->getArg(ArgNum); + if (Arg->isTypeDependent() || Arg->isValueDependent()) +return false; + + // Check constant-ness first. + llvm::APSInt Imm; + if (SemaBuiltinConstantArg(TheCall, ArgNum, Imm)) +return true; + + if (!CheckImm(Imm.getSExtValue())) +return Diag(TheCall->getBeginLoc(), ErrDiag) << Arg->getSourceRange(); + return false; +}; + +switch ((SVETypeFlags::ImmCheckType)CheckTy) { +case SVETypeFlags::ImmCheck0_31: + if
[clang] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function (PR #74064)
https://github.com/SamTebbs33 created https://github.com/llvm/llvm-project/pull/74064 This PR adds a warning that's emitted when a non-streaming or non-streaming-compatible builtin is called in an unsuitable function. Uses work by Kerry McLaughlin. >From f6a990a000b555d7f8ef0b2a99e3fea98420e899 Mon Sep 17 00:00:00 2001 From: Samuel Tebbs Date: Thu, 30 Nov 2023 13:42:50 + Subject: [PATCH] [AArch64][SME] Warn when using a streaming builtin from a non-streaming function This PR adds a warning that's emitted when a non-streaming or non-streaming-compatible builtin is called in an unsuitable function. Uses work by Kerry McLaughlin. --- clang/include/clang/Basic/CMakeLists.txt | 6 + .../clang/Basic/DiagnosticSemaKinds.td| 3 + clang/include/clang/Sema/Sema.h | 3 + clang/lib/Sema/SemaChecking.cpp | 191 ++ .../Sema/aarch64-incompat-sm-builtin-calls.c | 21 ++ clang/utils/TableGen/SveEmitter.cpp | 68 +++ clang/utils/TableGen/TableGen.cpp | 9 + clang/utils/TableGen/TableGenBackends.h | 1 + 8 files changed, 302 insertions(+) diff --git a/clang/include/clang/Basic/CMakeLists.txt b/clang/include/clang/Basic/CMakeLists.txt index 085e316fcc671df..bdd72d1d63c431b 100644 --- a/clang/include/clang/Basic/CMakeLists.txt +++ b/clang/include/clang/Basic/CMakeLists.txt @@ -97,6 +97,12 @@ clang_tablegen(arm_sme_builtin_cg.inc -gen-arm-sme-builtin-codegen clang_tablegen(arm_sme_sema_rangechecks.inc -gen-arm-sme-sema-rangechecks SOURCE arm_sme.td TARGET ClangARMSmeSemaRangeChecks) +clang_tablegen(arm_sme_streaming_attrs.inc -gen-arm-sme-streaming-attrs + SOURCE arm_sme.td + TARGET ClangARMSmeStreamingAttrs) +clang_tablegen(arm_sme_builtins_za_state.inc -gen-arm-sme-builtin-za-state + SOURCE arm_sme.td + TARGET ClangARMSmeBuiltinsZAState) clang_tablegen(arm_cde_builtins.inc -gen-arm-cde-builtin-def SOURCE arm_cde.td TARGET ClangARMCdeBuiltinsDef) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 6dfb2d7195203a3..c7036fc881a13e1 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3151,6 +3151,9 @@ def err_attribute_arm_feature_sve_bits_unsupported : Error< def warn_attribute_arm_sm_incompat_builtin : Warning< "builtin call has undefined behaviour when called from a %0 function">, InGroup>; +def warn_attribute_arm_za_builtin_no_za_state : Warning< + "builtin call is not valid when calling from a function without active ZA state">, + InGroup>; def err_sve_vector_in_non_sve_target : Error< "SVE vector type %0 cannot be used in a target without sve">; def err_attribute_riscv_rvv_bits_unsupported : Error< diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 6de1a098e067a38..c13c6942c219700 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -13845,7 +13845,10 @@ class Sema final { bool CheckNeonBuiltinFunctionCall(const TargetInfo , unsigned BuiltinID, CallExpr *TheCall); bool CheckMVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + bool ParseSVEImmChecks(CallExpr *TheCall, + SmallVector, 3> ); bool CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + bool CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); bool CheckCDEBuiltinFunctionCall(const TargetInfo , unsigned BuiltinID, CallExpr *TheCall); bool CheckARMCoprocessorImmediate(const TargetInfo , const Expr *CoprocArg, diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 77c8334f3ca25d3..f27eb8ad95cc703 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2995,6 +2995,134 @@ static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext , enum ArmStreamingType { ArmNonStreaming, ArmStreaming, ArmStreamingCompatible }; +bool Sema::ParseSVEImmChecks( +CallExpr *TheCall, SmallVector, 3> ) { + // Perform all the immediate checks for this builtin call. + bool HasError = false; + for (auto : ImmChecks) { +int ArgNum, CheckTy, ElementSizeInBits; +std::tie(ArgNum, CheckTy, ElementSizeInBits) = I; + +typedef bool (*OptionSetCheckFnTy)(int64_t Value); + +// Function that checks whether the operand (ArgNum) is an immediate +// that is one of the predefined values. +auto CheckImmediateInSet = [&](OptionSetCheckFnTy CheckImm, + int ErrDiag) -> bool { + // We can't check the value of a dependent argument. + Expr *Arg = TheCall->getArg(ArgNum); + if (Arg->isTypeDependent() || Arg->isValueDependent()) +return false; + + // Check constant-ness first. + llvm::APSInt Imm; + if (SemaBuiltinConstantArg(TheCall,