1*06c3fb27SDimitry Andric //===- TCE.cpp ------------------------------------------------------------===//
2*06c3fb27SDimitry Andric //
3*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*06c3fb27SDimitry Andric //
7*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
8*06c3fb27SDimitry Andric
9*06c3fb27SDimitry Andric #include "ABIInfoImpl.h"
10*06c3fb27SDimitry Andric #include "TargetInfo.h"
11*06c3fb27SDimitry Andric
12*06c3fb27SDimitry Andric using namespace clang;
13*06c3fb27SDimitry Andric using namespace clang::CodeGen;
14*06c3fb27SDimitry Andric
15*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
16*06c3fb27SDimitry Andric // TCE ABI Implementation (see http://tce.cs.tut.fi). Uses mostly the defaults.
17*06c3fb27SDimitry Andric // Currently subclassed only to implement custom OpenCL C function attribute
18*06c3fb27SDimitry Andric // handling.
19*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
20*06c3fb27SDimitry Andric
21*06c3fb27SDimitry Andric namespace {
22*06c3fb27SDimitry Andric
23*06c3fb27SDimitry Andric class TCETargetCodeGenInfo : public TargetCodeGenInfo {
24*06c3fb27SDimitry Andric public:
TCETargetCodeGenInfo(CodeGenTypes & CGT)25*06c3fb27SDimitry Andric TCETargetCodeGenInfo(CodeGenTypes &CGT)
26*06c3fb27SDimitry Andric : TargetCodeGenInfo(std::make_unique<DefaultABIInfo>(CGT)) {}
27*06c3fb27SDimitry Andric
28*06c3fb27SDimitry Andric void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
29*06c3fb27SDimitry Andric CodeGen::CodeGenModule &M) const override;
30*06c3fb27SDimitry Andric };
31*06c3fb27SDimitry Andric
setTargetAttributes(const Decl * D,llvm::GlobalValue * GV,CodeGen::CodeGenModule & M) const32*06c3fb27SDimitry Andric void TCETargetCodeGenInfo::setTargetAttributes(
33*06c3fb27SDimitry Andric const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const {
34*06c3fb27SDimitry Andric if (GV->isDeclaration())
35*06c3fb27SDimitry Andric return;
36*06c3fb27SDimitry Andric const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
37*06c3fb27SDimitry Andric if (!FD) return;
38*06c3fb27SDimitry Andric
39*06c3fb27SDimitry Andric llvm::Function *F = cast<llvm::Function>(GV);
40*06c3fb27SDimitry Andric
41*06c3fb27SDimitry Andric if (M.getLangOpts().OpenCL) {
42*06c3fb27SDimitry Andric if (FD->hasAttr<OpenCLKernelAttr>()) {
43*06c3fb27SDimitry Andric // OpenCL C Kernel functions are not subject to inlining
44*06c3fb27SDimitry Andric F->addFnAttr(llvm::Attribute::NoInline);
45*06c3fb27SDimitry Andric const ReqdWorkGroupSizeAttr *Attr = FD->getAttr<ReqdWorkGroupSizeAttr>();
46*06c3fb27SDimitry Andric if (Attr) {
47*06c3fb27SDimitry Andric // Convert the reqd_work_group_size() attributes to metadata.
48*06c3fb27SDimitry Andric llvm::LLVMContext &Context = F->getContext();
49*06c3fb27SDimitry Andric llvm::NamedMDNode *OpenCLMetadata =
50*06c3fb27SDimitry Andric M.getModule().getOrInsertNamedMetadata(
51*06c3fb27SDimitry Andric "opencl.kernel_wg_size_info");
52*06c3fb27SDimitry Andric
53*06c3fb27SDimitry Andric SmallVector<llvm::Metadata *, 5> Operands;
54*06c3fb27SDimitry Andric Operands.push_back(llvm::ConstantAsMetadata::get(F));
55*06c3fb27SDimitry Andric
56*06c3fb27SDimitry Andric Operands.push_back(
57*06c3fb27SDimitry Andric llvm::ConstantAsMetadata::get(llvm::Constant::getIntegerValue(
58*06c3fb27SDimitry Andric M.Int32Ty, llvm::APInt(32, Attr->getXDim()))));
59*06c3fb27SDimitry Andric Operands.push_back(
60*06c3fb27SDimitry Andric llvm::ConstantAsMetadata::get(llvm::Constant::getIntegerValue(
61*06c3fb27SDimitry Andric M.Int32Ty, llvm::APInt(32, Attr->getYDim()))));
62*06c3fb27SDimitry Andric Operands.push_back(
63*06c3fb27SDimitry Andric llvm::ConstantAsMetadata::get(llvm::Constant::getIntegerValue(
64*06c3fb27SDimitry Andric M.Int32Ty, llvm::APInt(32, Attr->getZDim()))));
65*06c3fb27SDimitry Andric
66*06c3fb27SDimitry Andric // Add a boolean constant operand for "required" (true) or "hint"
67*06c3fb27SDimitry Andric // (false) for implementing the work_group_size_hint attr later.
68*06c3fb27SDimitry Andric // Currently always true as the hint is not yet implemented.
69*06c3fb27SDimitry Andric Operands.push_back(
70*06c3fb27SDimitry Andric llvm::ConstantAsMetadata::get(llvm::ConstantInt::getTrue(Context)));
71*06c3fb27SDimitry Andric OpenCLMetadata->addOperand(llvm::MDNode::get(Context, Operands));
72*06c3fb27SDimitry Andric }
73*06c3fb27SDimitry Andric }
74*06c3fb27SDimitry Andric }
75*06c3fb27SDimitry Andric }
76*06c3fb27SDimitry Andric
77*06c3fb27SDimitry Andric }
78*06c3fb27SDimitry Andric
79*06c3fb27SDimitry Andric std::unique_ptr<TargetCodeGenInfo>
createTCETargetCodeGenInfo(CodeGenModule & CGM)80*06c3fb27SDimitry Andric CodeGen::createTCETargetCodeGenInfo(CodeGenModule &CGM) {
81*06c3fb27SDimitry Andric return std::make_unique<TCETargetCodeGenInfo>(CGM.getTypes());
82*06c3fb27SDimitry Andric }
83