Chaitanya 83451d8d4d
[CIR][AMDGPU] Add AMDGPU-specific function attributes for HIP kernels (#188007)
Upstreaming clangIR PR: https://github.com/llvm/clangir/pull/2091

This patch adds support for AMDGPU-specific function attributes for HIP
kernels

Added setTargetAttributes for AMDGPUTargetCIRGenInfo to set kernel
attributes
Added generic string attribute handler in amendFunction to translate
string-values with "cir." prefix function attributes to LLVM function
attributes
Follows OGCG AMDGPU implementation from
"clang/lib/CodeGen/Targets/AMDGPU.cpp".
2026-03-27 11:54:29 +05:30

154 lines
6.4 KiB
C++

//===---- TargetInfo.h - Encapsulate target details -------------*- 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
//
//===----------------------------------------------------------------------===//
//
// These classes wrap the information about a call or function definition used
// to handle ABI compliancy.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LIB_CIR_TARGETINFO_H
#define LLVM_CLANG_LIB_CIR_TARGETINFO_H
#include "ABIInfo.h"
#include "CIRGenTypes.h"
#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
#include "clang/Basic/AddressSpaces.h"
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
#include <memory>
#include <utility>
namespace clang::CIRGen {
/// isEmptyFieldForLayout - Return true if the field is "empty", that is,
/// either a zero-width bit-field or an isEmptyRecordForLayout.
bool isEmptyFieldForLayout(const ASTContext &context, const FieldDecl *fd);
/// isEmptyRecordForLayout - Return true if a structure contains only empty
/// base classes (per isEmptyRecordForLayout) and fields (per
/// isEmptyFieldForLayout). Note, C++ record fields are considered empty
/// if the [[no_unique_address]] attribute would have made them empty.
bool isEmptyRecordForLayout(const ASTContext &context, QualType t);
class CIRGenFunction;
class TargetCIRGenInfo {
std::unique_ptr<ABIInfo> info;
public:
TargetCIRGenInfo(std::unique_ptr<ABIInfo> info) : info(std::move(info)) {}
virtual ~TargetCIRGenInfo() = default;
/// Returns ABI info helper for the target.
const ABIInfo &getABIInfo() const { return *info; }
/// Get target favored AST address space of a global variable for languages
/// other than OpenCL and CUDA.
/// If \p d is nullptr, returns the default target favored address space
/// for global variable.
virtual clang::LangAS getGlobalVarAddressSpace(CIRGenModule &cgm,
const clang::VarDecl *d) const;
/// Get the address space for alloca.
virtual mlir::ptr::MemorySpaceAttrInterface getCIRAllocaAddressSpace() const {
return cir::LangAddressSpaceAttr::get(&info->cgt.getMLIRContext(),
cir::LangAddressSpace::Default);
}
/// Determine whether a call to an unprototyped functions under
/// the given calling convention should use the variadic
/// convention or the non-variadic convention.
///
/// There's a good reason to make a platform's variadic calling
/// convention be different from its non-variadic calling
/// convention: the non-variadic arguments can be passed in
/// registers (better for performance), and the variadic arguments
/// can be passed on the stack (also better for performance). If
/// this is done, however, unprototyped functions *must* use the
/// non-variadic convention, because C99 states that a call
/// through an unprototyped function type must succeed if the
/// function was defined with a non-variadic prototype with
/// compatible parameters. Therefore, splitting the conventions
/// makes it impossible to call a variadic function through an
/// unprototyped type. Since function prototypes came out in the
/// late 1970s, this is probably an acceptable trade-off.
/// Nonetheless, not all platforms are willing to make it, and in
/// particularly x86-64 bends over backwards to make the
/// conventions compatible.
///
/// The default is false. This is correct whenever:
/// - the conventions are exactly the same, because it does not
/// matter and the resulting IR will be somewhat prettier in
/// certain cases; or
/// - the conventions are substantively different in how they pass
/// arguments, because in this case using the variadic convention
/// will lead to C99 violations.
///
/// However, some platforms make the conventions identical except
/// for passing additional out-of-band information to a variadic
/// function: for example, x86-64 passes the number of SSE
/// arguments in %al. On these platforms, it is desirable to
/// call unprototyped functions using the variadic convention so
/// that unprototyped calls to varargs functions still succeed.
///
/// Relatedly, platforms which pass the fixed arguments to this:
/// A foo(B, C, D);
/// differently than they would pass them to this:
/// A foo(B, C, D, ...);
/// may need to adjust the debugger-support code in Sema to do the
/// right thing when calling a function with no know signature.
virtual bool isNoProtoCallVariadic(const FunctionNoProtoType *fnType) const;
/// Provides a convenient hook to handle extra target-specific attributes
/// for the given global.
/// In OG, the function receives an llvm::GlobalValue. However, functions
/// and global variables are separate types in Clang IR, so we use a general
/// mlir::Operation*.
virtual void setTargetAttributes(const clang::Decl *decl,
mlir::Operation *global,
CIRGenModule &module) const {}
virtual bool isScalarizableAsmOperand(CIRGenFunction &cgf,
mlir::Type ty) const {
return false;
}
/// Corrects the MLIR type for a given constraint and "usual"
/// type.
///
/// \returns A new MLIR type, possibly the same as the original
/// on success
virtual mlir::Type adjustInlineAsmType(CIRGenFunction &cgf,
llvm::StringRef constraint,
mlir::Type ty) const {
return ty;
}
};
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);
std::unique_ptr<TargetCIRGenInfo> createX8664TargetCIRGenInfo(CIRGenTypes &cgt);
std::unique_ptr<TargetCIRGenInfo> createNVPTXTargetCIRGenInfo(CIRGenTypes &cgt);
} // namespace clang::CIRGen
#endif // LLVM_CLANG_LIB_CIR_TARGETINFO_H