16#include "mlir/Dialect/OpenACC/OpenACC.h"
18#include "llvm/Support/SaveAndRestore.h"
24struct OpenACCDeclareCleanup final : EHScopeStack::Cleanup {
25 mlir::acc::DeclareEnterOp enterOp;
27 OpenACCDeclareCleanup(mlir::acc::DeclareEnterOp enterOp) : enterOp(enterOp) {}
29 template <
typename OutTy,
typename InTy>
30 void createOutOp(CIRGenFunction &cgf, InTy inOp) {
31 if constexpr (std::is_same_v<OutTy, mlir::acc::DeleteOp>) {
33 OutTy::create(cgf.
getBuilder(), inOp.getLoc(), inOp,
34 inOp.getStructured(), inOp.getImplicit(),
35 llvm::Twine(inOp.getNameAttr()), inOp.getBounds());
36 outOp.setDataClause(inOp.getDataClause());
37 outOp.setModifiers(inOp.getModifiers());
40 OutTy::create(cgf.
getBuilder(), inOp.getLoc(), inOp, inOp.getVarPtr(),
41 inOp.getStructured(), inOp.getImplicit(),
42 llvm::Twine(inOp.getNameAttr()), inOp.getBounds());
43 outOp.setDataClause(inOp.getDataClause());
44 outOp.setModifiers(inOp.getModifiers());
48 void emit(CIRGenFunction &cgf, Flags flags)
override {
49 auto exitOp = mlir::acc::DeclareExitOp::create(
50 cgf.
getBuilder(), enterOp.getLoc(), enterOp, {});
54 for (mlir::Value val : enterOp.getDataClauseOperands()) {
55 if (
auto copyin = val.getDefiningOp<mlir::acc::CopyinOp>()) {
56 switch (copyin.getDataClause()) {
59 "OpenACC local declare clause copyin unexpected data clause");
61 case mlir::acc::DataClause::acc_copy:
62 createOutOp<mlir::acc::CopyoutOp>(cgf, copyin);
64 case mlir::acc::DataClause::acc_copyin:
65 createOutOp<mlir::acc::DeleteOp>(cgf, copyin);
68 }
else if (
auto create = val.getDefiningOp<mlir::acc::CreateOp>()) {
69 switch (
create.getDataClause()) {
72 "OpenACC local declare clause create unexpected data clause");
74 case mlir::acc::DataClause::acc_copyout:
75 createOutOp<mlir::acc::CopyoutOp>(cgf, create);
77 case mlir::acc::DataClause::acc_create:
78 createOutOp<mlir::acc::DeleteOp>(cgf, create);
81 }
else if (
auto present = val.getDefiningOp<mlir::acc::PresentOp>()) {
82 createOutOp<mlir::acc::DeleteOp>(cgf, present);
83 }
else if (
auto dev_res =
84 val.getDefiningOp<mlir::acc::DeclareDeviceResidentOp>()) {
85 createOutOp<mlir::acc::DeleteOp>(cgf, dev_res);
86 }
else if (val.getDefiningOp<mlir::acc::DeclareLinkOp>()) {
89 }
else if (val.getDefiningOp<mlir::acc::DevicePtrOp>()) {
93 llvm_unreachable(
"OpenACC local declare clause unexpected defining op");
96 exitOp.getDataClauseOperandsMutable().append(val);
103 if (
const auto *rd = dyn_cast<OpenACCRoutineDecl>(d))
111 auto enterOp = mlir::acc::DeclareEnterOp::create(
112 builder, exprLoc, mlir::acc::DeclareTokenType::get(&
cgm.getMLIRContext()),
130 while (
const auto *ase = dyn_cast<ArraySectionExpr>(curVarExpr))
133 if (
const auto *dre = dyn_cast<DeclRefExpr>(curVarExpr))
134 return dre->getFoundDecl()->getCanonicalDecl();
140template <
typename BeforeOpTy,
typename DataClauseTy>
142 const Expr *varOperand, DataClauseTy dataClause,
147 static_assert(std::is_same_v<DataClauseTy, mlir::acc::DataClause>);
157 mlir::OpBuilder::InsertionGuard guardCase(builder);
158 auto ctorOp = mlir::acc::GlobalConstructorOp::create(
159 builder, exprLoc, (varName +
"_acc_ctor").str(),
162 mlir::Block *block = builder.createBlock(&ctorOp.getRegion(),
163 ctorOp.getRegion().end(), {}, {});
164 builder.setInsertionPointToEnd(block);
178 BeforeOpTy::create(builder, exprLoc, inf.
varValue, structured, implicit,
180 beforeOp.setDataClause(dataClause);
183 mlir::acc::DeclareEnterOp::create(
184 builder, exprLoc, mlir::acc::DeclareTokenType::get(&
getMLIRContext()),
185 beforeOp.getResult());
187 mlir::acc::TerminatorOp::create(builder, exprLoc);
194 mlir::OpBuilder::InsertionGuard guardCase(builder);
195 auto ctorOp = mlir::acc::GlobalDestructorOp::create(
196 builder, exprLoc, (varName +
"_acc_dtor").str(),
199 mlir::Block *block = builder.createBlock(&ctorOp.getRegion(),
200 ctorOp.getRegion().end(), {}, {});
201 builder.setInsertionPointToEnd(block);
213 auto getDevPtr = mlir::acc::GetDevicePtrOp::create(
214 builder, exprLoc, inf.
varValue, structured, implicit, inf.
name,
216 getDevPtr.setDataClause(dataClause);
219 mlir::acc::DeclareExitOp::create(builder, exprLoc, mlir::Value{},
220 getDevPtr.getResult());
221 auto deleteOp = mlir::acc::DeleteOp::create(
222 builder, exprLoc, getDevPtr, structured, implicit, inf.
name, {});
223 deleteOp.setDataClause(dataClause);
225 mlir::acc::TerminatorOp::create(builder, exprLoc);
234class OpenACCGlobalDeclareClauseEmitter final
239 OpenACCGlobalDeclareClauseEmitter(
CIRGenModule &cgm) : cgm(cgm) {}
242 llvm_unreachable(
"Invalid OpenACC clause on global Declare");
246 this->VisitClauseList(clauses);
249 void VisitCopyInClause(
const OpenACCCopyInClause &clause) {
251 cgm.emitGlobalOpenACCDeclareDataOperands<mlir::acc::CopyinOp>(
257 void VisitCreateClause(
const OpenACCCreateClause &clause) {
259 cgm.emitGlobalOpenACCDeclareDataOperands<mlir::acc::CreateOp>(
265 void VisitDeviceResidentClause(
const OpenACCDeviceResidentClause &clause) {
267 cgm.emitGlobalOpenACCDeclareDataOperands<
268 mlir::acc::DeclareDeviceResidentOp>(
269 var, mlir::acc::DataClause::acc_declare_device_resident, {},
274 void VisitLinkClause(
const OpenACCLinkClause &clause) {
276 cgm.emitGlobalOpenACCDeclareDataOperands<mlir::acc::DeclareLinkOp>(
277 var, mlir::acc::DataClause::acc_declare_link, {},
288 mlir::OpBuilder::InsertionGuard guardCase(builder);
289 OpenACCGlobalDeclareClauseEmitter em{*
this};
308class OpenACCRoutineClauseEmitter final
312 mlir::acc::RoutineOp routineOp;
319 mlir::acc::RoutineOp routineOp,
321 : cgm(cgm), builder(builder), routineOp(routineOp), funcDecl(funcDecl) {}
324 this->VisitClauseList(clauses);
328 llvm_unreachable(
"Invalid OpenACC clause on routine");
331 void VisitSeqClause(
const OpenACCSeqClause &clause) {
332 routineOp.addSeq(builder.getContext(), lastDeviceTypeValues);
334 void VisitWorkerClause(
const OpenACCWorkerClause &clause) {
335 routineOp.addWorker(builder.getContext(), lastDeviceTypeValues);
337 void VisitVectorClause(
const OpenACCVectorClause &clause) {
338 routineOp.addVector(builder.getContext(), lastDeviceTypeValues);
341 void VisitNoHostClause(
const OpenACCNoHostClause &clause) {
342 routineOp.setNohost(
true);
345 void VisitGangClause(
const OpenACCGangClause &clause) {
351 routineOp.addGang(builder.getContext(), lastDeviceTypeValues);
355 assert(
kind == OpenACCGangKind::Dim);
357 llvm::APSInt curValue =
expr->EvaluateKnownConstInt(cgm.getASTContext());
359 curValue = curValue.sextOrTrunc(64);
360 routineOp.addGang(builder.getContext(), lastDeviceTypeValues,
361 curValue.getZExtValue());
365 void VisitDeviceTypeClause(
const OpenACCDeviceTypeClause &clause) {
366 lastDeviceTypeValues.clear();
372 void VisitBindClause(
const OpenACCBindClause &clause) {
374 mlir::StringAttr value =
377 routineOp.addBindStrName(builder.getContext(), lastDeviceTypeValues,
381 std::string bindName = cgm.getOpenACCBindMangledName(
384 routineOp.addBindIDName(
385 builder.getContext(), lastDeviceTypeValues,
386 mlir::SymbolRefAttr::get(builder.getContext(), bindName));
395 mlir::OpBuilder::InsertionGuard guardCase(builder);
397 builder.setInsertionPointToEnd(&
getModule().getBodyRegion().front());
399 mlir::Location routineLoc =
getLoc(pragmaLoc);
401 std::stringstream routineNameSS;
404 std::string routineName = routineNameSS.str();
409 auto routineOp = mlir::acc::RoutineOp::create(
410 builder, routineLoc, routineName,
411 mlir::SymbolRefAttr::get(builder.getContext(), func.getName()),
417 if (
auto routineInfo =
418 func.getOperation()->getAttrOfType<mlir::acc::RoutineInfoAttr>(
419 mlir::acc::getRoutineInfoAttrName()))
420 funcRoutines.append(routineInfo.getAccRoutines().begin(),
421 routineInfo.getAccRoutines().end());
423 funcRoutines.push_back(
424 mlir::SymbolRefAttr::get(builder.getContext(), routineName));
425 func.getOperation()->setAttr(
426 mlir::acc::getRoutineInfoAttrName(),
427 mlir::acc::RoutineInfoAttr::get(func.getContext(), funcRoutines));
429 OpenACCRoutineClauseEmitter emitter{*
this, builder, routineOp, funcDecl};
430 emitter.emitClauses(clauses);
static void emit(Program &P, llvm::SmallVectorImpl< std::byte > &Code, const T &Val, bool &Success)
Helper to write bytecode and bail out if 32-bit offsets become invalid.
static const Decl * getDeclareReferencedDecl(const Expr *e)
This file defines OpenACC nodes for declarative directives.
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
void emitOpenACCRoutine(const OpenACCRoutineDecl &d)
void emitOpenACCDeclare(const OpenACCDeclareDecl &d)
OpenACCDataOperandInfo getOpenACCDataOperandInfo(const Expr *e)
mlir::Operation * curFn
The current function or global initializer that is generated code for.
EHScopeStack ehStack
Tracks function scope overall cleanup handling.
CIRGenBuilderTy & getBuilder()
This class organizes the cross-function state that is used while generating CIR code.
llvm::StringRef getMangledName(clang::GlobalDecl gd)
void emitGlobalOpenACCDeclareDataOperands(const Expr *varOperand, DataClauseTy dataClause, OpenACCModifierKind modifiers, bool structured, bool implicit, bool requiresDtor)
void emitGlobalOpenACCDeclareDecl(const clang::OpenACCDeclareDecl *cd)
void emitGlobalOpenACCRoutineDecl(const clang::OpenACCRoutineDecl *cd)
void emitGlobalOpenACCDecl(const clang::OpenACCConstructDecl *cd)
void emitOpenACCRoutineDecl(const clang::FunctionDecl *funcDecl, cir::FuncOp func, SourceLocation pragmaLoc, ArrayRef< const OpenACCClause * > clauses)
mlir::Location getLoc(clang::SourceLocation cLoc)
Helpers to convert the presumed location of Clang's SourceLocation to an MLIR Location.
mlir::ModuleOp getModule() const
mlir::MLIRContext & getMLIRContext()
Decl - This represents one declaration (or definition), e.g.
SourceLocation getBeginLoc() const LLVM_READONLY
This represents one expression.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Represents a function declaration or definition.
GlobalDecl - represents a global declaration.
const IdentifierInfo * getIdentifierArgument() const
const StringLiteral * getStringArgument() const
bool isIdentifierArgument() const
bool isStringArgument() const
ArrayRef< Expr * > getVarList() const
This is the base type for all OpenACC Clauses.
ArrayRef< const OpenACCClause * > clauses() const
OpenACCModifierKind getModifierList() const
OpenACCModifierKind getModifierList() const
ArrayRef< DeviceTypeArgument > getArchitectures() const
unsigned getNumExprs() const
std::pair< OpenACCGangKind, const Expr * > getExpr(unsigned I) const
Encodes a location in the source.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
SourceLocation getBeginLoc() const LLVM_READONLY
StringRef getString() const
mlir::acc::DeviceType decodeDeviceType(const IdentifierInfo *ii)
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
@ NormalCleanup
Denotes a cleanup that should run when a scope is exited using normal control flow (falling off the e...
mlir::acc::DataClauseModifier convertOpenACCModifiers(OpenACCModifierKind modifiers)
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
constexpr Variable var(Literal L)
Returns the variable of L.
std::unique_ptr< DiagnosticConsumer > create(StringRef OutputFile, DiagnosticOptions &DiagOpts, bool MergeChildRecords=false)
Returns a DiagnosticConsumer that serializes diagnostics to a bitcode file.
Top level wrappers for InstallAPI frontend operations.
IdentifierLoc DeviceTypeArgument
U cast(CodeGen::Address addr)
__DEVICE__ _Tp arg(const std::complex< _Tp > &__c)
llvm::SmallVector< mlir::Value > bounds