clang 24.0.0git
CIRGenSYCL.cpp
Go to the documentation of this file.
1//===--------- CIRGenSYCL.cpp - Emit CIR for SYCL kernels -----------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This contains code required for the generation of SYCL kernel code.
10//
11//===----------------------------------------------------------------------===//
12
13#include "CIRGenFunction.h"
14#include "CIRGenModule.h"
15
17#include "clang/AST/Attr.h"
18#include "clang/AST/Decl.h"
20#include "clang/AST/StmtSYCL.h"
21
22#include "llvm/Support/SaveAndRestore.h"
23
24using namespace clang;
25using namespace clang::CIRGen;
26
27mlir::LogicalResult
29 // SYCLKernelCallStmt nodes are only present in the bodies of functions
30 // declared with the sycl_kernel_entry_point attribute. ODR-use of such a
31 // function in code emitted during device compilation should be diagnosed.
32 // During device compilation, the offload kernel entry point is emitted in
33 // place of such a function (see CIRGenModule::emitDeferred), so this
34 // function is only reached during host compilation.
35 assert(!getLangOpts().SYCLIsDevice &&
36 "Attempt to emit a SYCL kernel call statement during device "
37 "compilation");
38
39 // During host compilation, the kernel launch statement is emitted in place
40 // of the original function body.
41 return emitStmt(s.getKernelLaunchStmt(), /*useCurrentScope=*/true);
42}
43
44// Emit the body of a SYCL kernel caller offload entry point. Mirrors the tail
45// of generateCode, but is driven by an OutlinedFunctionDecl and an explicit
46// argument list rather than a FunctionDecl.
48 const OutlinedFunctionDecl *outlinedFnDecl, cir::FuncOp funcOp,
49 cir::FuncType funcType, FunctionArgList &args) {
50 const Stmt *body = outlinedFnDecl->getBody();
51 SourceLocation loc = outlinedFnDecl->getLocation();
52 SourceRange bodyRange = body->getSourceRange();
53
54 // Synthesized entry point: no FunctionDecl, emitted with an empty GlobalDecl.
55 curGD = GlobalDecl();
56
57 SourceLocRAIIObject fnLoc{*this, loc.isValid() ? getLoc(loc)
58 : builder.getUnknownLoc()};
59
60 mlir::Location fusedLoc = getLoc(bodyRange);
61 mlir::Block *entryBB = funcOp.addEntryBlock();
62
64 {
65 LexicalScope lexScope(*this, fusedLoc, entryBB);
66 startFunction(GlobalDecl(), getContext().VoidTy, funcOp, funcType, args,
67 loc, bodyRange.getBegin());
68 if (mlir::failed(emitFunctionBody(body)))
69 return;
70 if (mlir::failed(funcOp.verifyBody()))
71 return;
73 }
74
76}
77
78void CIRGenModule::emitSYCLKernelCaller(const FunctionDecl *kernelEntryPointFn,
79 ASTContext &ctx) {
80 assert(ctx.getLangOpts().SYCLIsDevice &&
81 "SYCL kernel caller offload entry point functions can only be emitted"
82 " during device compilation");
83
84 const auto *kernelEntryPointAttr =
85 kernelEntryPointFn->getAttr<SYCLKernelEntryPointAttr>();
86 assert(kernelEntryPointAttr && "Missing sycl_kernel_entry_point attribute");
87 assert(!kernelEntryPointAttr->isInvalidAttr() &&
88 "sycl_kernel_entry_point attribute is invalid");
89
90 // Find the SYCLKernelCallStmt.
91 SYCLKernelCallStmt *kernelCallStmt =
92 cast<SYCLKernelCallStmt>(kernelEntryPointFn->getBody());
93
94 // Retrieve the SYCL kernel caller parameters from the OutlinedFunctionDecl.
95 FunctionArgList args;
96 const OutlinedFunctionDecl *outlinedFnDecl =
97 kernelCallStmt->getOutlinedFunctionDecl();
98 args.append(outlinedFnDecl->param_begin(), outlinedFnDecl->param_end());
99
100 // Compute the function info and CIR function type.
101 const CIRGenFunctionInfo &fnInfo =
103 cir::FuncType funcType = getTypes().getFunctionType(fnInfo);
104
105 // Retrieve the generated name for the SYCL kernel caller function.
106 CanQualType kernelNameType =
107 ctx.getCanonicalType(kernelEntryPointAttr->getKernelName());
108 const SYCLKernelInfo &kernelInfo = ctx.getSYCLKernelInfo(kernelNameType);
109
110 // Synthesized from the OutlinedFunctionDecl, not a FunctionDecl, so create
111 // the function directly with a null FunctionDecl (mirrors classic CodeGen's
112 // llvm::Function::Create).
113 cir::FuncOp funcOp = createCIRFunction(
114 getLoc(kernelEntryPointFn->getSourceRange()), kernelInfo.GetKernelName(),
115 funcType, /*funcDecl=*/nullptr);
116 funcOp.setLinkage(cir::GlobalLinkageKind::ExternalLinkage);
117
118 // Emit as a device kernel (e.g. spir_kernel). Classic CodeGen derives this
119 // from CC_DeviceKernel via SetLLVMFunctionAttributes; CIR does not yet route
120 // opFuncCallingConv onto the FuncOp, so set it from the target hook.
121 funcOp.setCallingConv(getTargetCIRGenInfo().getDeviceKernelCallingConv());
122
123 // Route through the shared attribute path so generic function attributes
124 // (e.g. convergent) are applied, matching classic CodeGen's
125 // SetLLVMFunctionAttributes. There is no FunctionDecl, so pass an empty
126 // GlobalDecl.
127 setCIRFunctionAttributes(GlobalDecl(), fnInfo, funcOp, /*isThunk=*/false);
128
129 // TODO: attributes applied by classic CodeGen not yet handled in CIR:
130 // SetSYCLKernelAttributes (norecurse, mustprogress), addSYCLModuleIdAttr.
132
133 // Emit the SYCL kernel caller function.
134 CIRGenFunction cgf(*this, builder);
135 llvm::SaveAndRestore<CIRGenFunction *> savedCGF(curCGF, &cgf);
136 {
137 mlir::OpBuilder::InsertionGuard guard(builder);
138 cgf.emitSYCLKernelCaller(outlinedFnDecl, funcOp, funcType, args);
139 }
140
141 setDSOLocal(static_cast<mlir::Operation *>(funcOp));
142
143 setNonAliasAttributes(GlobalDecl(), funcOp);
144 // CIR's setter takes a FunctionDecl; nullptr skips OutlinedFunctionDecl-
145 // derived attributes (e.g. inline hints), not yet handled.
147 setCIRFunctionAttributesForDefinition(/*fd=*/nullptr, funcOp);
148}
Defines the clang::ASTContext interface.
This file declares types used to describe SYCL kernels.
This file defines SYCL AST classes used to represent calls to SYCL kernels.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
const LangOptions & getLangOpts() const
Definition ASTContext.h:983
CanQualType VoidTy
const SYCLKernelInfo & getSYCLKernelInfo(QualType T) const
Given a type used as a SYCL kernel name, returns a reference to the metadata generated from the corre...
clang::GlobalDecl curGD
The GlobalDecl for the current function being compiled or the global variable currently being initial...
const clang::LangOptions & getLangOpts() const
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
llvm::ScopedHashTableScope< const clang::Decl *, mlir::Value > SymTableScopeTy
void finishFunction(SourceLocation endLoc)
mlir::LogicalResult emitFunctionBody(const clang::Stmt *body)
void startFunction(clang::GlobalDecl gd, clang::QualType returnType, cir::FuncOp fn, cir::FuncType funcType, FunctionArgList args, clang::SourceLocation loc, clang::SourceLocation startLoc)
Emit code for the start of a function.
static void eraseEmptyAndUnusedBlocks(cir::FuncOp func)
Remove leftover empty and unreachable blocks from an emitted function.
clang::ASTContext & getContext() const
void emitSYCLKernelCaller(const clang::OutlinedFunctionDecl *outlinedFnDecl, cir::FuncOp funcOp, cir::FuncType funcType, FunctionArgList &args)
mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope, llvm::ArrayRef< const Attr * > attrs={})
mlir::LogicalResult emitSYCLKernelCallStmt(const SYCLKernelCallStmt &s)
void setDSOLocal(mlir::Operation *op) const
void setCIRFunctionAttributes(GlobalDecl gd, const CIRGenFunctionInfo &info, cir::FuncOp func, bool isThunk)
Set the CIR function attributes (Sext, zext, etc).
cir::FuncOp createCIRFunction(mlir::Location loc, llvm::StringRef name, cir::FuncType funcType, const clang::FunctionDecl *funcDecl)
const TargetCIRGenInfo & getTargetCIRGenInfo()
mlir::Location getLoc(clang::SourceLocation cLoc)
Helpers to convert the presumed location of Clang's SourceLocation to an MLIR Location.
void emitSYCLKernelCaller(const clang::FunctionDecl *kernelEntryPointFn, clang::ASTContext &ctx)
Emit the SYCL kernel caller offload entry point function generated for a function declared with the s...
void setCIRFunctionAttributesForDefinition(const clang::FunctionDecl *fd, cir::FuncOp f)
Set extra attributes (inline, etc.) for a function.
cir::FuncType getFunctionType(const CIRGenFunctionInfo &info)
Get the CIR function type for.
const CIRGenFunctionInfo & arrangeDeviceKernelCallerDeclaration(clang::QualType resultType, const FunctionArgList &args)
Arrange the function info for a device kernel caller entry point (e.g.
Type for representing both the decl and type of parameters to a function.
Definition CIRGenCall.h:193
T * getAttr() const
Definition DeclBase.h:581
SourceLocation getLocation() const
Definition DeclBase.h:447
Represents a function declaration or definition.
Definition Decl.h:2058
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
Definition Decl.cpp:3268
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4613
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:60
Represents a partial function definition.
Definition Decl.h:5013
parameter_const_iterator param_end() const
Definition Decl.h:5061
Stmt * getBody() const override
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
Definition Decl.cpp:5741
parameter_const_iterator param_begin() const
Definition Decl.h:5060
SYCLKernelCallStmt represents the transformation that is applied to the body of a function declared w...
Definition StmtSYCL.h:36
OutlinedFunctionDecl * getOutlinedFunctionDecl()
Definition StmtSYCL.h:66
const std::string & GetKernelName() const
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
Stmt - This represents one statement.
Definition Stmt.h:85
SourceLocation getEndLoc() const LLVM_READONLY
Definition Stmt.cpp:367
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
Top level wrappers for InstallAPI frontend operations.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
U cast(CodeGen::Address addr)
Definition Address.h:327
static bool opFuncExtraAttrs()
static bool setLLVMFunctionFEnvAttributes()
Represents a scope, including function bodies, compound statements, and the substatements of if/while...