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".
140 lines
3.9 KiB
C++
140 lines
3.9 KiB
C++
#include "TargetInfo.h"
|
|
#include "ABIInfo.h"
|
|
#include "CIRGenFunction.h"
|
|
#include "CIRGenModule.h"
|
|
#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
|
|
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
|
|
#include "clang/CIR/Dialect/IR/CIRDialect.h"
|
|
|
|
using namespace clang;
|
|
using namespace clang::CIRGen;
|
|
|
|
bool clang::CIRGen::isEmptyRecordForLayout(const ASTContext &context,
|
|
QualType t) {
|
|
const auto *rd = t->getAsRecordDecl();
|
|
if (!rd)
|
|
return false;
|
|
|
|
// If this is a C++ record, check the bases first.
|
|
if (const CXXRecordDecl *cxxrd = dyn_cast<CXXRecordDecl>(rd)) {
|
|
if (cxxrd->isDynamicClass())
|
|
return false;
|
|
|
|
for (const auto &i : cxxrd->bases())
|
|
if (!isEmptyRecordForLayout(context, i.getType()))
|
|
return false;
|
|
}
|
|
|
|
for (const auto *i : rd->fields())
|
|
if (!isEmptyFieldForLayout(context, i))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool clang::CIRGen::isEmptyFieldForLayout(const ASTContext &context,
|
|
const FieldDecl *fd) {
|
|
if (fd->isZeroLengthBitField())
|
|
return true;
|
|
|
|
if (fd->isUnnamedBitField())
|
|
return false;
|
|
|
|
return isEmptyRecordForLayout(context, fd->getType());
|
|
}
|
|
|
|
namespace {
|
|
|
|
class AMDGPUABIInfo : public ABIInfo {
|
|
public:
|
|
AMDGPUABIInfo(CIRGenTypes &cgt) : ABIInfo(cgt) {}
|
|
};
|
|
|
|
class AMDGPUTargetCIRGenInfo : public TargetCIRGenInfo {
|
|
public:
|
|
AMDGPUTargetCIRGenInfo(CIRGenTypes &cgt)
|
|
: TargetCIRGenInfo(std::make_unique<AMDGPUABIInfo>(cgt)) {}
|
|
|
|
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())) {
|
|
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())) {
|
|
gv.setGlobalVisibility(cir::VisibilityKind::Protected);
|
|
gv.setDSOLocal(true);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
} // namespace
|
|
|
|
namespace {
|
|
|
|
class X8664ABIInfo : public ABIInfo {
|
|
public:
|
|
X8664ABIInfo(CIRGenTypes &cgt) : ABIInfo(cgt) {}
|
|
};
|
|
|
|
class X8664TargetCIRGenInfo : public TargetCIRGenInfo {
|
|
public:
|
|
X8664TargetCIRGenInfo(CIRGenTypes &cgt)
|
|
: TargetCIRGenInfo(std::make_unique<X8664ABIInfo>(cgt)) {}
|
|
};
|
|
|
|
} // namespace
|
|
|
|
namespace {
|
|
|
|
class NVPTXABIInfo : public ABIInfo {
|
|
public:
|
|
NVPTXABIInfo(CIRGenTypes &cgt) : ABIInfo(cgt) {}
|
|
};
|
|
|
|
class NVPTXTargetCIRGenInfo : public TargetCIRGenInfo {
|
|
public:
|
|
NVPTXTargetCIRGenInfo(CIRGenTypes &cgt)
|
|
: TargetCIRGenInfo(std::make_unique<NVPTXABIInfo>(cgt)) {}
|
|
};
|
|
} // namespace
|
|
|
|
std::unique_ptr<TargetCIRGenInfo>
|
|
clang::CIRGen::createAMDGPUTargetCIRGenInfo(CIRGenTypes &cgt) {
|
|
return std::make_unique<AMDGPUTargetCIRGenInfo>(cgt);
|
|
}
|
|
|
|
std::unique_ptr<TargetCIRGenInfo>
|
|
clang::CIRGen::createNVPTXTargetCIRGenInfo(CIRGenTypes &cgt) {
|
|
return std::make_unique<NVPTXTargetCIRGenInfo>(cgt);
|
|
}
|
|
|
|
std::unique_ptr<TargetCIRGenInfo>
|
|
clang::CIRGen::createX8664TargetCIRGenInfo(CIRGenTypes &cgt) {
|
|
return std::make_unique<X8664TargetCIRGenInfo>(cgt);
|
|
}
|
|
|
|
ABIInfo::~ABIInfo() noexcept = default;
|
|
|
|
bool TargetCIRGenInfo::isNoProtoCallVariadic(
|
|
const FunctionNoProtoType *fnType) const {
|
|
// The following conventions are known to require this to be false:
|
|
// x86_stdcall
|
|
// MIPS
|
|
// For everything else, we just prefer false unless we opt out.
|
|
return false;
|
|
}
|
|
|
|
clang::LangAS
|
|
TargetCIRGenInfo::getGlobalVarAddressSpace(CIRGenModule &cgm,
|
|
const clang::VarDecl *d) const {
|
|
assert(!cgm.getLangOpts().OpenCL &&
|
|
!(cgm.getLangOpts().CUDA && cgm.getLangOpts().CUDAIsDevice) &&
|
|
"Address space agnostic languages only");
|
|
return d ? d->getType().getAddressSpace() : LangAS::Default;
|
|
}
|