https://github.com/SamTebbs33 updated https://github.com/llvm/llvm-project/pull/77936
>From 7314429a203900a8f555e1b0471fdd4cfd4d8d03 Mon Sep 17 00:00:00 2001 From: Samuel Tebbs <samuel.te...@arm.com> Date: Wed, 10 Jan 2024 14:57:04 +0000 Subject: [PATCH 01/18] [Clang][SME] Detect always_inline used with mismatched streaming attributes This patch adds an error that is emitted when a streaming function is marked as always_inline and is called from a non-streaming function. --- .../clang/Basic/DiagnosticFrontendKinds.td | 2 ++ clang/include/clang/Sema/Sema.h | 9 +++++++ clang/lib/CodeGen/CMakeLists.txt | 1 + clang/lib/CodeGen/Targets/AArch64.cpp | 20 ++++++++++++++ clang/lib/Sema/SemaChecking.cpp | 27 +++++++------------ ...-sme-func-attrs-inline-locally-streaming.c | 12 +++++++++ .../aarch64-sme-func-attrs-inline-streaming.c | 12 +++++++++ 7 files changed, 66 insertions(+), 17 deletions(-) create mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline-locally-streaming.c create mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline-streaming.c diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td index 85ecfdf9de62d4..2d0f971858840d 100644 --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -279,6 +279,8 @@ def err_builtin_needs_feature : Error<"%0 needs target feature %1">; def err_function_needs_feature : Error< "always_inline function %1 requires target feature '%2', but would " "be inlined into function %0 that is compiled without support for '%2'">; +def err_function_alwaysinline_attribute_mismatch : Error< + "always_inline function %1 and its caller %0 have mismatched %2 attributes">; def warn_avx_calling_convention : Warning<"AVX vector %select{return|argument}0 of type %1 without '%2' " diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 6ce422d66ae5b0..dd75b5aad3d9c8 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -13832,8 +13832,17 @@ class Sema final { FormatArgumentPassingKind ArgPassingKind; }; +enum ArmStreamingType { + ArmNonStreaming, + ArmStreaming, + ArmStreamingCompatible, + ArmStreamingOrSVE2p1 +}; + + static bool getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember, bool IsVariadic, FormatStringInfo *FSI); + static ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD); private: void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt index 52216d93a302bb..03a6f2f1d7a9d2 100644 --- a/clang/lib/CodeGen/CMakeLists.txt +++ b/clang/lib/CodeGen/CMakeLists.txt @@ -151,4 +151,5 @@ add_clang_library(clangCodeGen clangFrontend clangLex clangSerialization + clangSema ) diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp index ee7f95084d2e0b..4018f91422e358 100644 --- a/clang/lib/CodeGen/Targets/AArch64.cpp +++ b/clang/lib/CodeGen/Targets/AArch64.cpp @@ -8,6 +8,8 @@ #include "ABIInfoImpl.h" #include "TargetInfo.h" +#include "clang/Basic/DiagnosticFrontend.h" +#include "clang/Sema/Sema.h" using namespace clang; using namespace clang::CodeGen; @@ -155,6 +157,11 @@ class AArch64TargetCodeGenInfo : public TargetCodeGenInfo { } return TargetCodeGenInfo::isScalarizableAsmOperand(CGF, Ty); } + + void checkFunctionCallABI(CodeGenModule &CGM, SourceLocation CallLoc, + const FunctionDecl *Caller, + const FunctionDecl *Callee, + const CallArgList &Args) const override; }; class WindowsAArch64TargetCodeGenInfo : public AArch64TargetCodeGenInfo { @@ -814,6 +821,19 @@ Address AArch64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr, /*allowHigherAlign*/ false); } +void AArch64TargetCodeGenInfo::checkFunctionCallABI( + CodeGenModule &CGM, SourceLocation CallLoc, const FunctionDecl *Caller, + const FunctionDecl *Callee, const CallArgList &Args) const { + if (!Callee->hasAttr<AlwaysInlineAttr>()) + return; + + auto CalleeIsStreaming = Sema::getArmStreamingFnType(Callee) == Sema::ArmStreaming; + auto CallerIsStreaming = Sema::getArmStreamingFnType(Caller) == Sema::ArmStreaming; + + if (CalleeIsStreaming && !CallerIsStreaming) + CGM.getDiags().Report(CallLoc, diag::err_function_alwaysinline_attribute_mismatch) << Caller->getDeclName() << Callee->getDeclName() << "streaming"; +} + std::unique_ptr<TargetCodeGenInfo> CodeGen::createAArch64TargetCodeGenInfo(CodeGenModule &CGM, AArch64ABIKind Kind) { diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index ace3e386988f00..a92db7d67e1cbd 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2998,13 +2998,6 @@ static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context, llvm_unreachable("Invalid NeonTypeFlag!"); } -enum ArmStreamingType { - ArmNonStreaming, - ArmStreaming, - ArmStreamingCompatible, - ArmStreamingOrSVE2p1 -}; - bool Sema::ParseSVEImmChecks( CallExpr *TheCall, SmallVector<std::tuple<int, int, int>, 3> &ImmChecks) { // Perform all the immediate checks for this builtin call. @@ -3145,7 +3138,7 @@ bool Sema::ParseSVEImmChecks( return HasError; } -static ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD) { +Sema::ArmStreamingType Sema::getArmStreamingFnType(const FunctionDecl *FD) { if (FD->hasAttr<ArmLocallyStreamingAttr>()) return ArmStreaming; if (const auto *T = FD->getType()->getAs<FunctionProtoType>()) { @@ -3159,31 +3152,31 @@ static ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD) { static void checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall, const FunctionDecl *FD, - ArmStreamingType BuiltinType) { - ArmStreamingType FnType = getArmStreamingFnType(FD); - if (BuiltinType == ArmStreamingOrSVE2p1) { + Sema::ArmStreamingType BuiltinType) { + Sema::ArmStreamingType FnType = Sema::getArmStreamingFnType(FD); + if (BuiltinType == Sema::ArmStreamingOrSVE2p1) { // Check intrinsics that are available in [sve2p1 or sme/sme2]. llvm::StringMap<bool> CallerFeatureMap; S.Context.getFunctionFeatureMap(CallerFeatureMap, FD); if (Builtin::evaluateRequiredTargetFeatures("sve2p1", CallerFeatureMap)) - BuiltinType = ArmStreamingCompatible; + BuiltinType = Sema::ArmStreamingCompatible; else - BuiltinType = ArmStreaming; + BuiltinType = Sema::ArmStreaming; } - if (FnType == ArmStreaming && BuiltinType == ArmNonStreaming) { + if (FnType == Sema::ArmStreaming && BuiltinType == Sema::ArmNonStreaming) { S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) << TheCall->getSourceRange() << "streaming"; } - if (FnType == ArmStreamingCompatible && - BuiltinType != ArmStreamingCompatible) { + if (FnType == Sema::ArmStreamingCompatible && + BuiltinType != Sema::ArmStreamingCompatible) { S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) << TheCall->getSourceRange() << "streaming compatible"; return; } - if (FnType == ArmNonStreaming && BuiltinType == ArmStreaming) { + if (FnType == Sema::ArmNonStreaming && BuiltinType == Sema::ArmStreaming) { S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) << TheCall->getSourceRange() << "non-streaming"; } diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline-locally-streaming.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline-locally-streaming.c new file mode 100644 index 00000000000000..4aa9fbf4a8fa18 --- /dev/null +++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline-locally-streaming.c @@ -0,0 +1,12 @@ +// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s + +// Conflicting attributes when using always_inline +__attribute__((always_inline)) __arm_locally_streaming +int inlined_fn_local(void) { + return 42; +} +// expected-error@+1 {{always_inline function 'inlined_fn_local' and its caller 'inlined_fn_caller' have mismatched streaming attributes}} +int inlined_fn_caller(void) { return inlined_fn_local(); } +__arm_locally_streaming +int inlined_fn_caller_local(void) { return inlined_fn_local(); } +int inlined_fn_caller_streaming(void) __arm_streaming { return inlined_fn_local(); } diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline-streaming.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline-streaming.c new file mode 100644 index 00000000000000..7268a49bb2491d --- /dev/null +++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline-streaming.c @@ -0,0 +1,12 @@ +// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s + +// Conflicting attributes when using always_inline +__attribute__((always_inline)) +int inlined_fn_streaming(void) __arm_streaming { + return 42; +} +// expected-error@+1 {{always_inline function 'inlined_fn_streaming' and its caller 'inlined_fn_caller' have mismatched streaming attributes}} +int inlined_fn_caller(void) { return inlined_fn_streaming(); } +__arm_locally_streaming +int inlined_fn_caller_local(void) { return inlined_fn_streaming(); } +int inlined_fn_caller_streaming(void) __arm_streaming { return inlined_fn_streaming(); } >From 04866d0c0be106a3d0296938f5e1b1d5f9e2591e Mon Sep 17 00:00:00 2001 From: Sam Tebbs <samuel.te...@arm.com> Date: Fri, 12 Jan 2024 15:13:28 +0000 Subject: [PATCH 02/18] fixup: formatting --- clang/include/clang/Sema/Sema.h | 13 ++++++------- clang/lib/CodeGen/Targets/AArch64.cpp | 16 ++++++++++------ 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index dd75b5aad3d9c8..1ee065e7de9b15 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -13832,13 +13832,12 @@ class Sema final { FormatArgumentPassingKind ArgPassingKind; }; -enum ArmStreamingType { - ArmNonStreaming, - ArmStreaming, - ArmStreamingCompatible, - ArmStreamingOrSVE2p1 -}; - + enum ArmStreamingType { + ArmNonStreaming, + ArmStreaming, + ArmStreamingCompatible, + ArmStreamingOrSVE2p1 + }; static bool getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember, bool IsVariadic, FormatStringInfo *FSI); diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp index 4018f91422e358..fe7b384c721d69 100644 --- a/clang/lib/CodeGen/Targets/AArch64.cpp +++ b/clang/lib/CodeGen/Targets/AArch64.cpp @@ -824,14 +824,18 @@ Address AArch64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr, void AArch64TargetCodeGenInfo::checkFunctionCallABI( CodeGenModule &CGM, SourceLocation CallLoc, const FunctionDecl *Caller, const FunctionDecl *Callee, const CallArgList &Args) const { - if (!Callee->hasAttr<AlwaysInlineAttr>()) - return; + if (!Callee->hasAttr<AlwaysInlineAttr>()) + return; - auto CalleeIsStreaming = Sema::getArmStreamingFnType(Callee) == Sema::ArmStreaming; - auto CallerIsStreaming = Sema::getArmStreamingFnType(Caller) == Sema::ArmStreaming; + auto CalleeIsStreaming = + Sema::getArmStreamingFnType(Callee) == Sema::ArmStreaming; + auto CallerIsStreaming = + Sema::getArmStreamingFnType(Caller) == Sema::ArmStreaming; - if (CalleeIsStreaming && !CallerIsStreaming) - CGM.getDiags().Report(CallLoc, diag::err_function_alwaysinline_attribute_mismatch) << Caller->getDeclName() << Callee->getDeclName() << "streaming"; + if (CalleeIsStreaming && !CallerIsStreaming) + CGM.getDiags().Report(CallLoc, + diag::err_function_alwaysinline_attribute_mismatch) + << Caller->getDeclName() << Callee->getDeclName() << "streaming"; } std::unique_ptr<TargetCodeGenInfo> >From 156c96bc9660472c17c666ff465613d7276e0db9 Mon Sep 17 00:00:00 2001 From: Sam Tebbs <samuel.te...@arm.com> Date: Mon, 15 Jan 2024 11:32:44 +0000 Subject: [PATCH 03/18] fixup: allow streaming compatible callee and check if modes are the same --- clang/lib/CodeGen/Targets/AArch64.cpp | 11 ++++++----- .../sme-inline-streaming-compatible-caller.c | 9 +++++++++ .../sme-inline-streaming-compatible.c | 17 +++++++++++++++++ .../sme-inline-streaming-locally.c} | 0 .../sme-inline-streaming.c} | 0 5 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c create mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c rename clang/test/CodeGen/{aarch64-sme-func-attrs-inline-locally-streaming.c => aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c} (100%) rename clang/test/CodeGen/{aarch64-sme-func-attrs-inline-streaming.c => aarch64-sme-func-attrs-inline/sme-inline-streaming.c} (100%) diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp index fe7b384c721d69..72f70c931fd9e6 100644 --- a/clang/lib/CodeGen/Targets/AArch64.cpp +++ b/clang/lib/CodeGen/Targets/AArch64.cpp @@ -827,12 +827,13 @@ void AArch64TargetCodeGenInfo::checkFunctionCallABI( if (!Callee->hasAttr<AlwaysInlineAttr>()) return; - auto CalleeIsStreaming = - Sema::getArmStreamingFnType(Callee) == Sema::ArmStreaming; - auto CallerIsStreaming = - Sema::getArmStreamingFnType(Caller) == Sema::ArmStreaming; + auto CalleeStreamingMode = Sema::getArmStreamingFnType(Callee); + auto CallerStreamingMode = Sema::getArmStreamingFnType(Caller); - if (CalleeIsStreaming && !CallerIsStreaming) + // The caller can inline the callee if their streaming modes match or the + // callee is streaming compatible + if (CalleeStreamingMode != CallerStreamingMode && + CalleeStreamingMode != Sema::ArmStreamingCompatible) CGM.getDiags().Report(CallLoc, diag::err_function_alwaysinline_attribute_mismatch) << Caller->getDeclName() << Callee->getDeclName() << "streaming"; diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c new file mode 100644 index 00000000000000..5c1779291a7e5b --- /dev/null +++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c @@ -0,0 +1,9 @@ +// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s + +// Conflicting attributes when using always_inline +__attribute__((always_inline)) +int inlined_fn_streaming(void) __arm_streaming { + return 42; +} +// expected-error@+1 {{always_inline function 'inlined_fn_streaming' and its caller 'inlined_fn_caller' have mismatched streaming attributes}} +int inlined_fn_caller(void) __arm_streaming_compatible { return inlined_fn_streaming(); } diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c new file mode 100644 index 00000000000000..a996c429fdda0d --- /dev/null +++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c @@ -0,0 +1,17 @@ +// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s + +// Conflicting attributes when using always_inline +__attribute__((always_inline)) +int inlined_fn_streaming_compatible(void) __arm_streaming_compatible { + return 42; +} +__attribute__((always_inline)) +int inlined_fn(void) { + return 42; +} +int inlined_fn_caller(void) { return inlined_fn_streaming_compatible(); } +__arm_locally_streaming +int inlined_fn_caller_local(void) { return inlined_fn_streaming_compatible(); } +int inlined_fn_caller_streaming(void) __arm_streaming { return inlined_fn_streaming_compatible(); } +// expected-error@+1 {{always_inline function 'inlined_fn' and its caller 'inlined_fn_caller_compatible' have mismatched streaming attributes}} +int inlined_fn_caller_compatible(void) __arm_streaming_compatible { return inlined_fn(); } diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline-locally-streaming.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme-func-attrs-inline-locally-streaming.c rename to clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline-streaming.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme-func-attrs-inline-streaming.c rename to clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c >From 5428dd7ed0745fd58cec768cc12742c40b86ce60 Mon Sep 17 00:00:00 2001 From: Sam Tebbs <samuel.te...@arm.com> Date: Mon, 15 Jan 2024 16:14:00 +0000 Subject: [PATCH 04/18] fixup: rename error --- clang/include/clang/Basic/DiagnosticFrontendKinds.td | 2 +- clang/lib/CodeGen/Targets/AArch64.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td index 2d0f971858840d..27149553c79a2a 100644 --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -279,7 +279,7 @@ def err_builtin_needs_feature : Error<"%0 needs target feature %1">; def err_function_needs_feature : Error< "always_inline function %1 requires target feature '%2', but would " "be inlined into function %0 that is compiled without support for '%2'">; -def err_function_alwaysinline_attribute_mismatch : Error< +def err_function_always_inline_attribute_mismatch : Error< "always_inline function %1 and its caller %0 have mismatched %2 attributes">; def warn_avx_calling_convention diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp index 72f70c931fd9e6..8d9f840c018fa5 100644 --- a/clang/lib/CodeGen/Targets/AArch64.cpp +++ b/clang/lib/CodeGen/Targets/AArch64.cpp @@ -835,7 +835,7 @@ void AArch64TargetCodeGenInfo::checkFunctionCallABI( if (CalleeStreamingMode != CallerStreamingMode && CalleeStreamingMode != Sema::ArmStreamingCompatible) CGM.getDiags().Report(CallLoc, - diag::err_function_alwaysinline_attribute_mismatch) + diag::err_function_always_inline_attribute_mismatch) << Caller->getDeclName() << Callee->getDeclName() << "streaming"; } >From 3b5451c8743a9f5a00d460c6a8eb998b6acaedc2 Mon Sep 17 00:00:00 2001 From: Sam Tebbs <samuel.te...@arm.com> Date: Mon, 15 Jan 2024 16:14:14 +0000 Subject: [PATCH 05/18] fixup: return void in tests --- .../sme-inline-streaming-compatible-caller.c | 6 ++---- .../sme-inline-streaming-compatible.c | 16 ++++++---------- .../sme-inline-streaming-locally.c | 10 ++++------ .../sme-inline-streaming.c | 10 ++++------ 4 files changed, 16 insertions(+), 26 deletions(-) diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c index 5c1779291a7e5b..add3f464bbaaa3 100644 --- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c +++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c @@ -2,8 +2,6 @@ // Conflicting attributes when using always_inline __attribute__((always_inline)) -int inlined_fn_streaming(void) __arm_streaming { - return 42; -} +void inlined_fn_streaming(void) __arm_streaming {} // expected-error@+1 {{always_inline function 'inlined_fn_streaming' and its caller 'inlined_fn_caller' have mismatched streaming attributes}} -int inlined_fn_caller(void) __arm_streaming_compatible { return inlined_fn_streaming(); } +void inlined_fn_caller(void) __arm_streaming_compatible { inlined_fn_streaming(); } diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c index a996c429fdda0d..a07c42c141d5b2 100644 --- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c +++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c @@ -2,16 +2,12 @@ // Conflicting attributes when using always_inline __attribute__((always_inline)) -int inlined_fn_streaming_compatible(void) __arm_streaming_compatible { - return 42; -} +void inlined_fn_streaming_compatible(void) __arm_streaming_compatible {} __attribute__((always_inline)) -int inlined_fn(void) { - return 42; -} -int inlined_fn_caller(void) { return inlined_fn_streaming_compatible(); } +void inlined_fn(void) {} +void inlined_fn_caller(void) { inlined_fn_streaming_compatible(); } __arm_locally_streaming -int inlined_fn_caller_local(void) { return inlined_fn_streaming_compatible(); } -int inlined_fn_caller_streaming(void) __arm_streaming { return inlined_fn_streaming_compatible(); } +void inlined_fn_caller_local(void) { inlined_fn_streaming_compatible(); } +void inlined_fn_caller_streaming(void) __arm_streaming { inlined_fn_streaming_compatible(); } // expected-error@+1 {{always_inline function 'inlined_fn' and its caller 'inlined_fn_caller_compatible' have mismatched streaming attributes}} -int inlined_fn_caller_compatible(void) __arm_streaming_compatible { return inlined_fn(); } +void inlined_fn_caller_compatible(void) __arm_streaming_compatible { inlined_fn(); } diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c index 4aa9fbf4a8fa18..6d645334ecb9d1 100644 --- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c +++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c @@ -2,11 +2,9 @@ // Conflicting attributes when using always_inline __attribute__((always_inline)) __arm_locally_streaming -int inlined_fn_local(void) { - return 42; -} +void inlined_fn_local(void) {} // expected-error@+1 {{always_inline function 'inlined_fn_local' and its caller 'inlined_fn_caller' have mismatched streaming attributes}} -int inlined_fn_caller(void) { return inlined_fn_local(); } +void inlined_fn_caller(void) { inlined_fn_local(); } __arm_locally_streaming -int inlined_fn_caller_local(void) { return inlined_fn_local(); } -int inlined_fn_caller_streaming(void) __arm_streaming { return inlined_fn_local(); } +void inlined_fn_caller_local(void) { inlined_fn_local(); } +void inlined_fn_caller_streaming(void) __arm_streaming { inlined_fn_local(); } diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c index 7268a49bb2491d..8afce84837838c 100644 --- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c +++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c @@ -2,11 +2,9 @@ // Conflicting attributes when using always_inline __attribute__((always_inline)) -int inlined_fn_streaming(void) __arm_streaming { - return 42; -} +void inlined_fn_streaming(void) __arm_streaming {} // expected-error@+1 {{always_inline function 'inlined_fn_streaming' and its caller 'inlined_fn_caller' have mismatched streaming attributes}} -int inlined_fn_caller(void) { return inlined_fn_streaming(); } +void inlined_fn_caller(void) { inlined_fn_streaming(); } __arm_locally_streaming -int inlined_fn_caller_local(void) { return inlined_fn_streaming(); } -int inlined_fn_caller_streaming(void) __arm_streaming { return inlined_fn_streaming(); } +void inlined_fn_caller_local(void) { inlined_fn_streaming(); } +void inlined_fn_caller_streaming(void) __arm_streaming { inlined_fn_streaming(); } >From c49ff5e797a123a146c7df722556eb4d12c85047 Mon Sep 17 00:00:00 2001 From: Samuel Tebbs <samuel.te...@arm.com> Date: Wed, 17 Jan 2024 17:10:41 +0000 Subject: [PATCH 06/18] fixup: use SMEAttrs class --- clang/include/clang/Sema/Sema.h | 8 ------ clang/lib/CodeGen/CMakeLists.txt | 2 +- clang/lib/CodeGen/Targets/AArch64.cpp | 25 ++++++++++++----- clang/lib/Sema/SemaChecking.cpp | 27 ++++++++++++------- .../llvm/Support}/AArch64SMEAttributes.h | 0 llvm/lib/Target/AArch64/AArch64ISelLowering.h | 2 +- llvm/lib/Target/AArch64/SMEABIPass.cpp | 2 +- .../AArch64/Utils/AArch64SMEAttributes.cpp | 2 +- .../Target/AArch64/SMEAttributesTest.cpp | 2 +- 9 files changed, 40 insertions(+), 30 deletions(-) rename llvm/{lib/Target/AArch64/Utils => include/llvm/Support}/AArch64SMEAttributes.h (100%) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 1ee065e7de9b15..6ce422d66ae5b0 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -13832,16 +13832,8 @@ class Sema final { FormatArgumentPassingKind ArgPassingKind; }; - enum ArmStreamingType { - ArmNonStreaming, - ArmStreaming, - ArmStreamingCompatible, - ArmStreamingOrSVE2p1 - }; - static bool getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember, bool IsVariadic, FormatStringInfo *FSI); - static ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD); private: void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt index 03a6f2f1d7a9d2..919b826f5c5716 100644 --- a/clang/lib/CodeGen/CMakeLists.txt +++ b/clang/lib/CodeGen/CMakeLists.txt @@ -31,6 +31,7 @@ set(LLVM_LINK_COMPONENTS Target TargetParser TransformUtils + AArch64Utils ) # Workaround for MSVC ARM64 performance regression: @@ -151,5 +152,4 @@ add_clang_library(clangCodeGen clangFrontend clangLex clangSerialization - clangSema ) diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp index 8d9f840c018fa5..8b15b798c5f896 100644 --- a/clang/lib/CodeGen/Targets/AArch64.cpp +++ b/clang/lib/CodeGen/Targets/AArch64.cpp @@ -9,7 +9,7 @@ #include "ABIInfoImpl.h" #include "TargetInfo.h" #include "clang/Basic/DiagnosticFrontend.h" -#include "clang/Sema/Sema.h" +#include "llvm/Support/AArch64SMEAttributes.h" using namespace clang; using namespace clang::CodeGen; @@ -827,13 +827,24 @@ void AArch64TargetCodeGenInfo::checkFunctionCallABI( if (!Callee->hasAttr<AlwaysInlineAttr>()) return; - auto CalleeStreamingMode = Sema::getArmStreamingFnType(Callee); - auto CallerStreamingMode = Sema::getArmStreamingFnType(Caller); + auto GetSMEAttrs = [](const FunctionDecl *F) { + llvm::SMEAttrs FAttrs; + if (F->hasAttr<ArmLocallyStreamingAttr>()) + FAttrs.set(llvm::SMEAttrs::Mask::SM_Enabled); + if (const auto *T = F->getType()->getAs<FunctionProtoType>()) { + if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask) + FAttrs.set(llvm::SMEAttrs::Mask::SM_Enabled); + if (T->getAArch64SMEAttributes() & + FunctionType::SME_PStateSMCompatibleMask) + FAttrs.set(llvm::SMEAttrs::Mask::SM_Compatible); + } + return FAttrs; + }; + + auto CalleeAttrs = GetSMEAttrs(Callee); + auto CallerAttrs = GetSMEAttrs(Caller); - // The caller can inline the callee if their streaming modes match or the - // callee is streaming compatible - if (CalleeStreamingMode != CallerStreamingMode && - CalleeStreamingMode != Sema::ArmStreamingCompatible) + if (CallerAttrs.requiresSMChange(CalleeAttrs, true)) CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_attribute_mismatch) << Caller->getDeclName() << Callee->getDeclName() << "streaming"; diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index a92db7d67e1cbd..ace3e386988f00 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2998,6 +2998,13 @@ static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context, llvm_unreachable("Invalid NeonTypeFlag!"); } +enum ArmStreamingType { + ArmNonStreaming, + ArmStreaming, + ArmStreamingCompatible, + ArmStreamingOrSVE2p1 +}; + bool Sema::ParseSVEImmChecks( CallExpr *TheCall, SmallVector<std::tuple<int, int, int>, 3> &ImmChecks) { // Perform all the immediate checks for this builtin call. @@ -3138,7 +3145,7 @@ bool Sema::ParseSVEImmChecks( return HasError; } -Sema::ArmStreamingType Sema::getArmStreamingFnType(const FunctionDecl *FD) { +static ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD) { if (FD->hasAttr<ArmLocallyStreamingAttr>()) return ArmStreaming; if (const auto *T = FD->getType()->getAs<FunctionProtoType>()) { @@ -3152,31 +3159,31 @@ Sema::ArmStreamingType Sema::getArmStreamingFnType(const FunctionDecl *FD) { static void checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall, const FunctionDecl *FD, - Sema::ArmStreamingType BuiltinType) { - Sema::ArmStreamingType FnType = Sema::getArmStreamingFnType(FD); - if (BuiltinType == Sema::ArmStreamingOrSVE2p1) { + ArmStreamingType BuiltinType) { + ArmStreamingType FnType = getArmStreamingFnType(FD); + if (BuiltinType == ArmStreamingOrSVE2p1) { // Check intrinsics that are available in [sve2p1 or sme/sme2]. llvm::StringMap<bool> CallerFeatureMap; S.Context.getFunctionFeatureMap(CallerFeatureMap, FD); if (Builtin::evaluateRequiredTargetFeatures("sve2p1", CallerFeatureMap)) - BuiltinType = Sema::ArmStreamingCompatible; + BuiltinType = ArmStreamingCompatible; else - BuiltinType = Sema::ArmStreaming; + BuiltinType = ArmStreaming; } - if (FnType == Sema::ArmStreaming && BuiltinType == Sema::ArmNonStreaming) { + if (FnType == ArmStreaming && BuiltinType == ArmNonStreaming) { S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) << TheCall->getSourceRange() << "streaming"; } - if (FnType == Sema::ArmStreamingCompatible && - BuiltinType != Sema::ArmStreamingCompatible) { + if (FnType == ArmStreamingCompatible && + BuiltinType != ArmStreamingCompatible) { S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) << TheCall->getSourceRange() << "streaming compatible"; return; } - if (FnType == Sema::ArmNonStreaming && BuiltinType == Sema::ArmStreaming) { + if (FnType == ArmNonStreaming && BuiltinType == ArmStreaming) { S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) << TheCall->getSourceRange() << "non-streaming"; } diff --git a/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.h b/llvm/include/llvm/Support/AArch64SMEAttributes.h similarity index 100% rename from llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.h rename to llvm/include/llvm/Support/AArch64SMEAttributes.h diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h index 6047a3b7b2864a..9d9d67490aa764 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h @@ -15,13 +15,13 @@ #define LLVM_LIB_TARGET_AARCH64_AARCH64ISELLOWERING_H #include "AArch64.h" -#include "Utils/AArch64SMEAttributes.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/TargetLowering.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/Instruction.h" +#include "llvm/Support/AArch64SMEAttributes.h" namespace llvm { diff --git a/llvm/lib/Target/AArch64/SMEABIPass.cpp b/llvm/lib/Target/AArch64/SMEABIPass.cpp index 3315171798d9f1..b9a68179966c04 100644 --- a/llvm/lib/Target/AArch64/SMEABIPass.cpp +++ b/llvm/lib/Target/AArch64/SMEABIPass.cpp @@ -14,7 +14,6 @@ #include "AArch64.h" #include "Utils/AArch64BaseInfo.h" -#include "Utils/AArch64SMEAttributes.h" #include "llvm/ADT/StringRef.h" #include "llvm/IR/Constants.h" #include "llvm/IR/IRBuilder.h" @@ -23,6 +22,7 @@ #include "llvm/IR/IntrinsicsAArch64.h" #include "llvm/IR/LLVMContext.h" #include "llvm/InitializePasses.h" +#include "llvm/Support/AArch64SMEAttributes.h" #include "llvm/Support/Debug.h" #include "llvm/Transforms/Utils/Cloning.h" diff --git a/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.cpp b/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.cpp index ccdec78d780866..4af54c1d611d56 100644 --- a/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.cpp +++ b/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "AArch64SMEAttributes.h" +#include "llvm/Support/AArch64SMEAttributes.h" #include "llvm/IR/InstrTypes.h" #include <cassert> diff --git a/llvm/unittests/Target/AArch64/SMEAttributesTest.cpp b/llvm/unittests/Target/AArch64/SMEAttributesTest.cpp index 2f7201464ba2f2..b99cb4c0d775a8 100644 --- a/llvm/unittests/Target/AArch64/SMEAttributesTest.cpp +++ b/llvm/unittests/Target/AArch64/SMEAttributesTest.cpp @@ -1,7 +1,7 @@ -#include "Utils/AArch64SMEAttributes.h" #include "llvm/AsmParser/Parser.h" #include "llvm/IR/Function.h" #include "llvm/IR/Module.h" +#include "llvm/Support/AArch64SMEAttributes.h" #include "llvm/Support/SourceMgr.h" #include "gtest/gtest.h" >From b38b7d59246de3a8a26e10238aed5cb757b89e1d Mon Sep 17 00:00:00 2001 From: Samuel Tebbs <samuel.te...@arm.com> Date: Thu, 18 Jan 2024 11:07:00 +0000 Subject: [PATCH 07/18] fixup: rebase and check for new za state --- clang/include/clang/Basic/DiagnosticFrontendKinds.td | 2 ++ clang/lib/CodeGen/Targets/AArch64.cpp | 7 +++++++ .../aarch64-sme-func-attrs-inline/sme-inline-new-za.c | 6 ++++++ 3 files changed, 15 insertions(+) create mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-new-za.c diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td index 27149553c79a2a..cbb5db3e0b1c82 100644 --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -281,6 +281,8 @@ def err_function_needs_feature : Error< "be inlined into function %0 that is compiled without support for '%2'">; def err_function_always_inline_attribute_mismatch : Error< "always_inline function %1 and its caller %0 have mismatched %2 attributes">; +def err_function_always_inline_new_za : Error< + "always_inline function %0 has new za state">; def warn_avx_calling_convention : Warning<"AVX vector %select{return|argument}0 of type %1 without '%2' " diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp index 8b15b798c5f896..9f4323bef38896 100644 --- a/clang/lib/CodeGen/Targets/AArch64.cpp +++ b/clang/lib/CodeGen/Targets/AArch64.cpp @@ -831,6 +831,10 @@ void AArch64TargetCodeGenInfo::checkFunctionCallABI( llvm::SMEAttrs FAttrs; if (F->hasAttr<ArmLocallyStreamingAttr>()) FAttrs.set(llvm::SMEAttrs::Mask::SM_Enabled); + if (auto *NewAttr = F->getAttr<ArmNewAttr>()) { + if (NewAttr->isNewZA()) + FAttrs.set(llvm::SMEAttrs::Mask::ZA_New); + } if (const auto *T = F->getType()->getAs<FunctionProtoType>()) { if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask) FAttrs.set(llvm::SMEAttrs::Mask::SM_Enabled); @@ -848,6 +852,9 @@ void AArch64TargetCodeGenInfo::checkFunctionCallABI( CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_attribute_mismatch) << Caller->getDeclName() << Callee->getDeclName() << "streaming"; + if (CalleeAttrs.hasNewZABody()) + CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_new_za) + << Callee->getDeclName(); } std::unique_ptr<TargetCodeGenInfo> diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-new-za.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-new-za.c new file mode 100644 index 00000000000000..97af6ec2be7a35 --- /dev/null +++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-new-za.c @@ -0,0 +1,6 @@ +// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s + +__attribute__((always_inline)) __arm_new("za") +void inline_new_za(void) { } +// expected-error@+1 {{always_inline function 'inline_new_za' has new za state}} +void inline_caller() { inline_new_za(); } >From c624882613fc3245ca3c8d73ce68b17a9cb43068 Mon Sep 17 00:00:00 2001 From: Samuel Tebbs <samuel.te...@arm.com> Date: Tue, 23 Jan 2024 14:43:32 +0000 Subject: [PATCH 08/18] fixup: re-implement SMEAttributes and check for lazy save --- .../clang/Basic/DiagnosticFrontendKinds.td | 2 + clang/lib/CodeGen/Targets/AArch64.cpp | 81 +++++++++++++++---- .../sme-inline-lazy-save.c | 14 ++++ .../sme-inline-streaming-locally.c | 4 +- .../sme-inline-streaming.c | 4 +- 5 files changed, 86 insertions(+), 19 deletions(-) create mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-lazy-save.c diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td index cbb5db3e0b1c82..d31577b5cf5e74 100644 --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -283,6 +283,8 @@ def err_function_always_inline_attribute_mismatch : Error< "always_inline function %1 and its caller %0 have mismatched %2 attributes">; def err_function_always_inline_new_za : Error< "always_inline function %0 has new za state">; +def err_function_always_inline_lazy_save : Error< + "inlining always_inline function %0 into %1 would require a lazy za save">; def warn_avx_calling_convention : Warning<"AVX vector %select{return|argument}0 of type %1 without '%2' " diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp index 9f4323bef38896..64d47a2f296d33 100644 --- a/clang/lib/CodeGen/Targets/AArch64.cpp +++ b/clang/lib/CodeGen/Targets/AArch64.cpp @@ -821,32 +821,80 @@ Address AArch64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr, /*allowHigherAlign*/ false); } -void AArch64TargetCodeGenInfo::checkFunctionCallABI( - CodeGenModule &CGM, SourceLocation CallLoc, const FunctionDecl *Caller, - const FunctionDecl *Callee, const CallArgList &Args) const { - if (!Callee->hasAttr<AlwaysInlineAttr>()) - return; +class SMEAttributes { +public: + bool IsStreaming = false; + bool IsStreamingBody = false; + bool IsStreamingCompatible = false; + bool HasNewZA = false; - auto GetSMEAttrs = [](const FunctionDecl *F) { - llvm::SMEAttrs FAttrs; + SMEAttributes(const FunctionDecl *F) { if (F->hasAttr<ArmLocallyStreamingAttr>()) - FAttrs.set(llvm::SMEAttrs::Mask::SM_Enabled); + IsStreamingBody = true; if (auto *NewAttr = F->getAttr<ArmNewAttr>()) { if (NewAttr->isNewZA()) - FAttrs.set(llvm::SMEAttrs::Mask::ZA_New); + HasNewZA = true; } if (const auto *T = F->getType()->getAs<FunctionProtoType>()) { if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask) - FAttrs.set(llvm::SMEAttrs::Mask::SM_Enabled); + IsStreaming = true; if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMCompatibleMask) - FAttrs.set(llvm::SMEAttrs::Mask::SM_Compatible); + IsStreamingCompatible = true; + } + } + + bool hasStreamingBody() const { return IsStreamingBody; } + bool hasStreamingInterface() const { return IsStreaming; } + bool hasStreamingCompatibleInterface() const { return IsStreamingCompatible; } + bool hasStreamingInterfaceOrBody() const { + return hasStreamingBody() || hasStreamingInterface(); + } + bool hasNonStreamingInterface() const { + return !hasStreamingInterface() && !hasStreamingCompatibleInterface(); + } + bool hasNonStreamingInterfaceAndBody() const { + return hasNonStreamingInterface() && !hasStreamingBody(); + } + + bool requiresSMChange(const SMEAttributes Callee, + bool BodyOverridesInterface = false) { + // If the transition is not through a call (e.g. when considering inlining) + // and Callee has a streaming body, then we can ignore the interface of + // Callee. + if (BodyOverridesInterface && Callee.hasStreamingBody()) { + return !hasStreamingInterfaceOrBody(); } - return FAttrs; - }; - auto CalleeAttrs = GetSMEAttrs(Callee); - auto CallerAttrs = GetSMEAttrs(Caller); + if (Callee.hasStreamingCompatibleInterface()) + return false; + + if (hasStreamingCompatibleInterface()) + return true; + + // Both non-streaming + if (hasNonStreamingInterfaceAndBody() && Callee.hasNonStreamingInterface()) + return false; + + // Both streaming + if (hasStreamingInterfaceOrBody() && Callee.hasStreamingInterface()) + return false; + + return Callee.hasStreamingInterface(); + } + + bool hasNewZABody() { return HasNewZA; } + bool requiresLazySave() const { return HasNewZA; } +}; + +void AArch64TargetCodeGenInfo::checkFunctionCallABI( + CodeGenModule &CGM, SourceLocation CallLoc, const FunctionDecl *Caller, + const FunctionDecl *Callee, const CallArgList &Args) const { + if (!Callee->hasAttr<AlwaysInlineAttr>()) + return; + + SMEAttributes CalleeAttrs(Callee); + SMEAttributes CallerAttrs(Caller); if (CallerAttrs.requiresSMChange(CalleeAttrs, true)) CGM.getDiags().Report(CallLoc, @@ -855,6 +903,9 @@ void AArch64TargetCodeGenInfo::checkFunctionCallABI( if (CalleeAttrs.hasNewZABody()) CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_new_za) << Callee->getDeclName(); + if (CallerAttrs.requiresLazySave()) + CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_lazy_save) + << Callee->getDeclName() << Caller->getDeclName(); } std::unique_ptr<TargetCodeGenInfo> diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-lazy-save.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-lazy-save.c new file mode 100644 index 00000000000000..4cd0b32a08dab0 --- /dev/null +++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-lazy-save.c @@ -0,0 +1,14 @@ +// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s + +__attribute__((always_inline)) +void inlined(void) {} + +void inline_caller(void) { + inlined(); +} + +__arm_new("za") +// expected-error@+2 {{inlining always_inline function 'inlined' into 'inline_caller_new_za' would require a lazy za save}} +void inline_caller_new_za(void) { + inlined(); +} diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c index 6d645334ecb9d1..09bbbaf43ea5a2 100644 --- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c +++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c @@ -3,8 +3,8 @@ // Conflicting attributes when using always_inline __attribute__((always_inline)) __arm_locally_streaming void inlined_fn_local(void) {} -// expected-error@+1 {{always_inline function 'inlined_fn_local' and its caller 'inlined_fn_caller' have mismatched streaming attributes}} -void inlined_fn_caller(void) { inlined_fn_local(); } __arm_locally_streaming void inlined_fn_caller_local(void) { inlined_fn_local(); } void inlined_fn_caller_streaming(void) __arm_streaming { inlined_fn_local(); } +// expected-error@+1 {{always_inline function 'inlined_fn_local' and its caller 'inlined_fn_caller' have mismatched streaming attributes}} +void inlined_fn_caller(void) { inlined_fn_local(); } diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c index 8afce84837838c..9f0e944c8f8401 100644 --- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c +++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c @@ -3,8 +3,8 @@ // Conflicting attributes when using always_inline __attribute__((always_inline)) void inlined_fn_streaming(void) __arm_streaming {} -// expected-error@+1 {{always_inline function 'inlined_fn_streaming' and its caller 'inlined_fn_caller' have mismatched streaming attributes}} -void inlined_fn_caller(void) { inlined_fn_streaming(); } __arm_locally_streaming void inlined_fn_caller_local(void) { inlined_fn_streaming(); } void inlined_fn_caller_streaming(void) __arm_streaming { inlined_fn_streaming(); } +// expected-error@+1 {{always_inline function 'inlined_fn_streaming' and its caller 'inlined_fn_caller' have mismatched streaming attributes}} +void inlined_fn_caller(void) { inlined_fn_streaming(); } >From 5d58e1e43da95aaa26aec1d43276d023cad7fac0 Mon Sep 17 00:00:00 2001 From: Samuel Tebbs <samuel.te...@arm.com> Date: Tue, 30 Jan 2024 11:33:17 +0000 Subject: [PATCH 09/18] fixup: simplify checking code --- clang/lib/CodeGen/Targets/AArch64.cpp | 53 +++------------------------ 1 file changed, 6 insertions(+), 47 deletions(-) diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp index 64d47a2f296d33..e0efda49f5b549 100644 --- a/clang/lib/CodeGen/Targets/AArch64.cpp +++ b/clang/lib/CodeGen/Targets/AArch64.cpp @@ -824,13 +824,12 @@ Address AArch64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr, class SMEAttributes { public: bool IsStreaming = false; - bool IsStreamingBody = false; bool IsStreamingCompatible = false; bool HasNewZA = false; SMEAttributes(const FunctionDecl *F) { if (F->hasAttr<ArmLocallyStreamingAttr>()) - IsStreamingBody = true; + IsStreaming = true; if (auto *NewAttr = F->getAttr<ArmNewAttr>()) { if (NewAttr->isNewZA()) HasNewZA = true; @@ -843,48 +842,6 @@ class SMEAttributes { IsStreamingCompatible = true; } } - - bool hasStreamingBody() const { return IsStreamingBody; } - bool hasStreamingInterface() const { return IsStreaming; } - bool hasStreamingCompatibleInterface() const { return IsStreamingCompatible; } - bool hasStreamingInterfaceOrBody() const { - return hasStreamingBody() || hasStreamingInterface(); - } - bool hasNonStreamingInterface() const { - return !hasStreamingInterface() && !hasStreamingCompatibleInterface(); - } - bool hasNonStreamingInterfaceAndBody() const { - return hasNonStreamingInterface() && !hasStreamingBody(); - } - - bool requiresSMChange(const SMEAttributes Callee, - bool BodyOverridesInterface = false) { - // If the transition is not through a call (e.g. when considering inlining) - // and Callee has a streaming body, then we can ignore the interface of - // Callee. - if (BodyOverridesInterface && Callee.hasStreamingBody()) { - return !hasStreamingInterfaceOrBody(); - } - - if (Callee.hasStreamingCompatibleInterface()) - return false; - - if (hasStreamingCompatibleInterface()) - return true; - - // Both non-streaming - if (hasNonStreamingInterfaceAndBody() && Callee.hasNonStreamingInterface()) - return false; - - // Both streaming - if (hasStreamingInterfaceOrBody() && Callee.hasStreamingInterface()) - return false; - - return Callee.hasStreamingInterface(); - } - - bool hasNewZABody() { return HasNewZA; } - bool requiresLazySave() const { return HasNewZA; } }; void AArch64TargetCodeGenInfo::checkFunctionCallABI( @@ -896,14 +853,16 @@ void AArch64TargetCodeGenInfo::checkFunctionCallABI( SMEAttributes CalleeAttrs(Callee); SMEAttributes CallerAttrs(Caller); - if (CallerAttrs.requiresSMChange(CalleeAttrs, true)) + if (!CalleeAttrs.IsStreamingCompatible && + (CallerAttrs.IsStreaming != CalleeAttrs.IsStreaming || + CallerAttrs.IsStreamingCompatible)) CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_attribute_mismatch) << Caller->getDeclName() << Callee->getDeclName() << "streaming"; - if (CalleeAttrs.hasNewZABody()) + if (CalleeAttrs.HasNewZA) CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_new_za) << Callee->getDeclName(); - if (CallerAttrs.requiresLazySave()) + if (CallerAttrs.HasNewZA) CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_lazy_save) << Callee->getDeclName() << Caller->getDeclName(); } >From 626059f3edf7d271cfede424b4c787c8b6437087 Mon Sep 17 00:00:00 2001 From: Samuel Tebbs <samuel.te...@arm.com> Date: Tue, 30 Jan 2024 11:33:44 +0000 Subject: [PATCH 10/18] fixup: remove lazy save checking --- clang/lib/CodeGen/Targets/AArch64.cpp | 3 --- .../sme-inline-lazy-save.c | 14 -------------- 2 files changed, 17 deletions(-) delete mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-lazy-save.c diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp index e0efda49f5b549..c8b35a9d8c2b1a 100644 --- a/clang/lib/CodeGen/Targets/AArch64.cpp +++ b/clang/lib/CodeGen/Targets/AArch64.cpp @@ -862,9 +862,6 @@ void AArch64TargetCodeGenInfo::checkFunctionCallABI( if (CalleeAttrs.HasNewZA) CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_new_za) << Callee->getDeclName(); - if (CallerAttrs.HasNewZA) - CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_lazy_save) - << Callee->getDeclName() << Caller->getDeclName(); } std::unique_ptr<TargetCodeGenInfo> diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-lazy-save.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-lazy-save.c deleted file mode 100644 index 4cd0b32a08dab0..00000000000000 --- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-lazy-save.c +++ /dev/null @@ -1,14 +0,0 @@ -// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s - -__attribute__((always_inline)) -void inlined(void) {} - -void inline_caller(void) { - inlined(); -} - -__arm_new("za") -// expected-error@+2 {{inlining always_inline function 'inlined' into 'inline_caller_new_za' would require a lazy za save}} -void inline_caller_new_za(void) { - inlined(); -} >From a5c1b77fab0b679ea373122f5fe1d4c378b8568b Mon Sep 17 00:00:00 2001 From: Samuel Tebbs <samuel.te...@arm.com> Date: Tue, 30 Jan 2024 11:45:13 +0000 Subject: [PATCH 11/18] fixup: undo sme attrs header file move --- clang/lib/CodeGen/CMakeLists.txt | 1 - clang/lib/CodeGen/Targets/AArch64.cpp | 1 - llvm/lib/Target/AArch64/AArch64ISelLowering.h | 2 +- llvm/lib/Target/AArch64/SMEABIPass.cpp | 2 +- llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.cpp | 2 +- .../Support => lib/Target/AArch64/Utils}/AArch64SMEAttributes.h | 0 llvm/unittests/Target/AArch64/SMEAttributesTest.cpp | 2 +- 7 files changed, 4 insertions(+), 6 deletions(-) rename llvm/{include/llvm/Support => lib/Target/AArch64/Utils}/AArch64SMEAttributes.h (100%) diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt index 919b826f5c5716..52216d93a302bb 100644 --- a/clang/lib/CodeGen/CMakeLists.txt +++ b/clang/lib/CodeGen/CMakeLists.txt @@ -31,7 +31,6 @@ set(LLVM_LINK_COMPONENTS Target TargetParser TransformUtils - AArch64Utils ) # Workaround for MSVC ARM64 performance regression: diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp index c8b35a9d8c2b1a..df1c8fe25fbbd4 100644 --- a/clang/lib/CodeGen/Targets/AArch64.cpp +++ b/clang/lib/CodeGen/Targets/AArch64.cpp @@ -9,7 +9,6 @@ #include "ABIInfoImpl.h" #include "TargetInfo.h" #include "clang/Basic/DiagnosticFrontend.h" -#include "llvm/Support/AArch64SMEAttributes.h" using namespace clang; using namespace clang::CodeGen; diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h index 9d9d67490aa764..6047a3b7b2864a 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h @@ -15,13 +15,13 @@ #define LLVM_LIB_TARGET_AARCH64_AARCH64ISELLOWERING_H #include "AArch64.h" +#include "Utils/AArch64SMEAttributes.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/TargetLowering.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/Instruction.h" -#include "llvm/Support/AArch64SMEAttributes.h" namespace llvm { diff --git a/llvm/lib/Target/AArch64/SMEABIPass.cpp b/llvm/lib/Target/AArch64/SMEABIPass.cpp index b9a68179966c04..3315171798d9f1 100644 --- a/llvm/lib/Target/AArch64/SMEABIPass.cpp +++ b/llvm/lib/Target/AArch64/SMEABIPass.cpp @@ -14,6 +14,7 @@ #include "AArch64.h" #include "Utils/AArch64BaseInfo.h" +#include "Utils/AArch64SMEAttributes.h" #include "llvm/ADT/StringRef.h" #include "llvm/IR/Constants.h" #include "llvm/IR/IRBuilder.h" @@ -22,7 +23,6 @@ #include "llvm/IR/IntrinsicsAArch64.h" #include "llvm/IR/LLVMContext.h" #include "llvm/InitializePasses.h" -#include "llvm/Support/AArch64SMEAttributes.h" #include "llvm/Support/Debug.h" #include "llvm/Transforms/Utils/Cloning.h" diff --git a/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.cpp b/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.cpp index 4af54c1d611d56..ccdec78d780866 100644 --- a/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.cpp +++ b/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/AArch64SMEAttributes.h" +#include "AArch64SMEAttributes.h" #include "llvm/IR/InstrTypes.h" #include <cassert> diff --git a/llvm/include/llvm/Support/AArch64SMEAttributes.h b/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.h similarity index 100% rename from llvm/include/llvm/Support/AArch64SMEAttributes.h rename to llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.h diff --git a/llvm/unittests/Target/AArch64/SMEAttributesTest.cpp b/llvm/unittests/Target/AArch64/SMEAttributesTest.cpp index b99cb4c0d775a8..2f7201464ba2f2 100644 --- a/llvm/unittests/Target/AArch64/SMEAttributesTest.cpp +++ b/llvm/unittests/Target/AArch64/SMEAttributesTest.cpp @@ -1,7 +1,7 @@ +#include "Utils/AArch64SMEAttributes.h" #include "llvm/AsmParser/Parser.h" #include "llvm/IR/Function.h" #include "llvm/IR/Module.h" -#include "llvm/Support/AArch64SMEAttributes.h" #include "llvm/Support/SourceMgr.h" #include "gtest/gtest.h" >From 30abfe2323705a7f5b9399da32f0df2c649f583f Mon Sep 17 00:00:00 2001 From: Samuel Tebbs <samuel.te...@arm.com> Date: Tue, 30 Jan 2024 13:39:32 +0000 Subject: [PATCH 12/18] fixup: change error message --- clang/include/clang/Basic/DiagnosticFrontendKinds.td | 2 +- .../sme-inline-streaming-compatible-caller.c | 2 +- .../sme-inline-streaming-compatible.c | 2 +- .../sme-inline-streaming-locally.c | 2 +- .../aarch64-sme-func-attrs-inline/sme-inline-streaming.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td index d31577b5cf5e74..f6e7bd72ac8448 100644 --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -280,7 +280,7 @@ def err_function_needs_feature : Error< "always_inline function %1 requires target feature '%2', but would " "be inlined into function %0 that is compiled without support for '%2'">; def err_function_always_inline_attribute_mismatch : Error< - "always_inline function %1 and its caller %0 have mismatched %2 attributes">; + "always_inline function %1 and its caller %0 have mismatching %2 attributes">; def err_function_always_inline_new_za : Error< "always_inline function %0 has new za state">; def err_function_always_inline_lazy_save : Error< diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c index add3f464bbaaa3..a52ae689b630a4 100644 --- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c +++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c @@ -3,5 +3,5 @@ // Conflicting attributes when using always_inline __attribute__((always_inline)) void inlined_fn_streaming(void) __arm_streaming {} -// expected-error@+1 {{always_inline function 'inlined_fn_streaming' and its caller 'inlined_fn_caller' have mismatched streaming attributes}} +// expected-error@+1 {{always_inline function 'inlined_fn_streaming' and its caller 'inlined_fn_caller' have mismatching streaming attributes}} void inlined_fn_caller(void) __arm_streaming_compatible { inlined_fn_streaming(); } diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c index a07c42c141d5b2..2970f66b3905d8 100644 --- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c +++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c @@ -9,5 +9,5 @@ void inlined_fn_caller(void) { inlined_fn_streaming_compatible(); } __arm_locally_streaming void inlined_fn_caller_local(void) { inlined_fn_streaming_compatible(); } void inlined_fn_caller_streaming(void) __arm_streaming { inlined_fn_streaming_compatible(); } -// expected-error@+1 {{always_inline function 'inlined_fn' and its caller 'inlined_fn_caller_compatible' have mismatched streaming attributes}} +// expected-error@+1 {{always_inline function 'inlined_fn' and its caller 'inlined_fn_caller_compatible' have mismatching streaming attributes}} void inlined_fn_caller_compatible(void) __arm_streaming_compatible { inlined_fn(); } diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c index 09bbbaf43ea5a2..f88564f2527a70 100644 --- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c +++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c @@ -6,5 +6,5 @@ void inlined_fn_local(void) {} __arm_locally_streaming void inlined_fn_caller_local(void) { inlined_fn_local(); } void inlined_fn_caller_streaming(void) __arm_streaming { inlined_fn_local(); } -// expected-error@+1 {{always_inline function 'inlined_fn_local' and its caller 'inlined_fn_caller' have mismatched streaming attributes}} +// expected-error@+1 {{always_inline function 'inlined_fn_local' and its caller 'inlined_fn_caller' have mismatching streaming attributes}} void inlined_fn_caller(void) { inlined_fn_local(); } diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c index 9f0e944c8f8401..480e99e313fe0b 100644 --- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c +++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c @@ -6,5 +6,5 @@ void inlined_fn_streaming(void) __arm_streaming {} __arm_locally_streaming void inlined_fn_caller_local(void) { inlined_fn_streaming(); } void inlined_fn_caller_streaming(void) __arm_streaming { inlined_fn_streaming(); } -// expected-error@+1 {{always_inline function 'inlined_fn_streaming' and its caller 'inlined_fn_caller' have mismatched streaming attributes}} +// expected-error@+1 {{always_inline function 'inlined_fn_streaming' and its caller 'inlined_fn_caller' have mismatching streaming attributes}} void inlined_fn_caller(void) { inlined_fn_streaming(); } >From 4c0341365d9e14165379f889f1882fe9d636cdaa Mon Sep 17 00:00:00 2001 From: Samuel Tebbs <samuel.te...@arm.com> Date: Wed, 14 Feb 2024 13:31:02 +0000 Subject: [PATCH 13/18] fixup: remove lazy save error definition --- clang/include/clang/Basic/DiagnosticFrontendKinds.td | 2 -- 1 file changed, 2 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td index f6e7bd72ac8448..1e1122f19c6178 100644 --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -283,8 +283,6 @@ def err_function_always_inline_attribute_mismatch : Error< "always_inline function %1 and its caller %0 have mismatching %2 attributes">; def err_function_always_inline_new_za : Error< "always_inline function %0 has new za state">; -def err_function_always_inline_lazy_save : Error< - "inlining always_inline function %0 into %1 would require a lazy za save">; def warn_avx_calling_convention : Warning<"AVX vector %select{return|argument}0 of type %1 without '%2' " >From c5dd67d9914a5eb80fe72dbf3e2acd8ec260e753 Mon Sep 17 00:00:00 2001 From: Samuel Tebbs <samuel.te...@arm.com> Date: Wed, 14 Feb 2024 13:31:14 +0000 Subject: [PATCH 14/18] fixup: remove attributes class --- clang/lib/CodeGen/Targets/AArch64.cpp | 56 ++++++++++++--------------- 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp index df1c8fe25fbbd4..3ddea253daa72b 100644 --- a/clang/lib/CodeGen/Targets/AArch64.cpp +++ b/clang/lib/CodeGen/Targets/AArch64.cpp @@ -820,47 +820,41 @@ Address AArch64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr, /*allowHigherAlign*/ false); } -class SMEAttributes { -public: - bool IsStreaming = false; - bool IsStreamingCompatible = false; - bool HasNewZA = false; - - SMEAttributes(const FunctionDecl *F) { - if (F->hasAttr<ArmLocallyStreamingAttr>()) - IsStreaming = true; - if (auto *NewAttr = F->getAttr<ArmNewAttr>()) { - if (NewAttr->isNewZA()) - HasNewZA = true; - } - if (const auto *T = F->getType()->getAs<FunctionProtoType>()) { - if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask) - IsStreaming = true; - if (T->getAArch64SMEAttributes() & - FunctionType::SME_PStateSMCompatibleMask) - IsStreamingCompatible = true; - } - } -}; +static bool isStreaming(const FunctionDecl *F) { + if (F->hasAttr<ArmLocallyStreamingAttr>()) + return true; + if (const auto *T = F->getType()->getAs<FunctionProtoType>()) + return T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask; + return false; +} + +static bool isStreamingCompatible(const FunctionDecl *F) { + if (const auto *T = F->getType()->getAs<FunctionProtoType>()) + return T->getAArch64SMEAttributes() & + FunctionType::SME_PStateSMCompatibleMask; + return false; +} void AArch64TargetCodeGenInfo::checkFunctionCallABI( CodeGenModule &CGM, SourceLocation CallLoc, const FunctionDecl *Caller, const FunctionDecl *Callee, const CallArgList &Args) const { - if (!Callee->hasAttr<AlwaysInlineAttr>()) + if (!Caller || !Callee->hasAttr<AlwaysInlineAttr>()) return; - SMEAttributes CalleeAttrs(Callee); - SMEAttributes CallerAttrs(Caller); + bool CallerIsStreaming = isStreaming(Caller); + bool CalleeIsStreaming = isStreaming(Callee); + bool CallerIsStreamingCompatible = isStreamingCompatible(Caller); + bool CalleeIsStreamingCompatible = isStreamingCompatible(Callee); - if (!CalleeAttrs.IsStreamingCompatible && - (CallerAttrs.IsStreaming != CalleeAttrs.IsStreaming || - CallerAttrs.IsStreamingCompatible)) + if (!CalleeIsStreamingCompatible && + (CallerIsStreaming != CalleeIsStreaming || CallerIsStreamingCompatible)) CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_attribute_mismatch) << Caller->getDeclName() << Callee->getDeclName() << "streaming"; - if (CalleeAttrs.HasNewZA) - CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_new_za) - << Callee->getDeclName(); + if (auto *NewAttr = Callee->getAttr<ArmNewAttr>()) + if (NewAttr->isNewZA()) + CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_new_za) + << Callee->getDeclName(); } std::unique_ptr<TargetCodeGenInfo> >From e2fc441f9f9c7731f838fab004c64e2356bd1f4b Mon Sep 17 00:00:00 2001 From: Samuel Tebbs <samuel.te...@arm.com> Date: Wed, 14 Feb 2024 13:35:27 +0000 Subject: [PATCH 15/18] fixup: define __ai in streaming compatible test --- .../sme-inline-streaming-compatible.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c index 2970f66b3905d8..1bc26f8ec7a55b 100644 --- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c +++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c @@ -1,10 +1,9 @@ // RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s // Conflicting attributes when using always_inline -__attribute__((always_inline)) -void inlined_fn_streaming_compatible(void) __arm_streaming_compatible {} -__attribute__((always_inline)) -void inlined_fn(void) {} +#define __ai __attribute__((always_inline)) +__ai void inlined_fn_streaming_compatible(void) __arm_streaming_compatible {} +__ai void inlined_fn(void) {} void inlined_fn_caller(void) { inlined_fn_streaming_compatible(); } __arm_locally_streaming void inlined_fn_caller_local(void) { inlined_fn_streaming_compatible(); } >From 36a1a4331d37842ea14f094c51bb1a379f2b1f28 Mon Sep 17 00:00:00 2001 From: Samuel Tebbs <samuel.te...@arm.com> Date: Wed, 14 Feb 2024 13:36:54 +0000 Subject: [PATCH 16/18] fixup: remove -O3 from tests --- .../CodeGen/aarch64-sme-func-attrs-inline/sme-inline-new-za.c | 2 +- .../sme-inline-streaming-compatible-caller.c | 2 +- .../sme-inline-streaming-compatible.c | 2 +- .../sme-inline-streaming-locally.c | 2 +- .../aarch64-sme-func-attrs-inline/sme-inline-streaming.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-new-za.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-new-za.c index 97af6ec2be7a35..9d0423cb52e530 100644 --- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-new-za.c +++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-new-za.c @@ -1,4 +1,4 @@ -// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s +// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -S -Xclang -verify %s __attribute__((always_inline)) __arm_new("za") void inline_new_za(void) { } diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c index a52ae689b630a4..2ed48e86b481f1 100644 --- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c +++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c @@ -1,4 +1,4 @@ -// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s +// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -S -Xclang -verify %s // Conflicting attributes when using always_inline __attribute__((always_inline)) diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c index 1bc26f8ec7a55b..b9a74fcfed103d 100644 --- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c +++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c @@ -1,4 +1,4 @@ -// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s +// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -S -Xclang -verify %s // Conflicting attributes when using always_inline #define __ai __attribute__((always_inline)) diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c index f88564f2527a70..93f51af8211726 100644 --- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c +++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c @@ -1,4 +1,4 @@ -// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s +// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -S -Xclang -verify %s // Conflicting attributes when using always_inline __attribute__((always_inline)) __arm_locally_streaming diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c index 480e99e313fe0b..e024d697faf38c 100644 --- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c +++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c @@ -1,4 +1,4 @@ -// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s +// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -S -Xclang -verify %s // Conflicting attributes when using always_inline __attribute__((always_inline)) >From 3283c2e2e9264f5d8fbad79be86104897bd84d1a Mon Sep 17 00:00:00 2001 From: Samuel Tebbs <samuel.te...@arm.com> Date: Wed, 14 Feb 2024 16:43:26 +0000 Subject: [PATCH 17/18] fixup: merge tests --- .../sme-inline-new-za.c | 6 --- .../sme-inline-streaming-compatible-caller.c | 7 --- .../sme-inline-streaming-compatible.c | 12 ----- .../sme-inline-streaming-locally.c | 10 ---- .../sme-inline-streaming.c | 10 ---- .../aarch64-sme-inline-streaming-attrs.c | 47 +++++++++++++++++++ 6 files changed, 47 insertions(+), 45 deletions(-) delete mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-new-za.c delete mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c delete mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c delete mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c delete mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c create mode 100644 clang/test/CodeGen/aarch64-sme-inline-streaming-attrs.c diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-new-za.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-new-za.c deleted file mode 100644 index 9d0423cb52e530..00000000000000 --- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-new-za.c +++ /dev/null @@ -1,6 +0,0 @@ -// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -S -Xclang -verify %s - -__attribute__((always_inline)) __arm_new("za") -void inline_new_za(void) { } -// expected-error@+1 {{always_inline function 'inline_new_za' has new za state}} -void inline_caller() { inline_new_za(); } diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c deleted file mode 100644 index 2ed48e86b481f1..00000000000000 --- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c +++ /dev/null @@ -1,7 +0,0 @@ -// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -S -Xclang -verify %s - -// Conflicting attributes when using always_inline -__attribute__((always_inline)) -void inlined_fn_streaming(void) __arm_streaming {} -// expected-error@+1 {{always_inline function 'inlined_fn_streaming' and its caller 'inlined_fn_caller' have mismatching streaming attributes}} -void inlined_fn_caller(void) __arm_streaming_compatible { inlined_fn_streaming(); } diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c deleted file mode 100644 index b9a74fcfed103d..00000000000000 --- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c +++ /dev/null @@ -1,12 +0,0 @@ -// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -S -Xclang -verify %s - -// Conflicting attributes when using always_inline -#define __ai __attribute__((always_inline)) -__ai void inlined_fn_streaming_compatible(void) __arm_streaming_compatible {} -__ai void inlined_fn(void) {} -void inlined_fn_caller(void) { inlined_fn_streaming_compatible(); } -__arm_locally_streaming -void inlined_fn_caller_local(void) { inlined_fn_streaming_compatible(); } -void inlined_fn_caller_streaming(void) __arm_streaming { inlined_fn_streaming_compatible(); } -// expected-error@+1 {{always_inline function 'inlined_fn' and its caller 'inlined_fn_caller_compatible' have mismatching streaming attributes}} -void inlined_fn_caller_compatible(void) __arm_streaming_compatible { inlined_fn(); } diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c deleted file mode 100644 index 93f51af8211726..00000000000000 --- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c +++ /dev/null @@ -1,10 +0,0 @@ -// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -S -Xclang -verify %s - -// Conflicting attributes when using always_inline -__attribute__((always_inline)) __arm_locally_streaming -void inlined_fn_local(void) {} -__arm_locally_streaming -void inlined_fn_caller_local(void) { inlined_fn_local(); } -void inlined_fn_caller_streaming(void) __arm_streaming { inlined_fn_local(); } -// expected-error@+1 {{always_inline function 'inlined_fn_local' and its caller 'inlined_fn_caller' have mismatching streaming attributes}} -void inlined_fn_caller(void) { inlined_fn_local(); } diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c deleted file mode 100644 index e024d697faf38c..00000000000000 --- a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c +++ /dev/null @@ -1,10 +0,0 @@ -// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -S -Xclang -verify %s - -// Conflicting attributes when using always_inline -__attribute__((always_inline)) -void inlined_fn_streaming(void) __arm_streaming {} -__arm_locally_streaming -void inlined_fn_caller_local(void) { inlined_fn_streaming(); } -void inlined_fn_caller_streaming(void) __arm_streaming { inlined_fn_streaming(); } -// expected-error@+1 {{always_inline function 'inlined_fn_streaming' and its caller 'inlined_fn_caller' have mismatching streaming attributes}} -void inlined_fn_caller(void) { inlined_fn_streaming(); } diff --git a/clang/test/CodeGen/aarch64-sme-inline-streaming-attrs.c b/clang/test/CodeGen/aarch64-sme-inline-streaming-attrs.c new file mode 100644 index 00000000000000..f653b512d14005 --- /dev/null +++ b/clang/test/CodeGen/aarch64-sme-inline-streaming-attrs.c @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -S -target-feature +sme -verify -DTEST_NONE -x c %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -S -target-feature +sme -verify -DTEST_COMPATIBLE -x c %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -S -target-feature +sme -verify -DTEST_STREAMING -x c %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -S -target-feature +sme -verify -DTEST_LOCALLY -x c %s + +#define __ai __attribute__((always_inline)) +__ai void inlined_fn(void) {} +__ai void inlined_fn_streaming_compatible(void) __arm_streaming_compatible {} +__ai void inlined_fn_streaming(void) __arm_streaming {} +__ai __arm_locally_streaming void inlined_fn_local(void) {} + +#ifdef TEST_NONE +void caller(void) { + inlined_fn(); + inlined_fn_streaming_compatible(); + inlined_fn_streaming(); // expected-error {{always_inline function 'inlined_fn_streaming' and its caller 'caller' have mismatching streaming attributes}} + inlined_fn_local(); // expected-error {{always_inline function 'inlined_fn_local' and its caller 'caller' have mismatching streaming attributes}} +} +#endif + +#ifdef TEST_COMPATIBLE +void caller_compatible(void) __arm_streaming_compatible { + inlined_fn(); // expected-error {{always_inline function 'inlined_fn' and its caller 'caller_compatible' have mismatching streaming attributes}} + inlined_fn_streaming_compatible(); + inlined_fn_streaming(); // expected-error {{always_inline function 'inlined_fn_streaming' and its caller 'caller_compatible' have mismatching streaming attributes}} + inlined_fn_local(); // expected-error {{always_inline function 'inlined_fn_local' and its caller 'caller_compatible' have mismatching streaming attributes}} +} +#endif + +#ifdef TEST_STREAMING +void caller_streaming(void) __arm_streaming { + inlined_fn(); // expected-error {{always_inline function 'inlined_fn' and its caller 'caller_streaming' have mismatching streaming attributes}} + inlined_fn_streaming_compatible(); + inlined_fn_streaming(); + inlined_fn_local(); +} +#endif + +#ifdef TEST_LOCALLY +__arm_locally_streaming +void caller_local(void) { + inlined_fn(); // expected-error {{always_inline function 'inlined_fn' and its caller 'caller_local' have mismatching streaming attributes}} + inlined_fn_streaming_compatible(); + inlined_fn_streaming(); + inlined_fn_local(); +} +#endif >From e330889a7709c7323cc03d147156fd105174855c Mon Sep 17 00:00:00 2001 From: Samuel Tebbs <samuel.te...@arm.com> Date: Wed, 21 Feb 2024 15:45:07 +0000 Subject: [PATCH 18/18] fixup: remove -x c and add Callee check --- clang/lib/CodeGen/Targets/AArch64.cpp | 2 +- clang/test/CodeGen/aarch64-sme-inline-streaming-attrs.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp index 3ddea253daa72b..94f8e7be2ee6eb 100644 --- a/clang/lib/CodeGen/Targets/AArch64.cpp +++ b/clang/lib/CodeGen/Targets/AArch64.cpp @@ -838,7 +838,7 @@ static bool isStreamingCompatible(const FunctionDecl *F) { void AArch64TargetCodeGenInfo::checkFunctionCallABI( CodeGenModule &CGM, SourceLocation CallLoc, const FunctionDecl *Caller, const FunctionDecl *Callee, const CallArgList &Args) const { - if (!Caller || !Callee->hasAttr<AlwaysInlineAttr>()) + if (!Caller || !Callee || !Callee->hasAttr<AlwaysInlineAttr>()) return; bool CallerIsStreaming = isStreaming(Caller); diff --git a/clang/test/CodeGen/aarch64-sme-inline-streaming-attrs.c b/clang/test/CodeGen/aarch64-sme-inline-streaming-attrs.c index f653b512d14005..7eb74f28a1c85a 100644 --- a/clang/test/CodeGen/aarch64-sme-inline-streaming-attrs.c +++ b/clang/test/CodeGen/aarch64-sme-inline-streaming-attrs.c @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -S -target-feature +sme -verify -DTEST_NONE -x c %s -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -S -target-feature +sme -verify -DTEST_COMPATIBLE -x c %s -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -S -target-feature +sme -verify -DTEST_STREAMING -x c %s -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -S -target-feature +sme -verify -DTEST_LOCALLY -x c %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -S -target-feature +sme -verify -DTEST_NONE %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -S -target-feature +sme -verify -DTEST_COMPATIBLE %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -S -target-feature +sme -verify -DTEST_STREAMING %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -S -target-feature +sme -verify -DTEST_LOCALLY %s #define __ai __attribute__((always_inline)) __ai void inlined_fn(void) {} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits