[llvm-branch-commits] [clang] [CIR][CodeGen][NFC] Share the AArch64/AMDGPU target predicates (PR #223425)

Henrich Lauko via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Mon Sep 21 06:36:26 PDT 2026


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 <hlauko at nvidia.com>
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



More information about the llvm-branch-commits mailing list