23 #include "llvm/ADT/TypeSwitch.h"
24 #include "llvm/Frontend/OpenMP/OMPConstants.h"
52 StringRef funcName = funcOp ? funcOp.getName() :
"unknown";
55 loc, builder, funcName, strLen);
56 return builder.getOrCreateIdent(locStr, strLen);
63 .Case([&](acc::EnterDataOp) {
64 return builder.getOrCreateRuntimeFunctionPtr(
65 llvm::omp::OMPRTL___tgt_target_data_begin_mapper);
67 .Case([&](acc::ExitDataOp) {
68 return builder.getOrCreateRuntimeFunctionPtr(
69 llvm::omp::OMPRTL___tgt_target_data_end_mapper);
71 .Case([&](acc::UpdateOp) {
72 return builder.getOrCreateRuntimeFunctionPtr(
73 llvm::omp::OMPRTL___tgt_target_data_update_mapper);
75 llvm_unreachable(
"Unknown OpenACC operation");
86 struct OpenACCIRBuilder::MapperAllocas &mapperAllocas) {
88 llvm::LLVMContext &ctx = builder.getContext();
89 auto *i8PtrTy = llvm::PointerType::getUnqual(ctx);
91 auto *i64Ty = llvm::Type::getInt64Ty(ctx);
94 for (
Value data : operands) {
95 llvm::Value *dataValue = moduleTranslation.
lookupValue(data);
97 llvm::Value *dataPtrBase;
99 llvm::Value *dataSize;
101 if (isa<LLVM::LLVMPointerType>(data.getType())) {
102 dataPtrBase = dataValue;
104 dataSize = accBuilder->getSizeInBytes(dataValue);
107 <<
"Data operand must be legalized before translation."
108 <<
"Unsupported type: " << data.getType();
113 llvm::Value *ptrBaseGEP = builder.CreateInBoundsGEP(
114 arrI8PtrTy, mapperAllocas.ArgsBase,
115 {builder.getInt32(0), builder.getInt32(index)});
116 builder.CreateStore(dataPtrBase, ptrBaseGEP);
119 llvm::Value *ptrGEP = builder.CreateInBoundsGEP(
120 arrI8PtrTy, mapperAllocas.Args,
121 {builder.getInt32(0), builder.getInt32(index)});
122 builder.CreateStore(dataPtr, ptrGEP);
125 llvm::Value *sizeGEP = builder.CreateInBoundsGEP(
126 arrI64Ty, mapperAllocas.ArgSizes,
127 {builder.getInt32(0), builder.getInt32(index)});
128 builder.CreateStore(dataSize, sizeGEP);
130 flags.push_back(operandFlag);
131 llvm::Constant *mapName =
133 names.push_back(mapName);
145 struct OpenACCIRBuilder::MapperAllocas &mapperAllocas) {
153 for (
mlir::Value dataOp : op.getDataClauseOperands()) {
154 if (
auto createOp = dataOp.getDefiningOp<acc::CreateOp>()) {
155 create.push_back(createOp.getVarPtr());
156 }
else if (
auto copyinOp = mlir::dyn_cast_or_null<acc::CopyinOp>(
157 dataOp.getDefiningOp())) {
158 copyin.push_back(copyinOp.getVarPtr());
162 auto nbTotalOperands = create.size() + copyin.size();
173 index, mapperAllocas)))
185 struct OpenACCIRBuilder::MapperAllocas &mapperAllocas) {
191 for (
mlir::Value dataOp : op.getDataClauseOperands()) {
192 if (
auto devicePtrOp = mlir::dyn_cast_or_null<acc::GetDevicePtrOp>(
193 dataOp.getDefiningOp())) {
194 for (
auto &u : devicePtrOp.getAccPtr().getUses()) {
195 if (mlir::dyn_cast_or_null<acc::DeleteOp>(u.getOwner()))
196 deleteOperands.push_back(devicePtrOp.getVarPtr());
197 else if (mlir::dyn_cast_or_null<acc::CopyoutOp>(u.getOwner()))
198 copyoutOperands.push_back(devicePtrOp.getVarPtr());
203 auto nbTotalOperands = deleteOperands.size() + copyoutOperands.size();
206 if (failed(
processOperands(builder, moduleTranslation, op, deleteOperands,
212 if (failed(
processOperands(builder, moduleTranslation, op, copyoutOperands,
214 index, mapperAllocas)))
226 struct OpenACCIRBuilder::MapperAllocas &mapperAllocas) {
232 for (
mlir::Value dataOp : op.getDataClauseOperands()) {
233 if (
auto getDevicePtrOp = mlir::dyn_cast_or_null<acc::GetDevicePtrOp>(
234 dataOp.getDefiningOp())) {
235 from.push_back(getDevicePtrOp.getVarPtr());
236 }
else if (
auto updateDeviceOp =
237 mlir::dyn_cast_or_null<acc::UpdateDeviceOp>(
238 dataOp.getDefiningOp())) {
239 to.push_back(updateDeviceOp.getVarPtr());
243 if (failed(
processOperands(builder, moduleTranslation, op, from, from.size(),
248 if (failed(
processOperands(builder, moduleTranslation, op, to, to.size(),
261 llvm::IRBuilderBase &builder,
263 llvm::LLVMContext &ctx = builder.getContext();
264 auto enclosingFuncOp = op.getOperation()->getParentOfType<LLVM::LLVMFuncOp>();
265 llvm::Function *enclosingFunction =
272 llvm::Function *beginMapperFunc = accBuilder->getOrCreateRuntimeFunctionPtr(
273 llvm::omp::OMPRTL___tgt_target_data_begin_mapper);
275 llvm::Function *endMapperFunc = accBuilder->getOrCreateRuntimeFunctionPtr(
276 llvm::omp::OMPRTL___tgt_target_data_end_mapper);
279 unsigned totalNbOperand = op.getNumDataOperands();
281 struct OpenACCIRBuilder::MapperAllocas mapperAllocas;
282 OpenACCIRBuilder::InsertPointTy allocaIP(
283 &enclosingFunction->getEntryBlock(),
284 enclosingFunction->getEntryBlock().getFirstInsertionPt());
285 accBuilder->createMapperAllocas(builder.saveIP(), allocaIP, totalNbOperand,
296 for (
mlir::Value dataOp : op.getDataClauseOperands()) {
297 if (
auto devicePtrOp = mlir::dyn_cast_or_null<acc::GetDevicePtrOp>(
298 dataOp.getDefiningOp())) {
299 for (
auto &u : devicePtrOp.getAccPtr().getUses()) {
300 if (mlir::dyn_cast_or_null<acc::DeleteOp>(u.getOwner())) {
301 deleteOperands.push_back(devicePtrOp.getVarPtr());
302 }
else if (mlir::dyn_cast_or_null<acc::CopyoutOp>(u.getOwner())) {
305 copyout.push_back(devicePtrOp.getVarPtr());
308 }
else if (
auto copyinOp = mlir::dyn_cast_or_null<acc::CopyinOp>(
309 dataOp.getDefiningOp())) {
312 copyin.push_back(copyinOp.getVarPtr());
313 }
else if (
auto createOp = mlir::dyn_cast_or_null<acc::CreateOp>(
314 dataOp.getDefiningOp())) {
317 create.push_back(createOp.getVarPtr());
318 }
else if (
auto presentOp = mlir::dyn_cast_or_null<acc::PresentOp>(
319 dataOp.getDefiningOp())) {
320 present.push_back(createOp.getVarPtr());
324 auto nbTotalOperands = copyin.size() + copyout.size() + create.size() +
325 present.size() + deleteOperands.size();
330 flags, names, index, mapperAllocas)))
334 if (failed(
processOperands(builder, moduleTranslation, op, deleteOperands,
342 flags, names, index, mapperAllocas)))
348 names, index, mapperAllocas)))
353 names, index, mapperAllocas)))
356 llvm::GlobalVariable *maptypes =
357 accBuilder->createOffloadMaptypes(flags,
".offload_maptypes");
358 llvm::Value *maptypesArg = builder.CreateConstInBoundsGEP2_32(
362 llvm::GlobalVariable *mapnames =
363 accBuilder->createOffloadMapnames(names,
".offload_mapnames");
364 llvm::Value *mapnamesArg = builder.CreateConstInBoundsGEP2_32(
369 accBuilder->emitMapperCall(builder.saveIP(), beginMapperFunc, srcLocInfo,
370 maptypesArg, mapnamesArg, mapperAllocas,
374 llvm::BasicBlock *entryBlock =
nullptr;
376 for (
Block &bb : op.getRegion()) {
377 llvm::BasicBlock *llvmBB = llvm::BasicBlock::Create(
378 ctx,
"acc.data", builder.GetInsertBlock()->getParent());
379 if (entryBlock ==
nullptr)
381 moduleTranslation.
mapBlock(&bb, llvmBB);
384 auto afterDataRegion = builder.saveIP();
386 llvm::BranchInst *sourceTerminator = builder.CreateBr(entryBlock);
388 builder.restoreIP(afterDataRegion);
389 llvm::BasicBlock *endDataBlock = llvm::BasicBlock::Create(
390 ctx,
"acc.end_data", builder.GetInsertBlock()->getParent());
393 for (
Block *bb : blocks) {
394 llvm::BasicBlock *llvmBB = moduleTranslation.
lookupBlock(bb);
395 if (bb->isEntryBlock()) {
396 assert(sourceTerminator->getNumSuccessors() == 1 &&
397 "provided entry block has multiple successors");
398 sourceTerminator->setSuccessor(0, llvmBB);
402 moduleTranslation.
convertBlock(*bb, bb->isEntryBlock(), builder))) {
406 if (isa<acc::TerminatorOp, acc::YieldOp>(bb->getTerminator()))
407 builder.CreateBr(endDataBlock);
411 builder.SetInsertPoint(endDataBlock);
412 accBuilder->emitMapperCall(builder.saveIP(), endMapperFunc, srcLocInfo,
413 maptypesArg, mapnamesArg, mapperAllocas,
420 template <
typename OpTy>
424 auto enclosingFuncOp =
425 op.getOperation()->template getParentOfType<LLVM::LLVMFuncOp>();
426 llvm::Function *enclosingFunction =
435 unsigned totalNbOperand = op.getNumDataOperands();
437 llvm::LLVMContext &ctx = builder.getContext();
439 struct OpenACCIRBuilder::MapperAllocas mapperAllocas;
440 OpenACCIRBuilder::InsertPointTy allocaIP(
441 &enclosingFunction->getEntryBlock(),
442 enclosingFunction->getEntryBlock().getFirstInsertionPt());
443 accBuilder->createMapperAllocas(builder.saveIP(), allocaIP, totalNbOperand,
453 llvm::GlobalVariable *maptypes =
454 accBuilder->createOffloadMaptypes(flags,
".offload_maptypes");
455 llvm::Value *maptypesArg = builder.CreateConstInBoundsGEP2_32(
459 llvm::GlobalVariable *mapnames =
460 accBuilder->createOffloadMapnames(names,
".offload_mapnames");
461 llvm::Value *mapnamesArg = builder.CreateConstInBoundsGEP2_32(
465 accBuilder->emitMapperCall(builder.saveIP(), mapperFunc, srcLocInfo,
466 maptypesArg, mapnamesArg, mapperAllocas,
476 class OpenACCDialectLLVMIRTranslationInterface
484 convertOperation(
Operation *op, llvm::IRBuilderBase &builder,
492 LogicalResult OpenACCDialectLLVMIRTranslationInterface::convertOperation(
493 Operation *op, llvm::IRBuilderBase &builder,
497 .Case([&](acc::DataOp dataOp) {
500 .Case([&](acc::EnterDataOp enterDataOp) {
501 return convertStandaloneDataOp<acc::EnterDataOp>(enterDataOp, builder,
504 .Case([&](acc::ExitDataOp exitDataOp) {
505 return convertStandaloneDataOp<acc::ExitDataOp>(exitDataOp, builder,
509 return convertStandaloneDataOp<acc::UpdateOp>(
updateOp, builder,
512 .Case<acc::TerminatorOp, acc::YieldOp>([](
auto op) {
516 "unexpected OpenACC terminator with operands");
519 .Case<acc::CreateOp, acc::CopyinOp, acc::CopyoutOp, acc::DeleteOp,
520 acc::UpdateDeviceOp, acc::GetDevicePtrOp>([](
auto op) {
525 return op->
emitError(
"unsupported OpenACC operation: ")
531 registry.
insert<acc::OpenACCDialect>();
533 dialect->addInterfaces<OpenACCDialectLLVMIRTranslationInterface>();
static llvm::Function * getAssociatedFunction(OpenACCIRBuilder &builder, Operation *op)
Return the runtime function used to lower the given operation.
static constexpr uint64_t kDeleteFlag
static LogicalResult processDataOperands(llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, acc::EnterDataOp op, SmallVector< uint64_t > &flags, SmallVectorImpl< llvm::Constant * > &names, struct OpenACCIRBuilder::MapperAllocas &mapperAllocas)
Process data operands from acc::EnterDataOp.
static llvm::Value * createSourceLocationInfo(OpenACCIRBuilder &builder, Operation *op)
Create the location struct from the operation location information.
static constexpr uint64_t kPresentFlag
static LogicalResult processOperands(llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, Operation *op, ValueRange operands, unsigned totalNbOperand, uint64_t operandFlag, SmallVector< uint64_t > &flags, SmallVectorImpl< llvm::Constant * > &names, unsigned &index, struct OpenACCIRBuilder::MapperAllocas &mapperAllocas)
Extract pointer, size and mapping information from operands to populate the future functions argument...
static constexpr uint64_t kHostCopyoutFlag
static constexpr int64_t kDefaultDevice
Default value for the device id.
llvm::OpenMPIRBuilder OpenACCIRBuilder
static LogicalResult convertDataOp(acc::DataOp &op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenACC data operation into LLVM IR.
static constexpr uint64_t kCreateFlag
Flag values are extracted from openmp/libomptarget/include/omptarget.h and mapped to corresponding Op...
static constexpr uint64_t kHoldFlag
static constexpr uint64_t kDeviceCopyinFlag
static LogicalResult convertStandaloneDataOp(OpTy &op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenACC standalone data operation into LLVM IR.
static LogicalResult updateOp(mlir::OpBuilder &builder, mlir::Operation *op, GetLayoutFnTy getLayoutOfValue)
Update an operation with the layout of its results.
Block represents an ordered list of Operations.
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
bool addExtension(TypeID extensionID, std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
Base class for dialect interfaces providing translation to LLVM IR.
LLVMTranslationDialectInterface(Dialect *dialect)
Implementation class for module translation.
llvm::Value * lookupValue(Value value) const
Finds an LLVM IR value corresponding to the given MLIR value.
LogicalResult convertBlock(Block &bb, bool ignoreArguments, llvm::IRBuilderBase &builder)
Translates the contents of the given block to LLVM IR using this translator.
llvm::BasicBlock * lookupBlock(Block *block) const
Finds an LLVM IR basic block that corresponds to the given MLIR block.
llvm::OpenMPIRBuilder * getOpenMPBuilder()
Returns the OpenMP IR builder associated with the LLVM IR module being constructed.
llvm::Function * lookupFunction(StringRef name) const
Finds an LLVM IR function by its name.
void mapBlock(Block *mlir, llvm::BasicBlock *llvm)
Stores the mapping between an MLIR block and LLVM IR basic block.
MLIRContext is the top-level object for a collection of MLIR operations.
void appendDialectRegistry(const DialectRegistry ®istry)
Append the contents of the given dialect registry to the registry associated with this context.
Operation is the basic unit of execution within MLIR.
Location getLoc()
The source location the operation was defined or derived from.
unsigned getNumOperands()
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
OperationName getName()
The name of an operation is the key identifier for it.
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
llvm::Constant * createMappingInformation(Location loc, llvm::OpenMPIRBuilder &builder)
Create a constant string representing the mapping information extracted from the MLIR location inform...
llvm::Constant * createSourceLocStrFromLocation(Location loc, llvm::OpenMPIRBuilder &builder, StringRef name, uint32_t &strLen)
Create a constant string location from the MLIR Location information.
Include the generated interface declarations.
SetVector< Block * > getBlocksSortedByDominance(Region ®ion)
Gets a list of blocks that is sorted according to dominance.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
void registerOpenACCDialectTranslation(DialectRegistry ®istry)
Register the OpenACC dialect and the translation to the LLVM IR in the given registry;.