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());
161 mlir::Block *block = builder.createBlock(&ctorOp.getRegion(),
162 ctorOp.getRegion().end(), {}, {});
163 builder.setInsertionPointToEnd(block);
176 BeforeOpTy::create(builder, exprLoc, inf.
varValue, structured, implicit,
178 beforeOp.setDataClause(dataClause);
181 mlir::acc::DeclareEnterOp::create(
182 builder, exprLoc, mlir::acc::DeclareTokenType::get(&
getMLIRContext()),
183 beforeOp.getResult());
185 mlir::acc::TerminatorOp::create(builder, exprLoc);
192 mlir::OpBuilder::InsertionGuard guardCase(builder);
193 auto ctorOp = mlir::acc::GlobalDestructorOp::create(
194 builder, exprLoc, (varName +
"_acc_dtor").str());
196 mlir::Block *block = builder.createBlock(&ctorOp.getRegion(),
197 ctorOp.getRegion().end(), {}, {});
198 builder.setInsertionPointToEnd(block);
209 auto getDevPtr = mlir::acc::GetDevicePtrOp::create(
210 builder, exprLoc, inf.
varValue, structured, implicit, inf.
name,
212 getDevPtr.setDataClause(dataClause);
215 mlir::acc::DeclareExitOp::create(builder, exprLoc, mlir::Value{},
216 getDevPtr.getResult());
217 auto deleteOp = mlir::acc::DeleteOp::create(
218 builder, exprLoc, getDevPtr, structured, implicit, inf.
name, {});
219 deleteOp.setDataClause(dataClause);
221 mlir::acc::TerminatorOp::create(builder, exprLoc);
230class OpenACCGlobalDeclareClauseEmitter final
235 OpenACCGlobalDeclareClauseEmitter(
CIRGenModule &cgm) : cgm(cgm) {}
238 llvm_unreachable(
"Invalid OpenACC clause on global Declare");
242 this->VisitClauseList(clauses);
245 void VisitCopyInClause(
const OpenACCCopyInClause &clause) {
247 cgm.emitGlobalOpenACCDeclareDataOperands<mlir::acc::CopyinOp>(
253 void VisitCreateClause(
const OpenACCCreateClause &clause) {
255 cgm.emitGlobalOpenACCDeclareDataOperands<mlir::acc::CreateOp>(
261 void VisitDeviceResidentClause(
const OpenACCDeviceResidentClause &clause) {
263 cgm.emitGlobalOpenACCDeclareDataOperands<
264 mlir::acc::DeclareDeviceResidentOp>(
265 var, mlir::acc::DataClause::acc_declare_device_resident, {},
270 void VisitLinkClause(
const OpenACCLinkClause &clause) {
272 cgm.emitGlobalOpenACCDeclareDataOperands<mlir::acc::DeclareLinkOp>(
273 var, mlir::acc::DataClause::acc_declare_link, {},
284 mlir::OpBuilder::InsertionGuard guardCase(builder);
285 OpenACCGlobalDeclareClauseEmitter em{*
this};
304class OpenACCRoutineClauseEmitter final
308 mlir::acc::RoutineOp routineOp;
315 mlir::acc::RoutineOp routineOp,
317 : cgm(cgm), builder(builder), routineOp(routineOp), funcDecl(funcDecl) {}
320 this->VisitClauseList(clauses);
324 llvm_unreachable(
"Invalid OpenACC clause on routine");
327 void VisitSeqClause(
const OpenACCSeqClause &clause) {
328 routineOp.addSeq(builder.getContext(), lastDeviceTypeValues);
330 void VisitWorkerClause(
const OpenACCWorkerClause &clause) {
331 routineOp.addWorker(builder.getContext(), lastDeviceTypeValues);
333 void VisitVectorClause(
const OpenACCVectorClause &clause) {
334 routineOp.addVector(builder.getContext(), lastDeviceTypeValues);
337 void VisitNoHostClause(
const OpenACCNoHostClause &clause) {
338 routineOp.setNohost(
true);
341 void VisitGangClause(
const OpenACCGangClause &clause) {
347 routineOp.addGang(builder.getContext(), lastDeviceTypeValues);
351 assert(kind == OpenACCGangKind::Dim);
353 llvm::APSInt curValue =
expr->EvaluateKnownConstInt(cgm.getASTContext());
355 curValue = curValue.sextOrTrunc(64);
356 routineOp.addGang(builder.getContext(), lastDeviceTypeValues,
357 curValue.getZExtValue());
361 void VisitDeviceTypeClause(
const OpenACCDeviceTypeClause &clause) {
362 lastDeviceTypeValues.clear();
368 void VisitBindClause(
const OpenACCBindClause &clause) {
370 mlir::StringAttr value =
373 routineOp.addBindStrName(builder.getContext(), lastDeviceTypeValues,
377 std::string bindName = cgm.getOpenACCBindMangledName(
380 routineOp.addBindIDName(
381 builder.getContext(), lastDeviceTypeValues,
382 mlir::SymbolRefAttr::get(builder.getContext(), bindName));
391 mlir::OpBuilder::InsertionGuard guardCase(builder);
393 builder.setInsertionPointToEnd(&
getModule().getBodyRegion().front());
395 mlir::Location routineLoc =
getLoc(pragmaLoc);
397 std::stringstream routineNameSS;
400 std::string routineName = routineNameSS.str();
405 auto routineOp = mlir::acc::RoutineOp::create(
406 builder, routineLoc, routineName,
407 mlir::SymbolRefAttr::get(builder.getContext(), func.getName()),
413 if (
auto routineInfo =
414 func.getOperation()->getAttrOfType<mlir::acc::RoutineInfoAttr>(
415 mlir::acc::getRoutineInfoAttrName()))
416 funcRoutines.append(routineInfo.getAccRoutines().begin(),
417 routineInfo.getAccRoutines().end());
419 funcRoutines.push_back(
420 mlir::SymbolRefAttr::get(builder.getContext(), routineName));
421 func.getOperation()->setAttr(
422 mlir::acc::getRoutineInfoAttrName(),
423 mlir::acc::RoutineInfoAttr::get(func.getContext(), funcRoutines));
425 OpenACCRoutineClauseEmitter emitter{*
this, builder, routineOp, funcDecl};
426 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.
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()
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.
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.
unsigned kind
All of the diagnostics that can be emitted by the frontend.
std::unique_ptr< DiagnosticConsumer > create(StringRef OutputFile, DiagnosticOptions &DiagOpts, bool MergeChildRecords=false)
Returns a DiagnosticConsumer that serializes diagnostics to a bitcode file.
The JSON file list parser is used to communicate input to InstallAPI.
IdentifierLoc DeviceTypeArgument
U cast(CodeGen::Address addr)
__DEVICE__ _Tp arg(const std::complex< _Tp > &__c)
llvm::SmallVector< mlir::Value > bounds