https://github.com/dtemirbulatov updated https://github.com/llvm/llvm-project/pull/79842
>From af323998a63a72f569d543cf5167d5d28e784682 Mon Sep 17 00:00:00 2001 From: Dinar Temirbulatov <dinar.temirbula...@arm.com> Date: Mon, 29 Jan 2024 14:43:13 +0000 Subject: [PATCH 1/8] [Clang][AArch64] Warn when calling streaming/non-streaming about vector size might be different. The compiler doesn't know in advance if the streaming and non-streaming vector-lengths are different, so it should be safe to give a warning diagnostic to warn the user about possible undefined behaviour. If the user knows the vector lengths are equal, they can disable the warning separately. --- .../clang/Basic/DiagnosticSemaKinds.td | 24 +++++++ clang/lib/Sema/SemaChecking.cpp | 42 ++++++++++++ clang/test/Sema/aarch64-sme-func-attrs.c | 68 ++++++++++++++++++- 3 files changed, 132 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 24d32cb87c89e2..37fea5746936c7 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3717,6 +3717,30 @@ def err_sme_definition_using_za_in_non_sme_target : Error< "function using ZA state requires 'sme'">; def err_sme_definition_using_zt0_in_non_sme2_target : Error< "function using ZT0 state requires 'sme2'">; +def warn_sme_streaming_caller_pass_args_to_non_streaming : Warning< + "streaming caller passes a VL-dependent argument to non-streaming callee, " + "the streaming and non-streaming vector lengths may be different">, + InGroup<IgnoredAttributes>; +def warn_sme_non_streaming_callee_returns_to_streaming : Warning< + "non-streaming callee returns a VL-dependent value to streaming caller, " + "the streaming and non-streaming vector lengths may be different">, + InGroup<IgnoredAttributes>; +def warn_sme_non_streaming_caller_pass_args_to_streaming : Warning< + "non-streaming caller passes a VL-dependent argument to streaming callee, " + "the streaming and non-streaming vector lengths may be different">, + InGroup<IgnoredAttributes>; +def warn_sme_non_streaming_caller_returns_to_streaming : Warning< + "non-streaming callee returns a VL-dependent value to streaming caller, " + "the streaming and non-streaming vector lengths may be different">, + InGroup<IgnoredAttributes>; +def warn_sme_locally_streaming_has_vl_args : Warning< + "non-streaming callee receives a VL-dependent argument and the callee has an arm_locally_streaming attribute, " + "the streaming and non-streaming vector lengths may be different">, + InGroup<IgnoredAttributes>; +def warn_sme_locally_streaming_returns_vl : Warning< + "non-streaming callee returns a VL-dependent value and the callee has an arm_locally_streaming attribute, " + "the streaming and non-streaming vector lengths may be different">, + InGroup<IgnoredAttributes>; def err_conflicting_attributes_arm_state : Error< "conflicting attributes for state '%0'">; def err_unknown_arm_state : Error< diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 502b24bcdf8b42..e668a45c69e5f9 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -7480,6 +7480,7 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, // For variadic functions, we may have more args than parameters. // For some K&R functions, we may have less args than parameters. const auto N = std::min<unsigned>(Proto->getNumParams(), Args.size()); + bool AnyScalableArgs = false; for (unsigned ArgIdx = 0; ArgIdx < N; ++ArgIdx) { // Args[ArgIdx] can be null in malformed code. if (const Expr *Arg = Args[ArgIdx]) { @@ -7493,6 +7494,8 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, checkAIXMemberAlignment((Arg->getExprLoc()), Arg); QualType ParamTy = Proto->getParamType(ArgIdx); + if (ParamTy->isSizelessVectorType()) + AnyScalableArgs = true; QualType ArgTy = Arg->getType(); CheckArgAlignment(Arg->getExprLoc(), FDecl, std::to_string(ArgIdx + 1), ArgTy, ParamTy); @@ -7513,6 +7516,45 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, } } + auto *CallerFD = dyn_cast<FunctionDecl>(CurContext); + if (FD && CallerFD && Context.getTargetInfo().hasFeature("sme") && + !FD->getBuiltinID()) { + // If the callee has an AArch64 SME __arm_locally_streaming attribute + // warn if this function returns VL-based value or pass any such argument, + // the streaming and non-streaming vector lengths may be different. + ArmStreamingType CalleeFnType = getArmStreamingFnType(FD); + ArmStreamingType CallerFnType = getArmStreamingFnType(CallerFD); + if (FD->hasAttr<ArmLocallyStreamingAttr>() && + CallerFnType != ArmStreaming) { + if (AnyScalableArgs) + Diag(Loc, diag::warn_sme_locally_streaming_has_vl_args); + if (FD->getReturnType()->isSizelessVectorType()) + Diag(Loc, diag::warn_sme_locally_streaming_returns_vl); + } + // If the caller is a non-streaming function and the callee has a + // streaming attribute. If it passed any VL-based arguments or return + // VL-based value, then warn that the streaming and non-streaming vector + // lengths may be different. + if (CallerFnType != ArmStreaming) { + if (CalleeFnType == ArmStreaming) { + if (AnyScalableArgs) + Diag(Loc, + diag::warn_sme_non_streaming_caller_pass_args_to_streaming); + if (FD->getReturnType()->isSizelessVectorType()) + Diag(Loc, diag::warn_sme_non_streaming_caller_returns_to_streaming); + } + } else if (!FD->hasAttr<ArmLocallyStreamingAttr>()) { + // If the callee is a non-streaming function and the caller has + // streaming attribute. If it passed any VL-based arguments or return + // VL-based value, then warn that the streaming and non-streaming vector + // lengths may be different. + if (AnyScalableArgs) + Diag(Loc, diag::warn_sme_streaming_caller_pass_args_to_non_streaming); + if (FD->getReturnType()->isSizelessVectorType()) + Diag(Loc, diag::warn_sme_non_streaming_callee_returns_to_streaming); + } + } + // If the callee uses AArch64 SME ZA state but the caller doesn't define // any, then this is an error. FunctionType::ArmStateValue ArmZAState = diff --git a/clang/test/Sema/aarch64-sme-func-attrs.c b/clang/test/Sema/aarch64-sme-func-attrs.c index 97409ae7d6040c..0a8e6e03a94f29 100644 --- a/clang/test/Sema/aarch64-sme-func-attrs.c +++ b/clang/test/Sema/aarch64-sme-func-attrs.c @@ -1,5 +1,6 @@ -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -fsyntax-only -verify %s -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -fsyntax-only -verify=expected-cpp -x c++ %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme -fsyntax-only -verify=expected-cpp -x c++ %s +#include <arm_sme.h> // Valid attributes @@ -48,6 +49,9 @@ typedef void (*fptrty6) (void); fptrty6 cast_nza_func_to_normal() { return sme_arm_new_za; } fptrty6 cast_ls_func_to_normal() { return sme_arm_locally_streaming; } +void sme_arm_streaming_with_vl_args(void) __arm_streaming; + + // Invalid attributes // expected-cpp-error@+4 {{'__arm_streaming_compatible' and '__arm_streaming' are not compatible}} @@ -445,3 +449,63 @@ void conflicting_state_attrs_preserves_out_zt0(void) __arm_preserves("zt0") __ar // expected-cpp-error@+2 {{conflicting attributes for state 'zt0'}} // expected-error@+1 {{conflicting attributes for state 'zt0'}} void conflicting_state_attrs_preserves_inout_zt0(void) __arm_preserves("zt0") __arm_inout("zt0"); + +void sme_streaming_with_vl_arg(svint32x4_t a) __arm_streaming { } + +svint32x4_t sme_streaming_returns_vl(void) __arm_streaming { svint32x4_t r; return r; } + +void sme_none_streaming_with_vl_arg(svint32x4_t a) { } + +svint32x4_t sme_none_streaming_returns_vl(void) { svint32x4_t r; return r; } + +__arm_locally_streaming void sme_locally_streaming_with_vl_arg(svint32x4_t a) { } + +__arm_locally_streaming svint32x4_t sme_locally_streaming_returns_vl(void) { svint32x4_t r; return r; } + +void sme_none_streaming_calling_streaming_with_vl_args() { + svint32x4_t a; + // expected-warning@+2 {{non-streaming caller passes a VL-dependent argument to streaming callee, the streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{non-streaming caller passes a VL-dependent argument to streaming callee, the streaming and non-streaming vector lengths may be different}} + sme_streaming_with_vl_arg(a); +} + +void sme_none_streaming_calling_streaming_with_return_vl() { + // expected-warning@+2 {{non-streaming callee returns a VL-dependent value to streaming caller, the streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{non-streaming callee returns a VL-dependent value to streaming caller, the streaming and non-streaming vector lengths may be different}} + svint32x4_t r = sme_streaming_returns_vl(); +} + +void sme_streaming_calling_non_streaming_with_vl_args(void) __arm_streaming { + svint32x4_t a; + // expected-warning@+2 {{streaming caller passes a VL-dependent argument to non-streaming callee, the streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{streaming caller passes a VL-dependent argument to non-streaming callee, the streaming and non-streaming vector lengths may be different}} + sme_none_streaming_with_vl_arg(a); +} + +void sme_streaming_calling_non_streaming_with_return_vl(void) __arm_streaming { + // expected-warning@+2 {{non-streaming callee returns a VL-dependent value to streaming caller, the streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{non-streaming callee returns a VL-dependent value to streaming caller, the streaming and non-streaming vector lengths may be different}} + svint32x4_t r = sme_streaming_returns_vl(); +} + +void sme_streaming_calling_locally_streaming_with_vl_args(void) __arm_streaming { + svint32x4_t a; + // expected-1warning@+2 {{non-streaming callee receives a VL-dependent argument and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} + // expected-1cpp-warning@+1 {{non-streaming callee receives a VL-dependent argument and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} + sme_locally_streaming_with_vl_arg(a); +} + +void sme_streaming_calling_locally_streaming_with_return_vl(void) __arm_streaming { + // expected-1warning@+2 {{non-streaming callee returns a VL-dependent value and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} + // expected-1cpp-warning@+1 {{non-streaming callee returns a VL-dependent value and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} + svint32x4_t r = sme_locally_streaming_returns_vl(); +} + +void sme_none_streaming_calling_locally_streaming_with_vl_args(void) __arm_streaming { + svint32x4_t a; + sme_locally_streaming_with_vl_arg(a); +} + +void sme_none_streaming_calling_locally_streaming_with_return_vl(void) __arm_streaming { + svint32x4_t r = sme_locally_streaming_returns_vl(); +} >From 470777a7704353fbf81a61a5c2c5572e9928ce61 Mon Sep 17 00:00:00 2001 From: Dinar Temirbulatov <dinar.temirbula...@arm.com> Date: Tue, 30 Jan 2024 08:59:36 +0000 Subject: [PATCH 2/8] Corrected diagnostics, allowed to emit warning even when we call streaming local function from streaming function. --- clang/lib/Sema/SemaChecking.cpp | 3 +-- clang/test/Sema/aarch64-sme-func-attrs.c | 12 ++++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index e668a45c69e5f9..5f7044cb09f80d 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -7524,8 +7524,7 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, // the streaming and non-streaming vector lengths may be different. ArmStreamingType CalleeFnType = getArmStreamingFnType(FD); ArmStreamingType CallerFnType = getArmStreamingFnType(CallerFD); - if (FD->hasAttr<ArmLocallyStreamingAttr>() && - CallerFnType != ArmStreaming) { + if (FD->hasAttr<ArmLocallyStreamingAttr>()) { if (AnyScalableArgs) Diag(Loc, diag::warn_sme_locally_streaming_has_vl_args); if (FD->getReturnType()->isSizelessVectorType()) diff --git a/clang/test/Sema/aarch64-sme-func-attrs.c b/clang/test/Sema/aarch64-sme-func-attrs.c index 0a8e6e03a94f29..05a0eead96d213 100644 --- a/clang/test/Sema/aarch64-sme-func-attrs.c +++ b/clang/test/Sema/aarch64-sme-func-attrs.c @@ -490,22 +490,26 @@ void sme_streaming_calling_non_streaming_with_return_vl(void) __arm_streaming { void sme_streaming_calling_locally_streaming_with_vl_args(void) __arm_streaming { svint32x4_t a; - // expected-1warning@+2 {{non-streaming callee receives a VL-dependent argument and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} - // expected-1cpp-warning@+1 {{non-streaming callee receives a VL-dependent argument and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} + // expected-warning@+2 {{non-streaming callee receives a VL-dependent argument and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{non-streaming callee receives a VL-dependent argument and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} sme_locally_streaming_with_vl_arg(a); } void sme_streaming_calling_locally_streaming_with_return_vl(void) __arm_streaming { - // expected-1warning@+2 {{non-streaming callee returns a VL-dependent value and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} - // expected-1cpp-warning@+1 {{non-streaming callee returns a VL-dependent value and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} + // expected-warning@+2 {{non-streaming callee returns a VL-dependent value and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{non-streaming callee returns a VL-dependent value and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} svint32x4_t r = sme_locally_streaming_returns_vl(); } void sme_none_streaming_calling_locally_streaming_with_vl_args(void) __arm_streaming { svint32x4_t a; + // expected-warning@+2 {{non-streaming callee receives a VL-dependent argument and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{non-streaming callee receives a VL-dependent argument and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} sme_locally_streaming_with_vl_arg(a); } void sme_none_streaming_calling_locally_streaming_with_return_vl(void) __arm_streaming { + // expected-warning@+2 {{non-streaming callee returns a VL-dependent value and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{non-streaming callee returns a VL-dependent value and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} svint32x4_t r = sme_locally_streaming_returns_vl(); } >From 540a14782fd868d2b63555c2ae614a6b3e95674d Mon Sep 17 00:00:00 2001 From: Dinar Temirbulatov <dinar.temirbula...@arm.com> Date: Thu, 8 Feb 2024 07:44:47 +0000 Subject: [PATCH 3/8] Resolved comments. --- clang/lib/Sema/SemaChecking.cpp | 8 +-- clang/lib/Sema/SemaDecl.cpp | 16 ++++++ .../Sema/aarch64-incompat-sm-builtin-calls.c | 8 +++ clang/test/Sema/aarch64-sme-func-attrs.c | 56 +++++++------------ 4 files changed, 46 insertions(+), 42 deletions(-) diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 5f7044cb09f80d..1414763fc97c1e 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -7524,12 +7524,6 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, // the streaming and non-streaming vector lengths may be different. ArmStreamingType CalleeFnType = getArmStreamingFnType(FD); ArmStreamingType CallerFnType = getArmStreamingFnType(CallerFD); - if (FD->hasAttr<ArmLocallyStreamingAttr>()) { - if (AnyScalableArgs) - Diag(Loc, diag::warn_sme_locally_streaming_has_vl_args); - if (FD->getReturnType()->isSizelessVectorType()) - Diag(Loc, diag::warn_sme_locally_streaming_returns_vl); - } // If the caller is a non-streaming function and the callee has a // streaming attribute. If it passed any VL-based arguments or return // VL-based value, then warn that the streaming and non-streaming vector @@ -7542,7 +7536,7 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, if (FD->getReturnType()->isSizelessVectorType()) Diag(Loc, diag::warn_sme_non_streaming_caller_returns_to_streaming); } - } else if (!FD->hasAttr<ArmLocallyStreamingAttr>()) { + } else if (CalleeFnType != ArmStreaming) { // If the callee is a non-streaming function and the caller has // streaming attribute. If it passed any VL-based arguments or return // VL-based value, then warn that the streaming and non-streaming vector diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index e725e187fc9ea0..0acb8e82b71e71 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -12236,6 +12236,22 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, bool UsesSM = NewFD->hasAttr<ArmLocallyStreamingAttr>(); bool UsesZA = Attr && Attr->isNewZA(); bool UsesZT0 = Attr && Attr->isNewZT0(); + + if (UsesSM) { + if (NewFD->getReturnType()->isSizelessVectorType()) + Diag(NewFD->getLocation(), diag::warn_sme_locally_streaming_returns_vl); + auto *FPT = NewFD->getType()->castAs<FunctionProtoType>(); + bool AnyScalableArgs = false; + for (QualType T : FPT->param_types()) { + if (T->isSizelessVectorType()) { + AnyScalableArgs = true; + break; + } + } + if (AnyScalableArgs) + Diag(NewFD->getLocation(), + diag::warn_sme_locally_streaming_has_vl_args); + } if (const auto *FPT = NewFD->getType()->getAs<FunctionProtoType>()) { FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); UsesSM |= diff --git a/clang/test/Sema/aarch64-incompat-sm-builtin-calls.c b/clang/test/Sema/aarch64-incompat-sm-builtin-calls.c index 55c97c73e8b695..83f61523927bc3 100644 --- a/clang/test/Sema/aarch64-incompat-sm-builtin-calls.c +++ b/clang/test/Sema/aarch64-incompat-sm-builtin-calls.c @@ -33,6 +33,8 @@ svuint32_t incompat_sve_sm(svbool_t pg, svuint32_t a, int16_t b) __arm_streaming return __builtin_sve_svld1_gather_u32base_index_u32(pg, a, b); } +// expected-warning@+2 {{non-streaming callee receives a VL-dependent argument and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} +// expected-warning@+1 {{non-streaming callee returns a VL-dependent value and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} __arm_locally_streaming svuint32_t incompat_sve_ls(svbool_t pg, svuint32_t a, int64_t b) { // expected-warning@+1 {{builtin call has undefined behaviour when called from a streaming function}} return __builtin_sve_svld1_gather_u32base_index_u32(pg, a, b); @@ -48,6 +50,8 @@ svuint32_t incompat_sve2_sm(svbool_t pg, svuint32_t a, int64_t b) __arm_streamin return __builtin_sve_svldnt1_gather_u32base_index_u32(pg, a, b); } +// expected-warning@+2 {{non-streaming callee receives a VL-dependent argument and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} +// expected-warning@+1 {{non-streaming callee returns a VL-dependent value and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} __arm_locally_streaming svuint32_t incompat_sve2_ls(svbool_t pg, svuint32_t a, int64_t b) { // expected-warning@+1 {{builtin call has undefined behaviour when called from a streaming function}} return __builtin_sve_svldnt1_gather_u32base_index_u32(pg, a, b); @@ -68,6 +72,8 @@ svfloat64_t streaming_caller_sve(svbool_t pg, svfloat64_t a, float64_t b) __arm_ return svadd_n_f64_m(pg, a, b); } +// expected-warning@+2 {{non-streaming callee receives a VL-dependent argument and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} +// expected-warning@+1 {{non-streaming callee returns a VL-dependent value and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} __arm_locally_streaming svfloat64_t locally_streaming_caller_sve(svbool_t pg, svfloat64_t a, float64_t b) { // expected-no-warning return svadd_n_f64_m(pg, a, b); @@ -83,6 +89,8 @@ svint16_t streaming_caller_sve2(svint16_t op1, svint16_t op2) __arm_streaming { return svmul_lane_s16(op1, op2, 0); } +// expected-warning@+2 {{non-streaming callee receives a VL-dependent argument and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} +// expected-warning@+1 {{non-streaming callee returns a VL-dependent value and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} __arm_locally_streaming svint16_t locally_streaming_caller_sve2(svint16_t op1, svint16_t op2) { // expected-no-warning return svmul_lane_s16(op1, op2, 0); diff --git a/clang/test/Sema/aarch64-sme-func-attrs.c b/clang/test/Sema/aarch64-sme-func-attrs.c index 05a0eead96d213..f54cad2eee967b 100644 --- a/clang/test/Sema/aarch64-sme-func-attrs.c +++ b/clang/test/Sema/aarch64-sme-func-attrs.c @@ -1,6 +1,5 @@ -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme -fsyntax-only -verify %s -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme -fsyntax-only -verify=expected-cpp -x c++ %s -#include <arm_sme.h> +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -fsyntax-only -verify=expected-cpp -x c++ %s // Valid attributes @@ -450,20 +449,24 @@ void conflicting_state_attrs_preserves_out_zt0(void) __arm_preserves("zt0") __ar // expected-error@+1 {{conflicting attributes for state 'zt0'}} void conflicting_state_attrs_preserves_inout_zt0(void) __arm_preserves("zt0") __arm_inout("zt0"); -void sme_streaming_with_vl_arg(svint32x4_t a) __arm_streaming { } +void sme_streaming_with_vl_arg(__SVInt8_t a) __arm_streaming { } -svint32x4_t sme_streaming_returns_vl(void) __arm_streaming { svint32x4_t r; return r; } +__SVInt8_t sme_streaming_returns_vl(void) __arm_streaming { __SVInt8_t r; return r; } -void sme_none_streaming_with_vl_arg(svint32x4_t a) { } +void sme_none_streaming_with_vl_arg(__SVInt8_t a) { } -svint32x4_t sme_none_streaming_returns_vl(void) { svint32x4_t r; return r; } +__SVInt8_t sme_none_streaming_returns_vl(void) { __SVInt8_t r; return r; } -__arm_locally_streaming void sme_locally_streaming_with_vl_arg(svint32x4_t a) { } +// expected-warning@+2 {{non-streaming callee receives a VL-dependent argument and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{non-streaming callee receives a VL-dependent argument and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} +__arm_locally_streaming void sme_locally_streaming_with_vl_arg(__SVInt8_t a) { } -__arm_locally_streaming svint32x4_t sme_locally_streaming_returns_vl(void) { svint32x4_t r; return r; } +// expected-warning@+2 {{non-streaming callee returns a VL-dependent value and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} +// expected-cpp-warning@+1 {{non-streaming callee returns a VL-dependent value and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} +__arm_locally_streaming __SVInt8_t sme_locally_streaming_returns_vl(void) { __SVInt8_t r; return r; } void sme_none_streaming_calling_streaming_with_vl_args() { - svint32x4_t a; + __SVInt8_t a; // expected-warning@+2 {{non-streaming caller passes a VL-dependent argument to streaming callee, the streaming and non-streaming vector lengths may be different}} // expected-cpp-warning@+1 {{non-streaming caller passes a VL-dependent argument to streaming callee, the streaming and non-streaming vector lengths may be different}} sme_streaming_with_vl_arg(a); @@ -472,11 +475,11 @@ void sme_none_streaming_calling_streaming_with_vl_args() { void sme_none_streaming_calling_streaming_with_return_vl() { // expected-warning@+2 {{non-streaming callee returns a VL-dependent value to streaming caller, the streaming and non-streaming vector lengths may be different}} // expected-cpp-warning@+1 {{non-streaming callee returns a VL-dependent value to streaming caller, the streaming and non-streaming vector lengths may be different}} - svint32x4_t r = sme_streaming_returns_vl(); + __SVInt8_t r = sme_streaming_returns_vl(); } void sme_streaming_calling_non_streaming_with_vl_args(void) __arm_streaming { - svint32x4_t a; + __SVInt8_t a; // expected-warning@+2 {{streaming caller passes a VL-dependent argument to non-streaming callee, the streaming and non-streaming vector lengths may be different}} // expected-cpp-warning@+1 {{streaming caller passes a VL-dependent argument to non-streaming callee, the streaming and non-streaming vector lengths may be different}} sme_none_streaming_with_vl_arg(a); @@ -485,31 +488,14 @@ void sme_streaming_calling_non_streaming_with_vl_args(void) __arm_streaming { void sme_streaming_calling_non_streaming_with_return_vl(void) __arm_streaming { // expected-warning@+2 {{non-streaming callee returns a VL-dependent value to streaming caller, the streaming and non-streaming vector lengths may be different}} // expected-cpp-warning@+1 {{non-streaming callee returns a VL-dependent value to streaming caller, the streaming and non-streaming vector lengths may be different}} - svint32x4_t r = sme_streaming_returns_vl(); -} - -void sme_streaming_calling_locally_streaming_with_vl_args(void) __arm_streaming { - svint32x4_t a; - // expected-warning@+2 {{non-streaming callee receives a VL-dependent argument and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} - // expected-cpp-warning@+1 {{non-streaming callee receives a VL-dependent argument and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} - sme_locally_streaming_with_vl_arg(a); + __SVInt8_t r = sme_none_streaming_returns_vl(); } -void sme_streaming_calling_locally_streaming_with_return_vl(void) __arm_streaming { - // expected-warning@+2 {{non-streaming callee returns a VL-dependent value and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} - // expected-cpp-warning@+1 {{non-streaming callee returns a VL-dependent value and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} - svint32x4_t r = sme_locally_streaming_returns_vl(); -} - -void sme_none_streaming_calling_locally_streaming_with_vl_args(void) __arm_streaming { - svint32x4_t a; - // expected-warning@+2 {{non-streaming callee receives a VL-dependent argument and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} - // expected-cpp-warning@+1 {{non-streaming callee receives a VL-dependent argument and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} - sme_locally_streaming_with_vl_arg(a); +void sme_streaming_calling_streaming_with_vl_args(void) __arm_streaming { + __SVInt8_t a; + sme_streaming_with_vl_arg(a); } -void sme_none_streaming_calling_locally_streaming_with_return_vl(void) __arm_streaming { - // expected-warning@+2 {{non-streaming callee returns a VL-dependent value and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} - // expected-cpp-warning@+1 {{non-streaming callee returns a VL-dependent value and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} - svint32x4_t r = sme_locally_streaming_returns_vl(); +void sme_streaming_calling_streaming_with_return_vl(void) __arm_streaming { + __SVInt8_t r = sme_streaming_returns_vl(); } >From 790afb23fca64f59f8672d7e6d6bf08bec08c234 Mon Sep 17 00:00:00 2001 From: Dinar Temirbulatov <dinar.temirbula...@arm.com> Date: Thu, 8 Feb 2024 11:37:26 +0000 Subject: [PATCH 4/8] Add new waring group AArch64SMEAttributes. --- clang/include/clang/Basic/DiagnosticGroups.td | 3 +++ clang/include/clang/Basic/DiagnosticSemaKinds.td | 12 ++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 6765721ae7002c..7f395a657046c0 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -1390,6 +1390,9 @@ def MultiGPU: DiagGroup<"multi-gpu">; // libc and the CRT to be skipped. def AVRRtlibLinkingQuirks : DiagGroup<"avr-rtlib-linking-quirks">; +// A warning group AArch64 related to SME function attribues. +def AArch64SMEAttributes : DiagGroup<"aarch64-sme-attributes">; + // A warning group for things that will change semantics in the future. def FutureCompat : DiagGroup<"future-compat">; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 37fea5746936c7..03611e0c4531ad 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3720,27 +3720,27 @@ def err_sme_definition_using_zt0_in_non_sme2_target : Error< def warn_sme_streaming_caller_pass_args_to_non_streaming : Warning< "streaming caller passes a VL-dependent argument to non-streaming callee, " "the streaming and non-streaming vector lengths may be different">, - InGroup<IgnoredAttributes>; + InGroup<AArch64SMEAttributes>; def warn_sme_non_streaming_callee_returns_to_streaming : Warning< "non-streaming callee returns a VL-dependent value to streaming caller, " "the streaming and non-streaming vector lengths may be different">, - InGroup<IgnoredAttributes>; + InGroup<AArch64SMEAttributes>; def warn_sme_non_streaming_caller_pass_args_to_streaming : Warning< "non-streaming caller passes a VL-dependent argument to streaming callee, " "the streaming and non-streaming vector lengths may be different">, - InGroup<IgnoredAttributes>; + InGroup<AArch64SMEAttributes>; def warn_sme_non_streaming_caller_returns_to_streaming : Warning< "non-streaming callee returns a VL-dependent value to streaming caller, " "the streaming and non-streaming vector lengths may be different">, - InGroup<IgnoredAttributes>; + InGroup<AArch64SMEAttributes>; def warn_sme_locally_streaming_has_vl_args : Warning< "non-streaming callee receives a VL-dependent argument and the callee has an arm_locally_streaming attribute, " "the streaming and non-streaming vector lengths may be different">, - InGroup<IgnoredAttributes>; + InGroup<AArch64SMEAttributes>; def warn_sme_locally_streaming_returns_vl : Warning< "non-streaming callee returns a VL-dependent value and the callee has an arm_locally_streaming attribute, " "the streaming and non-streaming vector lengths may be different">, - InGroup<IgnoredAttributes>; + InGroup<AArch64SMEAttributes>; def err_conflicting_attributes_arm_state : Error< "conflicting attributes for state '%0'">; def err_unknown_arm_state : Error< >From 66a37aa710ed6be7c3fd3ff46b6caf2adf688d65 Mon Sep 17 00:00:00 2001 From: Dinar Temirbulatov <dinar.temirbula...@arm.com> Date: Mon, 12 Feb 2024 18:45:38 +0000 Subject: [PATCH 5/8] Resolved comments. --- .../clang/Basic/DiagnosticSemaKinds.td | 28 ++----- clang/lib/Sema/SemaChecking.cpp | 27 +++--- clang/lib/Sema/SemaDecl.cpp | 5 +- .../Sema/aarch64-incompat-sm-builtin-calls.c | 16 ++-- clang/test/Sema/aarch64-sme-func-attrs.c | 83 ++++++++++++++----- 5 files changed, 95 insertions(+), 64 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 03611e0c4531ad..a94692166f6460 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3717,29 +3717,13 @@ def err_sme_definition_using_za_in_non_sme_target : Error< "function using ZA state requires 'sme'">; def err_sme_definition_using_zt0_in_non_sme2_target : Error< "function using ZT0 state requires 'sme2'">; -def warn_sme_streaming_caller_pass_args_to_non_streaming : Warning< - "streaming caller passes a VL-dependent argument to non-streaming callee, " - "the streaming and non-streaming vector lengths may be different">, +def warn_sme_streaming_pass_return_vl_to_non_streaming : Warning< + "passing a VL-dependent argument to/from a function that has a different" + " streaming-mode, is undefined behaviour">, InGroup<AArch64SMEAttributes>; -def warn_sme_non_streaming_callee_returns_to_streaming : Warning< - "non-streaming callee returns a VL-dependent value to streaming caller, " - "the streaming and non-streaming vector lengths may be different">, - InGroup<AArch64SMEAttributes>; -def warn_sme_non_streaming_caller_pass_args_to_streaming : Warning< - "non-streaming caller passes a VL-dependent argument to streaming callee, " - "the streaming and non-streaming vector lengths may be different">, - InGroup<AArch64SMEAttributes>; -def warn_sme_non_streaming_caller_returns_to_streaming : Warning< - "non-streaming callee returns a VL-dependent value to streaming caller, " - "the streaming and non-streaming vector lengths may be different">, - InGroup<AArch64SMEAttributes>; -def warn_sme_locally_streaming_has_vl_args : Warning< - "non-streaming callee receives a VL-dependent argument and the callee has an arm_locally_streaming attribute, " - "the streaming and non-streaming vector lengths may be different">, - InGroup<AArch64SMEAttributes>; -def warn_sme_locally_streaming_returns_vl : Warning< - "non-streaming callee returns a VL-dependent value and the callee has an arm_locally_streaming attribute, " - "the streaming and non-streaming vector lengths may be different">, +def warn_sme_locally_streaming_has_vl_args_returns : Warning< + "passing/returning a VL-dependent argument from a function" + " arm_locally_streaming attribute, is undefined behaviour">, InGroup<AArch64SMEAttributes>; def err_conflicting_attributes_arm_state : Error< "conflicting attributes for state '%0'">; diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 1414763fc97c1e..95ac69d9ea90fd 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -7517,34 +7517,37 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, } auto *CallerFD = dyn_cast<FunctionDecl>(CurContext); - if (FD && CallerFD && Context.getTargetInfo().hasFeature("sme") && - !FD->getBuiltinID()) { + bool IsCalleeStreaming = ((ExtInfo.AArch64SMEAttributes & + FunctionType::SME_PStateSMEnabledMask) || + (ExtInfo.AArch64SMEAttributes & + FunctionType::SME_PStateSMCompatibleMask)); + bool IsBuiltin = (FD && FD->getBuiltinID()); + + if (CallerFD && Context.getTargetInfo().hasFeature("sme") && !IsBuiltin) { // If the callee has an AArch64 SME __arm_locally_streaming attribute // warn if this function returns VL-based value or pass any such argument, // the streaming and non-streaming vector lengths may be different. - ArmStreamingType CalleeFnType = getArmStreamingFnType(FD); ArmStreamingType CallerFnType = getArmStreamingFnType(CallerFD); // If the caller is a non-streaming function and the callee has a // streaming attribute. If it passed any VL-based arguments or return // VL-based value, then warn that the streaming and non-streaming vector // lengths may be different. if (CallerFnType != ArmStreaming) { - if (CalleeFnType == ArmStreaming) { + if (IsCalleeStreaming) { if (AnyScalableArgs) - Diag(Loc, - diag::warn_sme_non_streaming_caller_pass_args_to_streaming); - if (FD->getReturnType()->isSizelessVectorType()) - Diag(Loc, diag::warn_sme_non_streaming_caller_returns_to_streaming); + Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming); + if (Proto->getReturnType()->isSizelessVectorType()) + Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming); } - } else if (CalleeFnType != ArmStreaming) { + } else if (!IsCalleeStreaming) { // If the callee is a non-streaming function and the caller has // streaming attribute. If it passed any VL-based arguments or return // VL-based value, then warn that the streaming and non-streaming vector // lengths may be different. if (AnyScalableArgs) - Diag(Loc, diag::warn_sme_streaming_caller_pass_args_to_non_streaming); - if (FD->getReturnType()->isSizelessVectorType()) - Diag(Loc, diag::warn_sme_non_streaming_callee_returns_to_streaming); + Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming); + if (Proto->getReturnType()->isSizelessVectorType()) + Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming); } } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 0acb8e82b71e71..355f464aa8f3f4 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -12239,7 +12239,8 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, if (UsesSM) { if (NewFD->getReturnType()->isSizelessVectorType()) - Diag(NewFD->getLocation(), diag::warn_sme_locally_streaming_returns_vl); + Diag(NewFD->getLocation(), + diag::warn_sme_locally_streaming_has_vl_args_returns); auto *FPT = NewFD->getType()->castAs<FunctionProtoType>(); bool AnyScalableArgs = false; for (QualType T : FPT->param_types()) { @@ -12250,7 +12251,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, } if (AnyScalableArgs) Diag(NewFD->getLocation(), - diag::warn_sme_locally_streaming_has_vl_args); + diag::warn_sme_locally_streaming_has_vl_args_returns); } if (const auto *FPT = NewFD->getType()->getAs<FunctionProtoType>()) { FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); diff --git a/clang/test/Sema/aarch64-incompat-sm-builtin-calls.c b/clang/test/Sema/aarch64-incompat-sm-builtin-calls.c index 83f61523927bc3..6002e9f25e2736 100644 --- a/clang/test/Sema/aarch64-incompat-sm-builtin-calls.c +++ b/clang/test/Sema/aarch64-incompat-sm-builtin-calls.c @@ -33,8 +33,8 @@ svuint32_t incompat_sve_sm(svbool_t pg, svuint32_t a, int16_t b) __arm_streaming return __builtin_sve_svld1_gather_u32base_index_u32(pg, a, b); } -// expected-warning@+2 {{non-streaming callee receives a VL-dependent argument and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} -// expected-warning@+1 {{non-streaming callee returns a VL-dependent value and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} +// expected-warning@+2 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, is undefined behaviour}} +// expected-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, is undefined behaviour}} __arm_locally_streaming svuint32_t incompat_sve_ls(svbool_t pg, svuint32_t a, int64_t b) { // expected-warning@+1 {{builtin call has undefined behaviour when called from a streaming function}} return __builtin_sve_svld1_gather_u32base_index_u32(pg, a, b); @@ -50,8 +50,8 @@ svuint32_t incompat_sve2_sm(svbool_t pg, svuint32_t a, int64_t b) __arm_streamin return __builtin_sve_svldnt1_gather_u32base_index_u32(pg, a, b); } -// expected-warning@+2 {{non-streaming callee receives a VL-dependent argument and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} -// expected-warning@+1 {{non-streaming callee returns a VL-dependent value and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} +// expected-warning@+2 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, is undefined behaviour}} +// expected-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, is undefined behaviour}} __arm_locally_streaming svuint32_t incompat_sve2_ls(svbool_t pg, svuint32_t a, int64_t b) { // expected-warning@+1 {{builtin call has undefined behaviour when called from a streaming function}} return __builtin_sve_svldnt1_gather_u32base_index_u32(pg, a, b); @@ -72,8 +72,8 @@ svfloat64_t streaming_caller_sve(svbool_t pg, svfloat64_t a, float64_t b) __arm_ return svadd_n_f64_m(pg, a, b); } -// expected-warning@+2 {{non-streaming callee receives a VL-dependent argument and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} -// expected-warning@+1 {{non-streaming callee returns a VL-dependent value and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} +// expected-warning@+2 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, is undefined behaviour}} +// expected-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, is undefined behaviour}} __arm_locally_streaming svfloat64_t locally_streaming_caller_sve(svbool_t pg, svfloat64_t a, float64_t b) { // expected-no-warning return svadd_n_f64_m(pg, a, b); @@ -89,8 +89,8 @@ svint16_t streaming_caller_sve2(svint16_t op1, svint16_t op2) __arm_streaming { return svmul_lane_s16(op1, op2, 0); } -// expected-warning@+2 {{non-streaming callee receives a VL-dependent argument and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} -// expected-warning@+1 {{non-streaming callee returns a VL-dependent value and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} +// expected-warning@+2 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, is undefined behaviour}} +// expected-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, is undefined behaviour}} __arm_locally_streaming svint16_t locally_streaming_caller_sve2(svint16_t op1, svint16_t op2) { // expected-no-warning return svmul_lane_s16(op1, op2, 0); diff --git a/clang/test/Sema/aarch64-sme-func-attrs.c b/clang/test/Sema/aarch64-sme-func-attrs.c index f54cad2eee967b..83c5776b93d170 100644 --- a/clang/test/Sema/aarch64-sme-func-attrs.c +++ b/clang/test/Sema/aarch64-sme-func-attrs.c @@ -453,49 +453,92 @@ void sme_streaming_with_vl_arg(__SVInt8_t a) __arm_streaming { } __SVInt8_t sme_streaming_returns_vl(void) __arm_streaming { __SVInt8_t r; return r; } -void sme_none_streaming_with_vl_arg(__SVInt8_t a) { } +void sme_streaming_compatible_with_vl_arg(__SVInt8_t a) __arm_streaming_compatible { } -__SVInt8_t sme_none_streaming_returns_vl(void) { __SVInt8_t r; return r; } +__SVInt8_t sme_streaming_compatible_returns_vl(void) __arm_streaming_compatible { __SVInt8_t r; return r; } -// expected-warning@+2 {{non-streaming callee receives a VL-dependent argument and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} - // expected-cpp-warning@+1 {{non-streaming callee receives a VL-dependent argument and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} +void sme_no_streaming_with_vl_arg(__SVInt8_t a) { } + +__SVInt8_t sme_no_streaming_returns_vl(void) { __SVInt8_t r; return r; } + +// expected-warning@+2 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, is undefined behaviour}} +// expected-cpp-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, is undefined behaviour}} __arm_locally_streaming void sme_locally_streaming_with_vl_arg(__SVInt8_t a) { } -// expected-warning@+2 {{non-streaming callee returns a VL-dependent value and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} -// expected-cpp-warning@+1 {{non-streaming callee returns a VL-dependent value and the callee has an arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} +// expected-warning@+2 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, is undefined behaviour}} +// expected-cpp-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, is undefined behaviour}} __arm_locally_streaming __SVInt8_t sme_locally_streaming_returns_vl(void) { __SVInt8_t r; return r; } -void sme_none_streaming_calling_streaming_with_vl_args() { +void sme_no_streaming_calling_streaming_with_vl_args() { __SVInt8_t a; - // expected-warning@+2 {{non-streaming caller passes a VL-dependent argument to streaming callee, the streaming and non-streaming vector lengths may be different}} - // expected-cpp-warning@+1 {{non-streaming caller passes a VL-dependent argument to streaming callee, the streaming and non-streaming vector lengths may be different}} + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} sme_streaming_with_vl_arg(a); } -void sme_none_streaming_calling_streaming_with_return_vl() { - // expected-warning@+2 {{non-streaming callee returns a VL-dependent value to streaming caller, the streaming and non-streaming vector lengths may be different}} - // expected-cpp-warning@+1 {{non-streaming callee returns a VL-dependent value to streaming caller, the streaming and non-streaming vector lengths may be different}} +void sme_no_streaming_calling_streaming_with_return_vl() { + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} __SVInt8_t r = sme_streaming_returns_vl(); } void sme_streaming_calling_non_streaming_with_vl_args(void) __arm_streaming { __SVInt8_t a; - // expected-warning@+2 {{streaming caller passes a VL-dependent argument to non-streaming callee, the streaming and non-streaming vector lengths may be different}} - // expected-cpp-warning@+1 {{streaming caller passes a VL-dependent argument to non-streaming callee, the streaming and non-streaming vector lengths may be different}} - sme_none_streaming_with_vl_arg(a); + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} + sme_no_streaming_with_vl_arg(a); } void sme_streaming_calling_non_streaming_with_return_vl(void) __arm_streaming { - // expected-warning@+2 {{non-streaming callee returns a VL-dependent value to streaming caller, the streaming and non-streaming vector lengths may be different}} - // expected-cpp-warning@+1 {{non-streaming callee returns a VL-dependent value to streaming caller, the streaming and non-streaming vector lengths may be different}} - __SVInt8_t r = sme_none_streaming_returns_vl(); + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} + __SVInt8_t r = sme_no_streaming_returns_vl(); } -void sme_streaming_calling_streaming_with_vl_args(void) __arm_streaming { - __SVInt8_t a; +void sme_no_streaming_calling_streaming(__SVInt8_t arg, void (*sc)( __SVInt8_t arg) __arm_streaming) { + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} + sc(arg); +} + +__SVInt8_t sme_no_streaming_calling_streaming_return_vl(__SVInt8_t (*sc)(void) __arm_streaming) { + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} + return sc(); +} + +void sme_streaming_compatible_calling_streaming(__SVInt8_t arg) __arm_streaming_compatible { + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} + sme_streaming_with_vl_arg(arg); +} + +void sme_streaming_compatible_sme_streaming_compatible_return_vl(void) __arm_streaming_compatible { + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} + __SVInt8_t r = sme_streaming_returns_vl(); +} + +void sme_streaming_calling_streaming(__SVInt8_t arg, void (*sc)( __SVInt8_t arg) __arm_streaming) __arm_streaming { + sc(arg); +} + +__SVInt8_t sme_streaming_calling_streaming_return_vl(__SVInt8_t (*sc)(void) __arm_streaming) __arm_streaming { + return sc(); +} + +void sme_streaming_calling_streaming_with_vl_args(__SVInt8_t a) __arm_streaming { sme_streaming_with_vl_arg(a); } void sme_streaming_calling_streaming_with_return_vl(void) __arm_streaming { __SVInt8_t r = sme_streaming_returns_vl(); } + +void sme_streaming_calling_streaming_compatible_with_vl_args(__SVInt8_t a) __arm_streaming { + sme_streaming_compatible_with_vl_arg(a); +} + +void sme_streaming_calling_streaming_compatible_with_return_vl(void) __arm_streaming { + __SVInt8_t r = sme_streaming_compatible_returns_vl(); +} >From 1827ad66a1e4d40542d3a22dc3eb981a6ad1cd2a Mon Sep 17 00:00:00 2001 From: Dinar Temirbulatov <dinar.temirbula...@arm.com> Date: Thu, 15 Feb 2024 11:51:54 +0000 Subject: [PATCH 6/8] Resolve comments. --- .../clang/Basic/DiagnosticSemaKinds.td | 6 +- clang/lib/Sema/SemaChecking.cpp | 49 +++++----- clang/lib/Sema/SemaDecl.cpp | 16 +--- .../Sema/aarch64-incompat-sm-builtin-calls.c | 12 +-- clang/test/Sema/aarch64-sme-func-attrs.c | 96 +++++++++++++------ 5 files changed, 101 insertions(+), 78 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index a94692166f6460..b60b5a6d379bc7 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3719,11 +3719,13 @@ def err_sme_definition_using_zt0_in_non_sme2_target : Error< "function using ZT0 state requires 'sme2'">; def warn_sme_streaming_pass_return_vl_to_non_streaming : Warning< "passing a VL-dependent argument to/from a function that has a different" - " streaming-mode, is undefined behaviour">, + " streaming-mode, the streaming and non-streaming vector lengths may be" + " different">, InGroup<AArch64SMEAttributes>; def warn_sme_locally_streaming_has_vl_args_returns : Warning< "passing/returning a VL-dependent argument from a function" - " arm_locally_streaming attribute, is undefined behaviour">, + " arm_locally_streaming attribute, the streaming and non-streaming vector" + " lengths may be different">, InGroup<AArch64SMEAttributes>; def err_conflicting_attributes_arm_state : Error< "conflicting attributes for state '%0'">; diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 95ac69d9ea90fd..7b501fc1f289bc 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -7480,7 +7480,7 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, // For variadic functions, we may have more args than parameters. // For some K&R functions, we may have less args than parameters. const auto N = std::min<unsigned>(Proto->getNumParams(), Args.size()); - bool AnyScalableArgs = false; + bool AnyScalableArgsOrRet = false; for (unsigned ArgIdx = 0; ArgIdx < N; ++ArgIdx) { // Args[ArgIdx] can be null in malformed code. if (const Expr *Arg = Args[ArgIdx]) { @@ -7495,7 +7495,7 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, QualType ParamTy = Proto->getParamType(ArgIdx); if (ParamTy->isSizelessVectorType()) - AnyScalableArgs = true; + AnyScalableArgsOrRet = true; QualType ArgTy = Arg->getType(); CheckArgAlignment(Arg->getExprLoc(), FDecl, std::to_string(ArgIdx + 1), ArgTy, ParamTy); @@ -7517,36 +7517,31 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, } auto *CallerFD = dyn_cast<FunctionDecl>(CurContext); - bool IsCalleeStreaming = ((ExtInfo.AArch64SMEAttributes & - FunctionType::SME_PStateSMEnabledMask) || - (ExtInfo.AArch64SMEAttributes & - FunctionType::SME_PStateSMCompatibleMask)); + bool IsCalleeStreaming = + (ExtInfo.AArch64SMEAttributes & FunctionType::SME_PStateSMEnabledMask); + bool IsCalleeStreamingCompatible = + (ExtInfo.AArch64SMEAttributes & + FunctionType::SME_PStateSMCompatibleMask); bool IsBuiltin = (FD && FD->getBuiltinID()); + AnyScalableArgsOrRet |= Proto->getReturnType()->isSizelessVectorType(); + // If the caller is a function and the callee has a different + // non-compitable streaming attribute. If it passed any VL-based arguments + // or return VL-based value, then warn that the streaming and non-streaming + // vector lengths may be different. if (CallerFD && Context.getTargetInfo().hasFeature("sme") && !IsBuiltin) { - // If the callee has an AArch64 SME __arm_locally_streaming attribute - // warn if this function returns VL-based value or pass any such argument, - // the streaming and non-streaming vector lengths may be different. ArmStreamingType CallerFnType = getArmStreamingFnType(CallerFD); - // If the caller is a non-streaming function and the callee has a - // streaming attribute. If it passed any VL-based arguments or return - // VL-based value, then warn that the streaming and non-streaming vector - // lengths may be different. - if (CallerFnType != ArmStreaming) { - if (IsCalleeStreaming) { - if (AnyScalableArgs) - Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming); - if (Proto->getReturnType()->isSizelessVectorType()) - Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming); - } - } else if (!IsCalleeStreaming) { - // If the callee is a non-streaming function and the caller has - // streaming attribute. If it passed any VL-based arguments or return - // VL-based value, then warn that the streaming and non-streaming vector - // lengths may be different. - if (AnyScalableArgs) + if (CallerFnType != ArmStreaming && + CallerFnType != ArmStreamingCompatible) { + if (IsCalleeStreaming && AnyScalableArgsOrRet) + Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming); + } else if (CallerFnType == ArmStreaming && !IsCalleeStreaming && + !IsCalleeStreamingCompatible) { + if (AnyScalableArgsOrRet) Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming); - if (Proto->getReturnType()->isSizelessVectorType()) + } else if (CallerFnType == ArmStreamingCompatible) { + if ((IsCalleeStreaming || !IsCalleeStreamingCompatible) && + AnyScalableArgsOrRet) Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming); } } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 355f464aa8f3f4..411616ff715544 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -12238,18 +12238,10 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, bool UsesZT0 = Attr && Attr->isNewZT0(); if (UsesSM) { - if (NewFD->getReturnType()->isSizelessVectorType()) - Diag(NewFD->getLocation(), - diag::warn_sme_locally_streaming_has_vl_args_returns); - auto *FPT = NewFD->getType()->castAs<FunctionProtoType>(); - bool AnyScalableArgs = false; - for (QualType T : FPT->param_types()) { - if (T->isSizelessVectorType()) { - AnyScalableArgs = true; - break; - } - } - if (AnyScalableArgs) + if (NewFD->getReturnType()->isSizelessVectorType() || + llvm::any_of(NewFD->parameters(), [](ParmVarDecl *P) { + return P->getOriginalType()->isSizelessVectorType(); + })) Diag(NewFD->getLocation(), diag::warn_sme_locally_streaming_has_vl_args_returns); } diff --git a/clang/test/Sema/aarch64-incompat-sm-builtin-calls.c b/clang/test/Sema/aarch64-incompat-sm-builtin-calls.c index 6002e9f25e2736..52ca11b3147c9c 100644 --- a/clang/test/Sema/aarch64-incompat-sm-builtin-calls.c +++ b/clang/test/Sema/aarch64-incompat-sm-builtin-calls.c @@ -33,8 +33,7 @@ svuint32_t incompat_sve_sm(svbool_t pg, svuint32_t a, int16_t b) __arm_streaming return __builtin_sve_svld1_gather_u32base_index_u32(pg, a, b); } -// expected-warning@+2 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, is undefined behaviour}} -// expected-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, is undefined behaviour}} +// expected-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} __arm_locally_streaming svuint32_t incompat_sve_ls(svbool_t pg, svuint32_t a, int64_t b) { // expected-warning@+1 {{builtin call has undefined behaviour when called from a streaming function}} return __builtin_sve_svld1_gather_u32base_index_u32(pg, a, b); @@ -50,8 +49,7 @@ svuint32_t incompat_sve2_sm(svbool_t pg, svuint32_t a, int64_t b) __arm_streamin return __builtin_sve_svldnt1_gather_u32base_index_u32(pg, a, b); } -// expected-warning@+2 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, is undefined behaviour}} -// expected-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, is undefined behaviour}} +// expected-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} __arm_locally_streaming svuint32_t incompat_sve2_ls(svbool_t pg, svuint32_t a, int64_t b) { // expected-warning@+1 {{builtin call has undefined behaviour when called from a streaming function}} return __builtin_sve_svldnt1_gather_u32base_index_u32(pg, a, b); @@ -72,8 +70,7 @@ svfloat64_t streaming_caller_sve(svbool_t pg, svfloat64_t a, float64_t b) __arm_ return svadd_n_f64_m(pg, a, b); } -// expected-warning@+2 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, is undefined behaviour}} -// expected-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, is undefined behaviour}} +// expected-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} __arm_locally_streaming svfloat64_t locally_streaming_caller_sve(svbool_t pg, svfloat64_t a, float64_t b) { // expected-no-warning return svadd_n_f64_m(pg, a, b); @@ -89,8 +86,7 @@ svint16_t streaming_caller_sve2(svint16_t op1, svint16_t op2) __arm_streaming { return svmul_lane_s16(op1, op2, 0); } -// expected-warning@+2 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, is undefined behaviour}} -// expected-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, is undefined behaviour}} +// expected-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} __arm_locally_streaming svint16_t locally_streaming_caller_sve2(svint16_t op1, svint16_t op2) { // expected-no-warning return svmul_lane_s16(op1, op2, 0); diff --git a/clang/test/Sema/aarch64-sme-func-attrs.c b/clang/test/Sema/aarch64-sme-func-attrs.c index 83c5776b93d170..88529fe7ef969d 100644 --- a/clang/test/Sema/aarch64-sme-func-attrs.c +++ b/clang/test/Sema/aarch64-sme-func-attrs.c @@ -461,70 +461,82 @@ void sme_no_streaming_with_vl_arg(__SVInt8_t a) { } __SVInt8_t sme_no_streaming_returns_vl(void) { __SVInt8_t r; return r; } -// expected-warning@+2 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, is undefined behaviour}} -// expected-cpp-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, is undefined behaviour}} +// expected-warning@+2 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} +// expected-cpp-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} __arm_locally_streaming void sme_locally_streaming_with_vl_arg(__SVInt8_t a) { } -// expected-warning@+2 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, is undefined behaviour}} -// expected-cpp-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, is undefined behaviour}} +// expected-warning@+2 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} +// expected-cpp-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} __arm_locally_streaming __SVInt8_t sme_locally_streaming_returns_vl(void) { __SVInt8_t r; return r; } void sme_no_streaming_calling_streaming_with_vl_args() { __SVInt8_t a; - // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} - // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} sme_streaming_with_vl_arg(a); } void sme_no_streaming_calling_streaming_with_return_vl() { - // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} - // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} __SVInt8_t r = sme_streaming_returns_vl(); } void sme_streaming_calling_non_streaming_with_vl_args(void) __arm_streaming { __SVInt8_t a; - // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} - // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} sme_no_streaming_with_vl_arg(a); } void sme_streaming_calling_non_streaming_with_return_vl(void) __arm_streaming { - // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} - // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} __SVInt8_t r = sme_no_streaming_returns_vl(); } -void sme_no_streaming_calling_streaming(__SVInt8_t arg, void (*sc)( __SVInt8_t arg) __arm_streaming) { - // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} - // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} +void sme_no_streaming_calling_streaming_with_vl_args_param(__SVInt8_t arg, void (*sc)( __SVInt8_t arg) __arm_streaming) { + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} sc(arg); } -__SVInt8_t sme_no_streaming_calling_streaming_return_vl(__SVInt8_t (*sc)(void) __arm_streaming) { - // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} - // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} - return sc(); +__SVInt8_t sme_no_streaming_calling_streaming_return_vl_param(__SVInt8_t (*s)(void) __arm_streaming) { + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} + return s(); } -void sme_streaming_compatible_calling_streaming(__SVInt8_t arg) __arm_streaming_compatible { - // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} - // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} +void sme_streaming_compatible_calling_streaming_with_vl_args(__SVInt8_t arg) __arm_streaming_compatible { + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} sme_streaming_with_vl_arg(arg); } -void sme_streaming_compatible_sme_streaming_compatible_return_vl(void) __arm_streaming_compatible { - // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} - // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, is undefined behaviour}} +void sme_streaming_compatible_calling_sme_streaming_return_vl(void) __arm_streaming_compatible { + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} __SVInt8_t r = sme_streaming_returns_vl(); } -void sme_streaming_calling_streaming(__SVInt8_t arg, void (*sc)( __SVInt8_t arg) __arm_streaming) __arm_streaming { - sc(arg); +void sme_streaming_compatible_calling_no_streaming_with_vl_args(__SVInt8_t arg) __arm_streaming_compatible { + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} + sme_no_streaming_with_vl_arg(arg); +} + +void sme_streaming_compatible_calling_no_sme_streaming_return_vl(void) __arm_streaming_compatible { + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} + __SVInt8_t r = sme_no_streaming_returns_vl(); } -__SVInt8_t sme_streaming_calling_streaming_return_vl(__SVInt8_t (*sc)(void) __arm_streaming) __arm_streaming { - return sc(); +void sme_streaming_calling_streaming(__SVInt8_t arg, void (*s)( __SVInt8_t arg) __arm_streaming) __arm_streaming { + s(arg); +} + +__SVInt8_t sme_streaming_calling_streaming_return_vl(__SVInt8_t (*s)(void) __arm_streaming) __arm_streaming { + return s(); } void sme_streaming_calling_streaming_with_vl_args(__SVInt8_t a) __arm_streaming { @@ -542,3 +554,29 @@ void sme_streaming_calling_streaming_compatible_with_vl_args(__SVInt8_t a) __arm void sme_streaming_calling_streaming_compatible_with_return_vl(void) __arm_streaming { __SVInt8_t r = sme_streaming_compatible_returns_vl(); } + +void sme_no_streaming_calling_streaming_compatible_with_vl_args() { + __SVInt8_t a; + sme_streaming_compatible_with_vl_arg(a); +} + +void sme_no_streaming_calling_streaming_compatible_with_return_vl() { + __SVInt8_t r = sme_streaming_compatible_returns_vl(); +} + +void sme_no_streaming_calling_non_streaming_compatible_with_vl_args() { + __SVInt8_t a; + sme_no_streaming_with_vl_arg(a); +} + +void sme_no_streaming_calling_non_streaming_compatible_with_return_vl() { + __SVInt8_t r = sme_no_streaming_returns_vl(); +} + +void sme_streaming_compatible_calling_streaming_compatible_with_vl_args(__SVInt8_t arg) __arm_streaming_compatible { + sme_streaming_compatible_with_vl_arg(arg); +} + +void sme_streaming_compatible_calling_streaming_compatible_with_return_vl(void) __arm_streaming_compatible { + __SVInt8_t r = sme_streaming_compatible_returns_vl(); +} >From e2a82ee38fab05ca12c416f3d37d2fad275a069a Mon Sep 17 00:00:00 2001 From: Dinar Temirbulatov <dinar.temirbula...@arm.com> Date: Thu, 15 Feb 2024 12:16:31 +0000 Subject: [PATCH 7/8] Updated comment in clang/lib/Sema/SemaDecl.cpp --- clang/lib/Sema/SemaDecl.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 411616ff715544..55152f3aca7f07 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -12230,7 +12230,8 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, } // Check if the function definition uses any AArch64 SME features without - // having the '+sme' feature enabled. + // having the '+sme' feature enabled and warn user if sme locally streaming + // function returns or uses arguments with VL-based types. if (DeclIsDefn) { const auto *Attr = NewFD->getAttr<ArmNewAttr>(); bool UsesSM = NewFD->hasAttr<ArmLocallyStreamingAttr>(); >From 3c5df4f66bbf4ef7584545cc91e45d679344315b Mon Sep 17 00:00:00 2001 From: Dinar Temirbulatov <dinar.temirbula...@arm.com> Date: Mon, 4 Mar 2024 13:36:26 +0000 Subject: [PATCH 8/8] Resolve comments. --- .../clang/Basic/DiagnosticSemaKinds.td | 4 +- clang/lib/Sema/SemaChecking.cpp | 22 ++++----- clang/lib/Sema/SemaDecl.cpp | 2 +- .../Sema/aarch64-incompat-sm-builtin-calls.c | 8 ++-- clang/test/Sema/aarch64-sme-func-attrs.c | 48 +++++++++---------- 5 files changed, 40 insertions(+), 44 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index b60b5a6d379bc7..b93c004157a403 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3719,12 +3719,12 @@ def err_sme_definition_using_zt0_in_non_sme2_target : Error< "function using ZT0 state requires 'sme2'">; def warn_sme_streaming_pass_return_vl_to_non_streaming : Warning< "passing a VL-dependent argument to/from a function that has a different" - " streaming-mode, the streaming and non-streaming vector lengths may be" + " streaming-mode. The streaming and non-streaming vector lengths may be" " different">, InGroup<AArch64SMEAttributes>; def warn_sme_locally_streaming_has_vl_args_returns : Warning< "passing/returning a VL-dependent argument from a function" - " arm_locally_streaming attribute, the streaming and non-streaming vector" + " arm_locally_streaming attribute. The streaming and non-streaming vector" " lengths may be different">, InGroup<AArch64SMEAttributes>; def err_conflicting_attributes_arm_state : Error< diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 7b501fc1f289bc..b41db76a2057bf 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -7531,19 +7531,15 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, // vector lengths may be different. if (CallerFD && Context.getTargetInfo().hasFeature("sme") && !IsBuiltin) { ArmStreamingType CallerFnType = getArmStreamingFnType(CallerFD); - if (CallerFnType != ArmStreaming && - CallerFnType != ArmStreamingCompatible) { - if (IsCalleeStreaming && AnyScalableArgsOrRet) - Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming); - } else if (CallerFnType == ArmStreaming && !IsCalleeStreaming && - !IsCalleeStreamingCompatible) { - if (AnyScalableArgsOrRet) - Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming); - } else if (CallerFnType == ArmStreamingCompatible) { - if ((IsCalleeStreaming || !IsCalleeStreamingCompatible) && - AnyScalableArgsOrRet) - Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming); - } + if ((CallerFnType != ArmStreaming && + CallerFnType != ArmStreamingCompatible && IsCalleeStreaming && + AnyScalableArgsOrRet) || + (CallerFnType == ArmStreaming && !IsCalleeStreaming && + !IsCalleeStreamingCompatible && AnyScalableArgsOrRet) || + (CallerFnType == ArmStreamingCompatible && + (IsCalleeStreaming || !IsCalleeStreamingCompatible) && + AnyScalableArgsOrRet)) + Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming); } // If the callee uses AArch64 SME ZA state but the caller doesn't define diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 55152f3aca7f07..c19922d3b19561 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -12238,7 +12238,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, bool UsesZA = Attr && Attr->isNewZA(); bool UsesZT0 = Attr && Attr->isNewZT0(); - if (UsesSM) { + if (NewFD->hasAttr<ArmLocallyStreamingAttr>()) { if (NewFD->getReturnType()->isSizelessVectorType() || llvm::any_of(NewFD->parameters(), [](ParmVarDecl *P) { return P->getOriginalType()->isSizelessVectorType(); diff --git a/clang/test/Sema/aarch64-incompat-sm-builtin-calls.c b/clang/test/Sema/aarch64-incompat-sm-builtin-calls.c index 52ca11b3147c9c..663813dfc7d930 100644 --- a/clang/test/Sema/aarch64-incompat-sm-builtin-calls.c +++ b/clang/test/Sema/aarch64-incompat-sm-builtin-calls.c @@ -33,7 +33,7 @@ svuint32_t incompat_sve_sm(svbool_t pg, svuint32_t a, int16_t b) __arm_streaming return __builtin_sve_svld1_gather_u32base_index_u32(pg, a, b); } -// expected-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} +// expected-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute. The streaming and non-streaming vector lengths may be different}} __arm_locally_streaming svuint32_t incompat_sve_ls(svbool_t pg, svuint32_t a, int64_t b) { // expected-warning@+1 {{builtin call has undefined behaviour when called from a streaming function}} return __builtin_sve_svld1_gather_u32base_index_u32(pg, a, b); @@ -49,7 +49,7 @@ svuint32_t incompat_sve2_sm(svbool_t pg, svuint32_t a, int64_t b) __arm_streamin return __builtin_sve_svldnt1_gather_u32base_index_u32(pg, a, b); } -// expected-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} +// expected-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute. The streaming and non-streaming vector lengths may be different}} __arm_locally_streaming svuint32_t incompat_sve2_ls(svbool_t pg, svuint32_t a, int64_t b) { // expected-warning@+1 {{builtin call has undefined behaviour when called from a streaming function}} return __builtin_sve_svldnt1_gather_u32base_index_u32(pg, a, b); @@ -70,7 +70,7 @@ svfloat64_t streaming_caller_sve(svbool_t pg, svfloat64_t a, float64_t b) __arm_ return svadd_n_f64_m(pg, a, b); } -// expected-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} +// expected-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute. The streaming and non-streaming vector lengths may be different}} __arm_locally_streaming svfloat64_t locally_streaming_caller_sve(svbool_t pg, svfloat64_t a, float64_t b) { // expected-no-warning return svadd_n_f64_m(pg, a, b); @@ -86,7 +86,7 @@ svint16_t streaming_caller_sve2(svint16_t op1, svint16_t op2) __arm_streaming { return svmul_lane_s16(op1, op2, 0); } -// expected-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} +// expected-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute. The streaming and non-streaming vector lengths may be different}} __arm_locally_streaming svint16_t locally_streaming_caller_sve2(svint16_t op1, svint16_t op2) { // expected-no-warning return svmul_lane_s16(op1, op2, 0); diff --git a/clang/test/Sema/aarch64-sme-func-attrs.c b/clang/test/Sema/aarch64-sme-func-attrs.c index 88529fe7ef969d..6f74ac5090ff90 100644 --- a/clang/test/Sema/aarch64-sme-func-attrs.c +++ b/clang/test/Sema/aarch64-sme-func-attrs.c @@ -461,73 +461,73 @@ void sme_no_streaming_with_vl_arg(__SVInt8_t a) { } __SVInt8_t sme_no_streaming_returns_vl(void) { __SVInt8_t r; return r; } -// expected-warning@+2 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} -// expected-cpp-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} +// expected-warning@+2 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute. The streaming and non-streaming vector lengths may be different}} +// expected-cpp-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute. The streaming and non-streaming vector lengths may be different}} __arm_locally_streaming void sme_locally_streaming_with_vl_arg(__SVInt8_t a) { } -// expected-warning@+2 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} -// expected-cpp-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute, the streaming and non-streaming vector lengths may be different}} +// expected-warning@+2 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute. The streaming and non-streaming vector lengths may be different}} +// expected-cpp-warning@+1 {{passing/returning a VL-dependent argument from a function arm_locally_streaming attribute. The streaming and non-streaming vector lengths may be different}} __arm_locally_streaming __SVInt8_t sme_locally_streaming_returns_vl(void) { __SVInt8_t r; return r; } void sme_no_streaming_calling_streaming_with_vl_args() { __SVInt8_t a; - // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} - // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} sme_streaming_with_vl_arg(a); } void sme_no_streaming_calling_streaming_with_return_vl() { - // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} - // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} __SVInt8_t r = sme_streaming_returns_vl(); } void sme_streaming_calling_non_streaming_with_vl_args(void) __arm_streaming { __SVInt8_t a; - // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} - // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} sme_no_streaming_with_vl_arg(a); } void sme_streaming_calling_non_streaming_with_return_vl(void) __arm_streaming { - // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} - // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} __SVInt8_t r = sme_no_streaming_returns_vl(); } void sme_no_streaming_calling_streaming_with_vl_args_param(__SVInt8_t arg, void (*sc)( __SVInt8_t arg) __arm_streaming) { - // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} - // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} sc(arg); } __SVInt8_t sme_no_streaming_calling_streaming_return_vl_param(__SVInt8_t (*s)(void) __arm_streaming) { - // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} - // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} return s(); } void sme_streaming_compatible_calling_streaming_with_vl_args(__SVInt8_t arg) __arm_streaming_compatible { - // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} - // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} sme_streaming_with_vl_arg(arg); } void sme_streaming_compatible_calling_sme_streaming_return_vl(void) __arm_streaming_compatible { - // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} - // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} __SVInt8_t r = sme_streaming_returns_vl(); } void sme_streaming_compatible_calling_no_streaming_with_vl_args(__SVInt8_t arg) __arm_streaming_compatible { - // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} - // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} sme_no_streaming_with_vl_arg(arg); } void sme_streaming_compatible_calling_no_sme_streaming_return_vl(void) __arm_streaming_compatible { - // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} - // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode, the streaming and non-streaming vector lengths may be different}} + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} __SVInt8_t r = sme_no_streaming_returns_vl(); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits