https://github.com/xlauko updated https://github.com/llvm/llvm-project/pull/223425
>From 26f18e2580d28358203bfd3edb49fe33503ebf59 Mon Sep 17 00:00:00 2001 From: Henrich Lauko <[email protected]> Date: Tue, 29 Sep 2026 09:56:29 +0000 Subject: [PATCH] [CIR][CodeGen][NFC] Share the Arm SME inlinability check Deduplicates `ArmSMEInlinability` and `getArmSMEInlinability` between CIR and classic CodeGen into a new `TargetUtils.h`. Assisted-by: Claude Code (Claude Fable 5.1). --- .../include/clang/CodeGenUtils/TargetUtils.h | 48 ++++++++++++ clang/lib/CIR/CodeGen/Targets/AArch64.cpp | 55 +------------ clang/lib/CodeGen/Targets/AArch64.cpp | 78 +++++-------------- clang/lib/CodeGenUtils/CMakeLists.txt | 1 + clang/lib/CodeGenUtils/TargetUtils.cpp | 50 ++++++++++++ 5 files changed, 120 insertions(+), 112 deletions(-) create mode 100644 clang/include/clang/CodeGenUtils/TargetUtils.h create mode 100644 clang/lib/CodeGenUtils/TargetUtils.cpp diff --git a/clang/include/clang/CodeGenUtils/TargetUtils.h b/clang/include/clang/CodeGenUtils/TargetUtils.h new file mode 100644 index 0000000000000..db34fe9988461 --- /dev/null +++ b/clang/include/clang/CodeGenUtils/TargetUtils.h @@ -0,0 +1,48 @@ +//===--- TargetUtils.h - Shared target-specific AST queries -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file holds the target-specific AST queries that both classic CodeGen +// and CIR CodeGen need. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CODEGENUTILS_TARGETUTILS_H +#define LLVM_CLANG_CODEGENUTILS_TARGETUTILS_H + +#include "clang/Basic/BitmaskEnum.h" + +#include <cstdint> + +namespace clang { +class FunctionDecl; +} // namespace clang + +namespace clang::CodeGenUtils { + +/// The Arm SME ABI issues that can prevent inlining one function into another. +enum class ArmSMEInlinability : uint8_t { + Ok = 0, + ErrorCalleeRequiresNewZA = 1 << 0, + ErrorCalleeRequiresNewZT0 = 1 << 1, + WarnIncompatibleStreamingModes = 1 << 2, + ErrorIncompatibleStreamingModes = 1 << 3, + + IncompatibleStreamingModes = WarnIncompatibleStreamingModes | + ErrorIncompatibleStreamingModes, + + LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/ErrorIncompatibleStreamingModes), +}; + +/// Determines if there are any Arm SME ABI issues with inlining \p Callee into +/// \p Caller. Returns the issue (if any) in the ArmSMEInlinability bit enum. +ArmSMEInlinability getArmSMEInlinability(const FunctionDecl *Caller, + const FunctionDecl *Callee); + +} // namespace clang::CodeGenUtils + +#endif // LLVM_CLANG_CODEGENUTILS_TARGETUTILS_H diff --git a/clang/lib/CIR/CodeGen/Targets/AArch64.cpp b/clang/lib/CIR/CodeGen/Targets/AArch64.cpp index cf69ca681f3f7..48791b9fa931f 100644 --- a/clang/lib/CIR/CodeGen/Targets/AArch64.cpp +++ b/clang/lib/CIR/CodeGen/Targets/AArch64.cpp @@ -16,6 +16,7 @@ #include "TargetInfo.h" #include "clang/AST/Decl.h" #include "clang/CIR/MissingFeatures.h" +#include "clang/CodeGenUtils/TargetUtils.h" using namespace clang; using namespace clang::CIRGen; @@ -56,61 +57,11 @@ class AArch64TargetCIRGenInfo : public TargetCIRGenInfo { } // namespace -// TODO(cir): Find a way to share this with classic codegen. -enum class ArmSMEInlinability : uint8_t { - Ok = 0, - ErrorCalleeRequiresNewZA = 1 << 0, - ErrorCalleeRequiresNewZT0 = 1 << 1, - WarnIncompatibleStreamingModes = 1 << 2, - ErrorIncompatibleStreamingModes = 1 << 3, - - IncompatibleStreamingModes = - WarnIncompatibleStreamingModes | ErrorIncompatibleStreamingModes, - - LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/ErrorIncompatibleStreamingModes), -}; - -static bool isStreamingCompatible(const FunctionDecl *fd) { - if (const auto *fpt = fd->getType()->getAs<FunctionProtoType>()) - return fpt->getAArch64SMEAttributes() & - clang::FunctionType::SME_PStateSMCompatibleMask; - return false; -} - -/// Determines if there are any Arm SME ABI issues with inlining \p Callee into -/// \p Caller. Returns the issue (if any) in the ArmSMEInlinability bit enum. -static ArmSMEInlinability getArmSMEInlinability(const FunctionDecl *caller, - const FunctionDecl *callee) { - bool callerIsStreaming = - clang::IsArmStreamingFunction(caller, /*IncludeLocallyStreaming=*/true); - bool calleeIsStreaming = - clang::IsArmStreamingFunction(callee, /*IncludeLocallyStreaming=*/true); - bool callerIsStreamingCompatible = isStreamingCompatible(caller); - bool calleeIsStreamingCompatible = isStreamingCompatible(callee); - - ArmSMEInlinability inlinability = ArmSMEInlinability::Ok; - - if (!calleeIsStreamingCompatible && - (callerIsStreaming != calleeIsStreaming || callerIsStreamingCompatible)) { - if (calleeIsStreaming) - inlinability |= ArmSMEInlinability::ErrorIncompatibleStreamingModes; - else - inlinability |= ArmSMEInlinability::WarnIncompatibleStreamingModes; - } - if (auto *newAttr = callee->getAttr<ArmNewAttr>()) { - if (newAttr->isNewZA()) - inlinability |= ArmSMEInlinability::ErrorCalleeRequiresNewZA; - if (newAttr->isNewZT0()) - inlinability |= ArmSMEInlinability::ErrorCalleeRequiresNewZT0; - } - - return inlinability; -} - bool AArch64TargetCIRGenInfo::wouldInliningViolateFunctionCallABI( const FunctionDecl *caller, const FunctionDecl *callee) const { return caller && callee && - getArmSMEInlinability(caller, callee) != ArmSMEInlinability::Ok; + CodeGenUtils::getArmSMEInlinability(caller, callee) != + CodeGenUtils::ArmSMEInlinability::Ok; } std::unique_ptr<TargetCIRGenInfo> diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp index 23a4e5c0ce9ec..e76d7fa21b807 100644 --- a/clang/lib/CodeGen/Targets/AArch64.cpp +++ b/clang/lib/CodeGen/Targets/AArch64.cpp @@ -10,6 +10,7 @@ #include "TargetInfo.h" #include "clang/AST/Decl.h" #include "clang/Basic/DiagnosticFrontend.h" +#include "clang/CodeGenUtils/TargetUtils.h" #include "llvm/TargetParser/AArch64TargetParser.h" using namespace clang; @@ -1191,13 +1192,6 @@ RValue AArch64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr, CharUnits::fromQuantity(8), AllowHigherAlign, Slot); } -static bool isStreamingCompatible(const FunctionDecl *F) { - if (const auto *T = F->getType()->getAs<FunctionProtoType>()) - return T->getAArch64SMEAttributes() & - FunctionType::SME_PStateSMCompatibleMask; - return false; -} - // Report an error if an argument or return value of type Ty would need to be // passed in a floating-point register. static void diagnoseIfNeedsFPReg(DiagnosticsEngine &Diags, @@ -1233,74 +1227,37 @@ void AArch64TargetCodeGenInfo::checkFunctionABI( } } -enum class ArmSMEInlinability : uint8_t { - Ok = 0, - ErrorCalleeRequiresNewZA = 1 << 0, - ErrorCalleeRequiresNewZT0 = 1 << 1, - WarnIncompatibleStreamingModes = 1 << 2, - ErrorIncompatibleStreamingModes = 1 << 3, - - IncompatibleStreamingModes = - WarnIncompatibleStreamingModes | ErrorIncompatibleStreamingModes, - - LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/ErrorIncompatibleStreamingModes), -}; - -/// Determines if there are any Arm SME ABI issues with inlining \p Callee into -/// \p Caller. Returns the issue (if any) in the ArmSMEInlinability bit enum. -static ArmSMEInlinability GetArmSMEInlinability(const FunctionDecl *Caller, - const FunctionDecl *Callee) { - bool CallerIsStreaming = - IsArmStreamingFunction(Caller, /*IncludeLocallyStreaming=*/true); - bool CalleeIsStreaming = - IsArmStreamingFunction(Callee, /*IncludeLocallyStreaming=*/true); - bool CallerIsStreamingCompatible = isStreamingCompatible(Caller); - bool CalleeIsStreamingCompatible = isStreamingCompatible(Callee); - - ArmSMEInlinability Inlinability = ArmSMEInlinability::Ok; - - if (!CalleeIsStreamingCompatible && - (CallerIsStreaming != CalleeIsStreaming || CallerIsStreamingCompatible)) { - if (CalleeIsStreaming) - Inlinability |= ArmSMEInlinability::ErrorIncompatibleStreamingModes; - else - Inlinability |= ArmSMEInlinability::WarnIncompatibleStreamingModes; - } - if (auto *NewAttr = Callee->getAttr<ArmNewAttr>()) { - if (NewAttr->isNewZA()) - Inlinability |= ArmSMEInlinability::ErrorCalleeRequiresNewZA; - if (NewAttr->isNewZT0()) - Inlinability |= ArmSMEInlinability::ErrorCalleeRequiresNewZT0; - } - - return Inlinability; -} - void AArch64TargetCodeGenInfo::checkFunctionCallABIStreaming( CodeGenModule &CGM, SourceLocation CallLoc, const FunctionDecl *Caller, const FunctionDecl *Callee) const { if (!Caller || !Callee || !Callee->hasAttr<AlwaysInlineAttr>()) return; - ArmSMEInlinability Inlinability = GetArmSMEInlinability(Caller, Callee); + CodeGenUtils::ArmSMEInlinability Inlinability = + CodeGenUtils::getArmSMEInlinability(Caller, Callee); - if ((Inlinability & ArmSMEInlinability::IncompatibleStreamingModes) != - ArmSMEInlinability::Ok) + if ((Inlinability & + CodeGenUtils::ArmSMEInlinability::IncompatibleStreamingModes) != + CodeGenUtils::ArmSMEInlinability::Ok) CGM.getDiags().Report( CallLoc, - (Inlinability & ArmSMEInlinability::ErrorIncompatibleStreamingModes) == - ArmSMEInlinability::ErrorIncompatibleStreamingModes + (Inlinability & + CodeGenUtils::ArmSMEInlinability::ErrorIncompatibleStreamingModes) == + CodeGenUtils::ArmSMEInlinability:: + ErrorIncompatibleStreamingModes ? diag::err_function_always_inline_attribute_mismatch : diag::warn_function_always_inline_attribute_mismatch) << Caller->getDeclName() << Callee->getDeclName() << "streaming"; - if ((Inlinability & ArmSMEInlinability::ErrorCalleeRequiresNewZA) == - ArmSMEInlinability::ErrorCalleeRequiresNewZA) + if ((Inlinability & + CodeGenUtils::ArmSMEInlinability::ErrorCalleeRequiresNewZA) == + CodeGenUtils::ArmSMEInlinability::ErrorCalleeRequiresNewZA) CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_new_za) << Callee->getDeclName(); - if ((Inlinability & ArmSMEInlinability::ErrorCalleeRequiresNewZT0) == - ArmSMEInlinability::ErrorCalleeRequiresNewZT0) + if ((Inlinability & + CodeGenUtils::ArmSMEInlinability::ErrorCalleeRequiresNewZT0) == + CodeGenUtils::ArmSMEInlinability::ErrorCalleeRequiresNewZT0) CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_new_zt0) << Callee->getDeclName(); } @@ -1339,7 +1296,8 @@ void AArch64TargetCodeGenInfo::checkFunctionCallABI(CodeGenModule &CGM, bool AArch64TargetCodeGenInfo::wouldInliningViolateFunctionCallABI( const FunctionDecl *Caller, const FunctionDecl *Callee) const { return Caller && Callee && - GetArmSMEInlinability(Caller, Callee) != ArmSMEInlinability::Ok; + CodeGenUtils::getArmSMEInlinability(Caller, Callee) != + CodeGenUtils::ArmSMEInlinability::Ok; } void AArch64ABIInfo::appendAttributeMangling(TargetClonesAttr *Attr, diff --git a/clang/lib/CodeGenUtils/CMakeLists.txt b/clang/lib/CodeGenUtils/CMakeLists.txt index 2052ca13f6e5d..7fb94a994bfed 100644 --- a/clang/lib/CodeGenUtils/CMakeLists.txt +++ b/clang/lib/CodeGenUtils/CMakeLists.txt @@ -17,6 +17,7 @@ add_clang_library(clangCodeGenUtils ModuleUtils.cpp RecordLayoutUtils.cpp StmtUtils.cpp + TargetUtils.cpp LINK_LIBS clangAST diff --git a/clang/lib/CodeGenUtils/TargetUtils.cpp b/clang/lib/CodeGenUtils/TargetUtils.cpp new file mode 100644 index 0000000000000..2561d6760773b --- /dev/null +++ b/clang/lib/CodeGenUtils/TargetUtils.cpp @@ -0,0 +1,50 @@ +//===--- TargetUtils.cpp - Shared target-specific AST queries ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "clang/CodeGenUtils/TargetUtils.h" +#include "clang/AST/Attr.h" +#include "clang/AST/Decl.h" + +namespace clang::CodeGenUtils { + +static bool isStreamingCompatible(const FunctionDecl *F) { + if (const auto *T = F->getType()->getAs<FunctionProtoType>()) + return T->getAArch64SMEAttributes() & + FunctionType::SME_PStateSMCompatibleMask; + return false; +} + +ArmSMEInlinability getArmSMEInlinability(const FunctionDecl *Caller, + const FunctionDecl *Callee) { + bool CallerIsStreaming = + IsArmStreamingFunction(Caller, /*IncludeLocallyStreaming=*/true); + bool CalleeIsStreaming = + IsArmStreamingFunction(Callee, /*IncludeLocallyStreaming=*/true); + bool CallerIsStreamingCompatible = isStreamingCompatible(Caller); + bool CalleeIsStreamingCompatible = isStreamingCompatible(Callee); + + ArmSMEInlinability Inlinability = ArmSMEInlinability::Ok; + + if (!CalleeIsStreamingCompatible && + (CallerIsStreaming != CalleeIsStreaming || CallerIsStreamingCompatible)) { + if (CalleeIsStreaming) + Inlinability |= ArmSMEInlinability::ErrorIncompatibleStreamingModes; + else + Inlinability |= ArmSMEInlinability::WarnIncompatibleStreamingModes; + } + if (auto *NewAttr = Callee->getAttr<ArmNewAttr>()) { + if (NewAttr->isNewZA()) + Inlinability |= ArmSMEInlinability::ErrorCalleeRequiresNewZA; + if (NewAttr->isNewZT0()) + Inlinability |= ArmSMEInlinability::ErrorCalleeRequiresNewZT0; + } + + return Inlinability; +} + +} // namespace clang::CodeGenUtils _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
