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()) {
155 mlir::dyn_cast_or_null<acc::CreateOp>(dataOp.getDefiningOp())) {
156 create.push_back(createOp.getVarPtr());
157 }
else if (
auto copyinOp = mlir::dyn_cast_or_null<acc::CopyinOp>(
158 dataOp.getDefiningOp())) {
159 copyin.push_back(copyinOp.getVarPtr());
163 auto nbTotalOperands = create.size() + copyin.size();
174 index, mapperAllocas)))
186 struct OpenACCIRBuilder::MapperAllocas &mapperAllocas) {
192 for (
mlir::Value dataOp : op.getDataClauseOperands()) {
193 if (
auto devicePtrOp = mlir::dyn_cast_or_null<acc::GetDevicePtrOp>(
194 dataOp.getDefiningOp())) {
195 for (
auto &u : devicePtrOp.getAccPtr().getUses()) {
196 if (mlir::dyn_cast_or_null<acc::DeleteOp>(u.getOwner()))
197 deleteOperands.push_back(devicePtrOp.getVarPtr());
198 else if (mlir::dyn_cast_or_null<acc::CopyoutOp>(u.getOwner()))
199 copyoutOperands.push_back(devicePtrOp.getVarPtr());
204 auto nbTotalOperands = deleteOperands.size() + copyoutOperands.size();
207 if (failed(
processOperands(builder, moduleTranslation, op, deleteOperands,
213 if (failed(
processOperands(builder, moduleTranslation, op, copyoutOperands,
215 index, mapperAllocas)))
227 struct OpenACCIRBuilder::MapperAllocas &mapperAllocas) {
233 for (
mlir::Value dataOp : op.getDataClauseOperands()) {
234 if (
auto getDevicePtrOp = mlir::dyn_cast_or_null<acc::GetDevicePtrOp>(
235 dataOp.getDefiningOp())) {
236 from.push_back(getDevicePtrOp.getVarPtr());
237 }
else if (
auto updateDeviceOp =
238 mlir::dyn_cast_or_null<acc::UpdateDeviceOp>(
239 dataOp.getDefiningOp())) {
240 to.push_back(updateDeviceOp.getVarPtr());
244 if (failed(
processOperands(builder, moduleTranslation, op, from, from.size(),
249 if (failed(
processOperands(builder, moduleTranslation, op, to, to.size(),
262 llvm::IRBuilderBase &builder,
264 llvm::LLVMContext &ctx = builder.getContext();
265 auto enclosingFuncOp = op.getOperation()->getParentOfType<LLVM::LLVMFuncOp>();
266 llvm::Function *enclosingFunction =
273 llvm::Function *beginMapperFunc = accBuilder->getOrCreateRuntimeFunctionPtr(
274 llvm::omp::OMPRTL___tgt_target_data_begin_mapper);
276 llvm::Function *endMapperFunc = accBuilder->getOrCreateRuntimeFunctionPtr(
277 llvm::omp::OMPRTL___tgt_target_data_end_mapper);
280 unsigned totalNbOperand = op.getNumDataOperands();
282 struct OpenACCIRBuilder::MapperAllocas mapperAllocas;
283 OpenACCIRBuilder::InsertPointTy allocaIP(
284 &enclosingFunction->getEntryBlock(),
285 enclosingFunction->getEntryBlock().getFirstInsertionPt());
286 accBuilder->createMapperAllocas(builder.saveIP(), allocaIP, totalNbOperand,
297 for (
mlir::Value dataOp : op.getDataClauseOperands()) {
298 if (
auto devicePtrOp = mlir::dyn_cast_or_null<acc::GetDevicePtrOp>(
299 dataOp.getDefiningOp())) {
300 for (
auto &u : devicePtrOp.getAccPtr().getUses()) {
301 if (mlir::dyn_cast_or_null<acc::DeleteOp>(u.getOwner())) {
302 deleteOperands.push_back(devicePtrOp.getVarPtr());
303 }
else if (mlir::dyn_cast_or_null<acc::CopyoutOp>(u.getOwner())) {
306 copyout.push_back(devicePtrOp.getVarPtr());
309 }
else if (
auto copyinOp = mlir::dyn_cast_or_null<acc::CopyinOp>(
310 dataOp.getDefiningOp())) {
313 copyin.push_back(copyinOp.getVarPtr());
314 }
else if (
auto createOp = mlir::dyn_cast_or_null<acc::CreateOp>(
315 dataOp.getDefiningOp())) {
318 create.push_back(createOp.getVarPtr());
319 }
else if (
auto presentOp = mlir::dyn_cast_or_null<acc::PresentOp>(
320 dataOp.getDefiningOp())) {
321 present.push_back(createOp.getVarPtr());
325 auto nbTotalOperands = copyin.size() + copyout.size() + create.size() +
326 present.size() + deleteOperands.size();
331 flags, names, index, mapperAllocas)))
335 if (failed(
processOperands(builder, moduleTranslation, op, deleteOperands,
343 flags, names, index, mapperAllocas)))
349 names, index, mapperAllocas)))
354 names, index, mapperAllocas)))
357 llvm::GlobalVariable *maptypes =
358 accBuilder->createOffloadMaptypes(flags,
".offload_maptypes");
359 llvm::Value *maptypesArg = builder.CreateConstInBoundsGEP2_32(
363 llvm::GlobalVariable *mapnames =
364 accBuilder->createOffloadMapnames(names,
".offload_mapnames");
365 llvm::Value *mapnamesArg = builder.CreateConstInBoundsGEP2_32(
370 accBuilder->emitMapperCall(builder.saveIP(), beginMapperFunc, srcLocInfo,
371 maptypesArg, mapnamesArg, mapperAllocas,
375 llvm::BasicBlock *entryBlock =
nullptr;
377 for (
Block &bb : op.getRegion()) {
378 llvm::BasicBlock *llvmBB = llvm::BasicBlock::Create(
379 ctx,
"acc.data", builder.GetInsertBlock()->getParent());
380 if (entryBlock ==
nullptr)
382 moduleTranslation.
mapBlock(&bb, llvmBB);
385 auto afterDataRegion = builder.saveIP();
387 llvm::BranchInst *sourceTerminator = builder.CreateBr(entryBlock);
389 builder.restoreIP(afterDataRegion);
390 llvm::BasicBlock *endDataBlock = llvm::BasicBlock::Create(
391 ctx,
"acc.end_data", builder.GetInsertBlock()->getParent());
394 for (
Block *bb : blocks) {
395 llvm::BasicBlock *llvmBB = moduleTranslation.
lookupBlock(bb);
396 if (bb->isEntryBlock()) {
397 assert(sourceTerminator->getNumSuccessors() == 1 &&
398 "provided entry block has multiple successors");
399 sourceTerminator->setSuccessor(0, llvmBB);
403 moduleTranslation.
convertBlock(*bb, bb->isEntryBlock(), builder))) {
407 if (isa<acc::TerminatorOp, acc::YieldOp>(bb->getTerminator()))
408 builder.CreateBr(endDataBlock);
412 builder.SetInsertPoint(endDataBlock);
413 accBuilder->emitMapperCall(builder.saveIP(), endMapperFunc, srcLocInfo,
414 maptypesArg, mapnamesArg, mapperAllocas,
421 template <
typename OpTy>
425 auto enclosingFuncOp =
426 op.getOperation()->template getParentOfType<LLVM::LLVMFuncOp>();
427 llvm::Function *enclosingFunction =
436 unsigned totalNbOperand = op.getNumDataOperands();
438 llvm::LLVMContext &ctx = builder.getContext();
440 struct OpenACCIRBuilder::MapperAllocas mapperAllocas;
441 OpenACCIRBuilder::InsertPointTy allocaIP(
442 &enclosingFunction->getEntryBlock(),
443 enclosingFunction->getEntryBlock().getFirstInsertionPt());
444 accBuilder->createMapperAllocas(builder.saveIP(), allocaIP, totalNbOperand,
454 llvm::GlobalVariable *maptypes =
455 accBuilder->createOffloadMaptypes(flags,
".offload_maptypes");
456 llvm::Value *maptypesArg = builder.CreateConstInBoundsGEP2_32(
460 llvm::GlobalVariable *mapnames =
461 accBuilder->createOffloadMapnames(names,
".offload_mapnames");
462 llvm::Value *mapnamesArg = builder.CreateConstInBoundsGEP2_32(
466 accBuilder->emitMapperCall(builder.saveIP(), mapperFunc, srcLocInfo,
467 maptypesArg, mapnamesArg, mapperAllocas,
477 class OpenACCDialectLLVMIRTranslationInterface
485 convertOperation(
Operation *op, llvm::IRBuilderBase &builder,
493 LogicalResult OpenACCDialectLLVMIRTranslationInterface::convertOperation(
494 Operation *op, llvm::IRBuilderBase &builder,
498 .Case([&](acc::DataOp dataOp) {
501 .Case([&](acc::EnterDataOp enterDataOp) {
502 return convertStandaloneDataOp<acc::EnterDataOp>(enterDataOp, builder,
505 .Case([&](acc::ExitDataOp exitDataOp) {
506 return convertStandaloneDataOp<acc::ExitDataOp>(exitDataOp, builder,
510 return convertStandaloneDataOp<acc::UpdateOp>(
updateOp, builder,
513 .Case<acc::TerminatorOp, acc::YieldOp>([](
auto op) {
517 "unexpected OpenACC terminator with operands");
520 .Case<acc::CreateOp, acc::CopyinOp, acc::CopyoutOp, acc::DeleteOp,
521 acc::UpdateDeviceOp, acc::GetDevicePtrOp>([](
auto op) {
526 return op->
emitError(
"unsupported OpenACC operation: ")
532 registry.
insert<acc::OpenACCDialect>();
534 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;.