https://github.com/xlauko updated https://github.com/llvm/llvm-project/pull/223425
>From cbae5ebc3609a8dbd50741fa4d92d84d4d83422c Mon Sep 17 00:00:00 2001 From: Henrich Lauko <[email protected]> Date: Mon, 14 Sep 2026 13:52:34 +0000 Subject: [PATCH] [CIR][CodeGen][NFC] Share the AArch64/AMDGPU target predicates Three AST-only target predicates that both CodeGens duplicate. None of them touch llvm::Type, llvm::Value or the CIR dialect. requiresAMDGPUProtectedVisibility now takes a bool saying whether the global currently has hidden visibility. Classic passed an llvm::GlobalValue and CIR a cir::VisibilityKind, and both only compared it against hidden. NFC. --- .../include/clang/CodeGenUtils/TargetUtils.h | 63 +++++++++++++ .../lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp | 40 +-------- clang/lib/CIR/CodeGen/TargetInfo.cpp | 8 +- clang/lib/CIR/CodeGen/TargetInfo.h | 4 - clang/lib/CIR/CodeGen/Targets/AArch64.cpp | 55 +----------- clang/lib/CIR/CodeGen/Targets/AMDGPU.cpp | 14 --- clang/lib/CodeGen/TargetBuiltins/ARM.cpp | 37 +------- clang/lib/CodeGen/Targets/AArch64.cpp | 78 ++++------------ clang/lib/CodeGen/Targets/AMDGPU.cpp | 18 +--- clang/lib/CodeGenUtils/CMakeLists.txt | 1 + clang/lib/CodeGenUtils/TargetUtils.cpp | 89 +++++++++++++++++++ 11 files changed, 188 insertions(+), 219 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..a44541c572590 --- /dev/null +++ b/clang/include/clang/CodeGenUtils/TargetUtils.h @@ -0,0 +1,63 @@ +//===--- 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 "llvm/ADT/BitmaskEnum.h" + +#include <cstdint> + +namespace clang { +class Decl; +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), +}; + +// Enable the bitwise operators on ArmSMEInlinability. +LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); + +/// 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); + +/// Returns whether the Neon builtin \p BuiltinID takes a trailing argument +/// that discriminates the operand type. This should be kept consistent with +/// the logic in Sema. +/// TODO: Make this return false for SISD builtins. +bool hasExtraNeonArgument(unsigned BuiltinID); + +/// Returns whether \p D must be given protected visibility on AMDGPU. +/// \p HasHiddenVisibility is whether the emitted global currently has hidden +/// visibility. +bool requiresAMDGPUProtectedVisibility(const Decl *D, bool HasHiddenVisibility); + +} // namespace clang::CodeGenUtils + +#endif // LLVM_CLANG_CODEGENUTILS_TARGETUTILS_H diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp index d681c390fe9de..e55d1790c2685 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp @@ -16,6 +16,7 @@ #include "clang/Basic/TargetBuiltins.h" #include "clang/CIR/Dialect/IR/CIRTypes.h" #include "clang/CIR/MissingFeatures.h" +#include "clang/CodeGenUtils/TargetUtils.h" // TODO(cir): once all builtins are covered, decide whether we still // need to use LLVM intrinsics or if there's a better approach to follow. Right @@ -90,43 +91,6 @@ static llvm::StringRef getLLVMIntrNameNoPrefix(llvm::Intrinsic::ID intrID) { return llvmIntrName.drop_front(/*strlen("llvm.")=*/5); } -//===----------------------------------------------------------------------===// -// NEON helpers -//===----------------------------------------------------------------------===// -/// Return true if BuiltinID is an overloaded Neon intrinsic with an extra -/// argument that specifies the vector type. The additional argument is meant -/// for Sema checking (see `CheckNeonBuiltinFunctionCall`) and this function -/// should be kept consistent with the logic in Sema. -/// TODO: Make this return false for SISD builtins. -/// TODO(cir): Share this with ARM.cpp -static bool hasExtraNeonArgument(unsigned builtinID) { - // Required by the headers included below, but not in this particular - // function. - [[maybe_unused]] int PtrArgNum = -1; - [[maybe_unused]] bool HasConstPtr = false; - - // The mask encodes the type. We don't care about the actual value. Instead, - // we just check whether its been set. - uint64_t mask = 0; - switch (builtinID) { -#define GET_NEON_OVERLOAD_CHECK -#include "clang/Basic/arm_fp16.inc" -#include "clang/Basic/arm_neon.inc" -#undef GET_NEON_OVERLOAD_CHECK - // Non-neon builtins for controling VFP that take extra argument for - // discriminating the type. - case ARM::BI__builtin_arm_vcvtr_f: - case ARM::BI__builtin_arm_vcvtr_d: - mask = 1; - } - switch (builtinID) { - default: - break; - } - - return mask != 0; -} - static cir::VectorType getFloatNeonType(CIRGenFunction &cgf, NeonTypeFlags intTypeFlags) { int isQuad = intTypeFlags.isQuad(); @@ -2688,7 +2652,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, // Skip extra arguments used to discriminate vector types and that are // intended for Sema checking. - bool hasExtraArg = hasExtraNeonArgument(builtinID); + bool hasExtraArg = CodeGenUtils::hasExtraNeonArgument(builtinID); unsigned numArgs = expr->getNumArgs() - (hasExtraArg ? 1 : 0); for (unsigned i = 0, e = numArgs; i != e; i++) { if (i == 0) { diff --git a/clang/lib/CIR/CodeGen/TargetInfo.cpp b/clang/lib/CIR/CodeGen/TargetInfo.cpp index 57bc5f167e460..b648ca1f2cd74 100644 --- a/clang/lib/CIR/CodeGen/TargetInfo.cpp +++ b/clang/lib/CIR/CodeGen/TargetInfo.cpp @@ -7,6 +7,7 @@ #include "clang/CIR/Dialect/IR/CIRAttrs.h" #include "clang/CIR/Dialect/IR/CIRDialect.h" #include "clang/CIR/MissingFeatures.h" +#include "clang/CodeGenUtils/TargetUtils.h" using namespace clang; using namespace clang::CIRGen; @@ -91,13 +92,16 @@ class AMDGPUTargetCIRGenInfo : public TargetCIRGenInfo { void setTargetAttributes(const clang::Decl *decl, mlir::Operation *global, CIRGenModule &cgm) const override { if (auto func = mlir::dyn_cast<cir::FuncOp>(global)) { - if (requiresAMDGPUProtectedVisibility(decl, func.getGlobalVisibility())) { + if (CodeGenUtils::requiresAMDGPUProtectedVisibility( + decl, + func.getGlobalVisibility() == cir::VisibilityKind::Hidden)) { func.setGlobalVisibility(cir::VisibilityKind::Protected); func.setDSOLocal(true); } setAMDGPUTargetFunctionAttributes(decl, func, cgm); } else if (auto gv = mlir::dyn_cast<cir::GlobalOp>(global)) { - if (requiresAMDGPUProtectedVisibility(decl, gv.getGlobalVisibility())) { + if (CodeGenUtils::requiresAMDGPUProtectedVisibility( + decl, gv.getGlobalVisibility() == cir::VisibilityKind::Hidden)) { gv.setGlobalVisibility(cir::VisibilityKind::Protected); gv.setDSOLocal(true); } diff --git a/clang/lib/CIR/CodeGen/TargetInfo.h b/clang/lib/CIR/CodeGen/TargetInfo.h index e094fa53561f5..affb09f3c85d3 100644 --- a/clang/lib/CIR/CodeGen/TargetInfo.h +++ b/clang/lib/CIR/CodeGen/TargetInfo.h @@ -179,10 +179,6 @@ class TargetCIRGenInfo { std::unique_ptr<TargetCIRGenInfo> createAMDGPUTargetCIRGenInfo(CIRGenTypes &cgt); -/// Check if AMDGPU protected visibility is required. -bool requiresAMDGPUProtectedVisibility(const clang::Decl *d, - cir::VisibilityKind visibility); - /// Set AMDGPU-specific function attributes for HIP kernels. void setAMDGPUTargetFunctionAttributes(const clang::Decl *decl, cir::FuncOp func, CIRGenModule &cgm); 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/CIR/CodeGen/Targets/AMDGPU.cpp b/clang/lib/CIR/CodeGen/Targets/AMDGPU.cpp index 7f1d903853660..5f3b848ed9cb6 100644 --- a/clang/lib/CIR/CodeGen/Targets/AMDGPU.cpp +++ b/clang/lib/CIR/CodeGen/Targets/AMDGPU.cpp @@ -23,20 +23,6 @@ using namespace clang; using namespace clang::CIRGen; -bool clang::CIRGen::requiresAMDGPUProtectedVisibility( - const Decl *d, cir::VisibilityKind visibility) { - if (visibility != cir::VisibilityKind::Hidden) - return false; - - return !d->hasAttr<OMPDeclareTargetDeclAttr>() && - (d->hasAttr<DeviceKernelAttr>() || - (isa<FunctionDecl>(d) && d->hasAttr<CUDAGlobalAttr>()) || - (isa<VarDecl>(d) && - (d->hasAttr<CUDADeviceAttr>() || d->hasAttr<CUDAConstantAttr>() || - cast<VarDecl>(d)->getType()->isCUDADeviceBuiltinSurfaceType() || - cast<VarDecl>(d)->getType()->isCUDADeviceBuiltinTextureType()))); -} - namespace { /// Handle amdgpu-flat-work-group-size attribute. diff --git a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp index 527bfd752e018..0c39e8b26fc9f 100644 --- a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp @@ -16,6 +16,7 @@ #include "TargetInfo.h" #include "clang/Basic/AArch64CodeGenUtils.h" #include "clang/Basic/TargetBuiltins.h" +#include "clang/CodeGenUtils/TargetUtils.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/IntrinsicsAArch64.h" #include "llvm/IR/IntrinsicsARM.h" @@ -2065,38 +2066,6 @@ static Value *EmitRangePrefetchBuiltin(CodeGenFunction &CGF, unsigned BuiltinID, Ops); } -/// Return true if BuiltinID is an overloaded Neon intrinsic with an extra -/// argument that specifies the vector type. The additional argument is meant -/// for Sema checking (see `CheckNeonBuiltinFunctionCall`) and this function -/// should be kept consistent with the logic in Sema. -/// TODO: Make this return false for SISD builtins. -static bool HasExtraNeonArgument(unsigned BuiltinID) { - // Required by the headers included below, but not in this particular - // function. - [[maybe_unused]] int PtrArgNum = -1; - [[maybe_unused]] bool HasConstPtr = false; - - // The mask encodes the type. We don't care about the actual value. Instead, - // we just check whether its been set. - uint64_t mask = 0; - switch (BuiltinID) { -#define GET_NEON_OVERLOAD_CHECK -#include "clang/Basic/arm_fp16.inc" -#include "clang/Basic/arm_neon.inc" -#undef GET_NEON_OVERLOAD_CHECK - // Non-neon builtins for controling VFP that take extra argument for - // discriminating the type. - case ARM::BI__builtin_arm_vcvtr_f: - case ARM::BI__builtin_arm_vcvtr_d: - mask = 1; - } - - if (mask) - return true; - - return false; -} - Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue, @@ -2476,7 +2445,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, Address PtrOp0 = Address::invalid(); Address PtrOp1 = Address::invalid(); SmallVector<Value*, 4> Ops; - bool HasExtraArg = HasExtraNeonArgument(BuiltinID); + bool HasExtraArg = CodeGenUtils::hasExtraNeonArgument(BuiltinID); unsigned NumArgs = E->getNumArgs() - (HasExtraArg ? 1 : 0); for (unsigned i = 0, e = NumArgs; i != e; i++) { if (i == 0) { @@ -5305,7 +5274,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, // Note the assumption that SISD intrinsics do not contain extra arguments. // TODO: Fold this into a single function call instead of, effectively, two // separate checks. - bool HasExtraArg = !IsSISD && HasExtraNeonArgument(BuiltinID); + bool HasExtraArg = !IsSISD && CodeGenUtils::hasExtraNeonArgument(BuiltinID); unsigned NumArgs = E->getNumArgs() - (HasExtraArg ? 1 : 0); for (unsigned i = 0, e = NumArgs; i != e; i++) { if (i == 0) { 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/CodeGen/Targets/AMDGPU.cpp b/clang/lib/CodeGen/Targets/AMDGPU.cpp index 0b5ed1898f138..607442c899f87 100644 --- a/clang/lib/CodeGen/Targets/AMDGPU.cpp +++ b/clang/lib/CodeGen/Targets/AMDGPU.cpp @@ -9,6 +9,7 @@ #include "ABIInfoImpl.h" #include "TargetInfo.h" #include "clang/AST/DeclCXX.h" +#include "clang/CodeGenUtils/TargetUtils.h" #include "llvm/ADT/StringExtras.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MemoryModelRelaxationAnnotations.h" @@ -325,20 +326,6 @@ class AMDGPUTargetCodeGenInfo : public TargetCodeGenInfo { }; } -static bool requiresAMDGPUProtectedVisibility(const Decl *D, - llvm::GlobalValue *GV) { - if (GV->getVisibility() != llvm::GlobalValue::HiddenVisibility) - return false; - - return !D->hasAttr<OMPDeclareTargetDeclAttr>() && - (D->hasAttr<DeviceKernelAttr>() || - (isa<FunctionDecl>(D) && D->hasAttr<CUDAGlobalAttr>()) || - (isa<VarDecl>(D) && - (D->hasAttr<CUDADeviceAttr>() || D->hasAttr<CUDAConstantAttr>() || - cast<VarDecl>(D)->getType()->isCUDADeviceBuiltinSurfaceType() || - cast<VarDecl>(D)->getType()->isCUDADeviceBuiltinTextureType()))); -} - void AMDGPUTargetCodeGenInfo::setFunctionDeclAttributes( const FunctionDecl *FD, llvm::Function *F, CodeGenModule &M) const { const auto *ReqdWGS = @@ -454,7 +441,8 @@ void AMDGPUTargetCodeGenInfo::setFunctionDeclAttributes( void AMDGPUTargetCodeGenInfo::setTargetAttributes( const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const { - if (requiresAMDGPUProtectedVisibility(D, GV)) { + if (CodeGenUtils::requiresAMDGPUProtectedVisibility( + D, GV->getVisibility() == llvm::GlobalValue::HiddenVisibility)) { GV->setVisibility(llvm::GlobalValue::ProtectedVisibility); GV->setDSOLocal(true); } diff --git a/clang/lib/CodeGenUtils/CMakeLists.txt b/clang/lib/CodeGenUtils/CMakeLists.txt index f46ac572a0ce9..edd32da5b5f7c 100644 --- a/clang/lib/CodeGenUtils/CMakeLists.txt +++ b/clang/lib/CodeGenUtils/CMakeLists.txt @@ -12,6 +12,7 @@ add_clang_library(clangCodeGenUtils ItaniumCXXABIUtils.cpp ModuleUtils.cpp RecordLayoutUtils.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..f72218f4dda2d --- /dev/null +++ b/clang/lib/CodeGenUtils/TargetUtils.cpp @@ -0,0 +1,89 @@ +//===--- 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" +#include "clang/Basic/TargetBuiltins.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; +} + +bool hasExtraNeonArgument(unsigned BuiltinID) { + // Required by the headers included below, but not in this particular + // function. + [[maybe_unused]] int PtrArgNum = -1; + [[maybe_unused]] bool HasConstPtr = false; + + // The mask encodes the type. We don't care about the actual value. Instead, + // we just check whether its been set. + uint64_t mask = 0; + switch (BuiltinID) { +#define GET_NEON_OVERLOAD_CHECK +#include "clang/Basic/arm_fp16.inc" +#include "clang/Basic/arm_neon.inc" +#undef GET_NEON_OVERLOAD_CHECK + // Non-neon builtins for controling VFP that take extra argument for + // discriminating the type. + case ARM::BI__builtin_arm_vcvtr_f: + case ARM::BI__builtin_arm_vcvtr_d: + mask = 1; + } + + return mask != 0; +} + +bool requiresAMDGPUProtectedVisibility(const Decl *D, + bool HasHiddenVisibility) { + if (!HasHiddenVisibility) + return false; + + return !D->hasAttr<OMPDeclareTargetDeclAttr>() && + (D->hasAttr<DeviceKernelAttr>() || + (isa<FunctionDecl>(D) && D->hasAttr<CUDAGlobalAttr>()) || + (isa<VarDecl>(D) && + (D->hasAttr<CUDADeviceAttr>() || D->hasAttr<CUDAConstantAttr>() || + cast<VarDecl>(D)->getType()->isCUDADeviceBuiltinSurfaceType() || + cast<VarDecl>(D)->getType()->isCUDADeviceBuiltinTextureType()))); +} + +} // namespace clang::CodeGenUtils _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
