23 #include "llvm/ADT/TypeSwitch.h"
24 #include "llvm/Frontend/OpenMP/OMPConstants.h"
25 #include "llvm/Support/FormatVariadic.h"
53 StringRef funcName = funcOp ? funcOp.getName() :
"unknown";
56 loc, builder, funcName, strLen);
57 return builder.getOrCreateIdent(locStr, strLen);
64 .Case([&](acc::EnterDataOp) {
65 return builder.getOrCreateRuntimeFunctionPtr(
66 llvm::omp::OMPRTL___tgt_target_data_begin_mapper);
68 .Case([&](acc::ExitDataOp) {
69 return builder.getOrCreateRuntimeFunctionPtr(
70 llvm::omp::OMPRTL___tgt_target_data_end_mapper);
72 .Case([&](acc::UpdateOp) {
73 return builder.getOrCreateRuntimeFunctionPtr(
74 llvm::omp::OMPRTL___tgt_target_data_update_mapper);
76 llvm_unreachable(
"Unknown OpenACC operation");
87 struct OpenACCIRBuilder::MapperAllocas &mapperAllocas) {
89 llvm::LLVMContext &ctx = builder.getContext();
90 auto *i8PtrTy = llvm::Type::getInt8PtrTy(ctx);
92 auto *i64Ty = llvm::Type::getInt64Ty(ctx);
95 for (
Value data : operands) {
96 llvm::Value *dataValue = moduleTranslation.
lookupValue(data);
98 llvm::Value *dataPtrBase;
100 llvm::Value *dataSize;
102 if (isa<LLVM::LLVMPointerType>(data.getType())) {
103 dataPtrBase = dataValue;
105 dataSize = accBuilder->getSizeInBytes(dataValue);
108 <<
"Data operand must be legalized before translation."
109 <<
"Unsupported type: " << data.getType();
114 llvm::Value *ptrBaseGEP = builder.CreateInBoundsGEP(
115 arrI8PtrTy, mapperAllocas.ArgsBase,
116 {builder.getInt32(0), builder.getInt32(index)});
117 llvm::Value *ptrBaseCast = builder.CreateBitCast(
118 ptrBaseGEP, dataPtrBase->getType()->getPointerTo());
119 builder.CreateStore(dataPtrBase, ptrBaseCast);
122 llvm::Value *ptrGEP = builder.CreateInBoundsGEP(
123 arrI8PtrTy, mapperAllocas.Args,
124 {builder.getInt32(0), builder.getInt32(index)});
125 llvm::Value *ptrCast =
126 builder.CreateBitCast(ptrGEP, dataPtr->getType()->getPointerTo());
127 builder.CreateStore(dataPtr, ptrCast);
130 llvm::Value *sizeGEP = builder.CreateInBoundsGEP(
131 arrI64Ty, mapperAllocas.ArgSizes,
132 {builder.getInt32(0), builder.getInt32(index)});
133 builder.CreateStore(dataSize, sizeGEP);
135 flags.push_back(operandFlag);
136 llvm::Constant *mapName =
138 names.push_back(mapName);
150 struct OpenACCIRBuilder::MapperAllocas &mapperAllocas) {
158 for (
mlir::Value dataOp : op.getDataClauseOperands()) {
160 mlir::dyn_cast_or_null<acc::CreateOp>(dataOp.getDefiningOp())) {
161 create.push_back(createOp.getVarPtr());
162 }
else if (
auto copyinOp = mlir::dyn_cast_or_null<acc::CopyinOp>(
163 dataOp.getDefiningOp())) {
164 copyin.push_back(copyinOp.getVarPtr());
168 auto nbTotalOperands = create.size() + copyin.size();
179 index, mapperAllocas)))
191 struct OpenACCIRBuilder::MapperAllocas &mapperAllocas) {
197 for (
mlir::Value dataOp : op.getDataClauseOperands()) {
198 if (
auto devicePtrOp = mlir::dyn_cast_or_null<acc::GetDevicePtrOp>(
199 dataOp.getDefiningOp())) {
200 for (
auto &u : devicePtrOp.getAccPtr().getUses()) {
201 if (mlir::dyn_cast_or_null<acc::DeleteOp>(u.getOwner()))
202 deleteOperands.push_back(devicePtrOp.getVarPtr());
203 else if (mlir::dyn_cast_or_null<acc::CopyoutOp>(u.getOwner()))
204 copyoutOperands.push_back(devicePtrOp.getVarPtr());
209 auto nbTotalOperands = deleteOperands.size() + copyoutOperands.size();
220 index, mapperAllocas)))
232 struct OpenACCIRBuilder::MapperAllocas &mapperAllocas) {
238 for (
mlir::Value dataOp : op.getDataClauseOperands()) {
239 if (
auto getDevicePtrOp = mlir::dyn_cast_or_null<acc::GetDevicePtrOp>(
240 dataOp.getDefiningOp())) {
241 from.push_back(getDevicePtrOp.getVarPtr());
242 }
else if (
auto updateDeviceOp =
243 mlir::dyn_cast_or_null<acc::UpdateDeviceOp>(
244 dataOp.getDefiningOp())) {
245 to.push_back(updateDeviceOp.getVarPtr());
267 llvm::IRBuilderBase &builder,
269 llvm::LLVMContext &ctx = builder.getContext();
270 auto enclosingFuncOp = op.getOperation()->
getParentOfType<LLVM::LLVMFuncOp>();
271 llvm::Function *enclosingFunction =
278 llvm::Function *beginMapperFunc = accBuilder->getOrCreateRuntimeFunctionPtr(
279 llvm::omp::OMPRTL___tgt_target_data_begin_mapper);
281 llvm::Function *endMapperFunc = accBuilder->getOrCreateRuntimeFunctionPtr(
282 llvm::omp::OMPRTL___tgt_target_data_end_mapper);
285 unsigned totalNbOperand = op.getNumDataOperands();
287 struct OpenACCIRBuilder::MapperAllocas mapperAllocas;
288 OpenACCIRBuilder::InsertPointTy allocaIP(
289 &enclosingFunction->getEntryBlock(),
290 enclosingFunction->getEntryBlock().getFirstInsertionPt());
291 accBuilder->createMapperAllocas(builder.saveIP(), allocaIP, totalNbOperand,
302 for (
mlir::Value dataOp : op.getDataClauseOperands()) {
303 if (
auto devicePtrOp = mlir::dyn_cast_or_null<acc::GetDevicePtrOp>(
304 dataOp.getDefiningOp())) {
305 for (
auto &u : devicePtrOp.getAccPtr().getUses()) {
306 if (mlir::dyn_cast_or_null<acc::DeleteOp>(u.getOwner())) {
307 deleteOperands.push_back(devicePtrOp.getVarPtr());
308 }
else if (mlir::dyn_cast_or_null<acc::CopyoutOp>(u.getOwner())) {
311 copyout.push_back(devicePtrOp.getVarPtr());
314 }
else if (
auto copyinOp = mlir::dyn_cast_or_null<acc::CopyinOp>(
315 dataOp.getDefiningOp())) {
318 copyin.push_back(copyinOp.getVarPtr());
319 }
else if (
auto createOp = mlir::dyn_cast_or_null<acc::CreateOp>(
320 dataOp.getDefiningOp())) {
323 create.push_back(createOp.getVarPtr());
324 }
else if (
auto presentOp = mlir::dyn_cast_or_null<acc::PresentOp>(
325 dataOp.getDefiningOp())) {
326 present.push_back(createOp.getVarPtr());
330 auto nbTotalOperands = copyin.size() + copyout.size() + create.size() +
331 present.size() + deleteOperands.size();
336 flags, names, index, mapperAllocas)))
348 flags, names, index, mapperAllocas)))
354 names, index, mapperAllocas)))
359 names, index, mapperAllocas)))
362 llvm::GlobalVariable *maptypes =
363 accBuilder->createOffloadMaptypes(flags,
".offload_maptypes");
364 llvm::Value *maptypesArg = builder.CreateConstInBoundsGEP2_32(
368 llvm::GlobalVariable *mapnames =
369 accBuilder->createOffloadMapnames(names,
".offload_mapnames");
370 llvm::Value *mapnamesArg = builder.CreateConstInBoundsGEP2_32(
375 accBuilder->emitMapperCall(builder.saveIP(), beginMapperFunc, srcLocInfo,
376 maptypesArg, mapnamesArg, mapperAllocas,
380 llvm::BasicBlock *entryBlock =
nullptr;
383 llvm::BasicBlock *llvmBB = llvm::BasicBlock::Create(
384 ctx,
"acc.data", builder.GetInsertBlock()->getParent());
385 if (entryBlock ==
nullptr)
387 moduleTranslation.
mapBlock(&bb, llvmBB);
390 auto afterDataRegion = builder.saveIP();
392 llvm::BranchInst *sourceTerminator = builder.CreateBr(entryBlock);
394 builder.restoreIP(afterDataRegion);
395 llvm::BasicBlock *endDataBlock = llvm::BasicBlock::Create(
396 ctx,
"acc.end_data", builder.GetInsertBlock()->getParent());
400 for (
Block *bb : blocks) {
401 llvm::BasicBlock *llvmBB = moduleTranslation.
lookupBlock(bb);
402 if (bb->isEntryBlock()) {
403 assert(sourceTerminator->getNumSuccessors() == 1 &&
404 "provided entry block has multiple successors");
405 sourceTerminator->setSuccessor(0, llvmBB);
409 moduleTranslation.
convertBlock(*bb, bb->isEntryBlock(), builder))) {
413 if (isa<acc::TerminatorOp, acc::YieldOp>(bb->getTerminator()))
414 builder.CreateBr(endDataBlock);
418 builder.SetInsertPoint(endDataBlock);
419 accBuilder->emitMapperCall(builder.saveIP(), endMapperFunc, srcLocInfo,
420 maptypesArg, mapnamesArg, mapperAllocas,
427 template <
typename OpTy>
431 auto enclosingFuncOp =
432 op.getOperation()->template getParentOfType<LLVM::LLVMFuncOp>();
433 llvm::Function *enclosingFunction =
442 unsigned totalNbOperand = op.getNumDataOperands();
444 llvm::LLVMContext &ctx = builder.
getContext();
446 struct OpenACCIRBuilder::MapperAllocas mapperAllocas;
447 OpenACCIRBuilder::InsertPointTy allocaIP(
448 &enclosingFunction->getEntryBlock(),
449 enclosingFunction->getEntryBlock().getFirstInsertionPt());
450 accBuilder->createMapperAllocas(builder.saveIP(), allocaIP, totalNbOperand,
460 llvm::GlobalVariable *maptypes =
461 accBuilder->createOffloadMaptypes(flags,
".offload_maptypes");
462 llvm::Value *maptypesArg = builder.CreateConstInBoundsGEP2_32(
466 llvm::GlobalVariable *mapnames =
467 accBuilder->createOffloadMapnames(names,
".offload_mapnames");
468 llvm::Value *mapnamesArg = builder.CreateConstInBoundsGEP2_32(
472 accBuilder->emitMapperCall(builder.saveIP(), mapperFunc, srcLocInfo,
473 maptypesArg, mapnamesArg, mapperAllocas,
483 class OpenACCDialectLLVMIRTranslationInterface
491 convertOperation(
Operation *op, llvm::IRBuilderBase &builder,
499 LogicalResult OpenACCDialectLLVMIRTranslationInterface::convertOperation(
500 Operation *op, llvm::IRBuilderBase &builder,
504 .Case([&](acc::DataOp dataOp) {
507 .Case([&](acc::EnterDataOp enterDataOp) {
508 return convertStandaloneDataOp<acc::EnterDataOp>(enterDataOp, builder,
511 .Case([&](acc::ExitDataOp exitDataOp) {
512 return convertStandaloneDataOp<acc::ExitDataOp>(exitDataOp, builder,
515 .Case([&](acc::UpdateOp updateOp) {
516 return convertStandaloneDataOp<acc::UpdateOp>(updateOp, builder,
519 .Case<acc::TerminatorOp, acc::YieldOp>([](
auto op) {
523 "unexpected OpenACC terminator with operands");
526 .Case<acc::CreateOp, acc::CopyinOp, acc::CopyoutOp, acc::DeleteOp,
527 acc::UpdateDeviceOp, acc::GetDevicePtrOp>([](
auto op) {
532 return op->
emitError(
"unsupported OpenACC operation: ")
538 registry.
insert<acc::OpenACCDialect>();
540 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.
Block represents an ordered list of Operations.
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
void addExtension(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.
LogicalResult convertBlock(Block &bb, bool ignoreArguments, llvm::IRBuilderBase &builder)
Translates the contents of the given block to LLVM IR using this translator.
llvm::Value * lookupValue(Value value) const
Finds an LLVM IR value corresponding to the given MLIR value.
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.
MLIRContext * getContext()
Return the context this operation is associated with.
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'.
Region & getRegion(unsigned index)
Returns the region held by this operation at position 'index'.
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...
SetVector< Block * > getTopologicallySortedBlocks(Region ®ion)
Get a topologically sorted list of blocks of the given region.
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.
This header declares functions that assit transformations in the MemRef dialect.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
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;.
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
This class represents an efficient way to signal success or failure.