24 #include "llvm/ADT/TypeSwitch.h"
25 #include "llvm/Frontend/OpenMP/OMPConstants.h"
26 #include "llvm/Support/FormatVariadic.h"
54 StringRef funcName = funcOp ? funcOp.getName() :
"unknown";
57 loc, builder, funcName, strLen);
58 return builder.getOrCreateIdent(locStr, strLen);
65 .Case([&](acc::EnterDataOp) {
66 return builder.getOrCreateRuntimeFunctionPtr(
67 llvm::omp::OMPRTL___tgt_target_data_begin_mapper);
69 .Case([&](acc::ExitDataOp) {
70 return builder.getOrCreateRuntimeFunctionPtr(
71 llvm::omp::OMPRTL___tgt_target_data_end_mapper);
73 .Case([&](acc::UpdateOp) {
74 return builder.getOrCreateRuntimeFunctionPtr(
75 llvm::omp::OMPRTL___tgt_target_data_update_mapper);
77 llvm_unreachable(
"Unknown OpenACC operation");
88 struct OpenACCIRBuilder::MapperAllocas &mapperAllocas) {
90 llvm::LLVMContext &ctx = builder.getContext();
91 auto *i8PtrTy = llvm::PointerType::getUnqual(ctx);
93 auto *i64Ty = llvm::Type::getInt64Ty(ctx);
96 for (
Value data : operands) {
97 llvm::Value *dataValue = moduleTranslation.
lookupValue(data);
99 llvm::Value *dataPtrBase;
100 llvm::Value *dataPtr;
101 llvm::Value *dataSize;
103 if (isa<LLVM::LLVMPointerType>(data.getType())) {
104 dataPtrBase = dataValue;
106 dataSize = accBuilder->getSizeInBytes(dataValue);
109 <<
"Data operand must be legalized before translation."
110 <<
"Unsupported type: " << data.getType();
115 llvm::Value *ptrBaseGEP = builder.CreateInBoundsGEP(
116 arrI8PtrTy, mapperAllocas.ArgsBase,
117 {builder.getInt32(0), builder.getInt32(index)});
118 builder.CreateStore(dataPtrBase, ptrBaseGEP);
121 llvm::Value *ptrGEP = builder.CreateInBoundsGEP(
122 arrI8PtrTy, mapperAllocas.Args,
123 {builder.getInt32(0), builder.getInt32(index)});
124 builder.CreateStore(dataPtr, ptrGEP);
127 llvm::Value *sizeGEP = builder.CreateInBoundsGEP(
128 arrI64Ty, mapperAllocas.ArgSizes,
129 {builder.getInt32(0), builder.getInt32(index)});
130 builder.CreateStore(dataSize, sizeGEP);
132 flags.push_back(operandFlag);
133 llvm::Constant *mapName =
135 names.push_back(mapName);
147 struct OpenACCIRBuilder::MapperAllocas &mapperAllocas) {
155 for (
mlir::Value dataOp : op.getDataClauseOperands()) {
157 mlir::dyn_cast_or_null<acc::CreateOp>(dataOp.getDefiningOp())) {
158 create.push_back(createOp.getVarPtr());
159 }
else if (
auto copyinOp = mlir::dyn_cast_or_null<acc::CopyinOp>(
160 dataOp.getDefiningOp())) {
161 copyin.push_back(copyinOp.getVarPtr());
165 auto nbTotalOperands = create.size() + copyin.size();
176 index, mapperAllocas)))
188 struct OpenACCIRBuilder::MapperAllocas &mapperAllocas) {
194 for (
mlir::Value dataOp : op.getDataClauseOperands()) {
195 if (
auto devicePtrOp = mlir::dyn_cast_or_null<acc::GetDevicePtrOp>(
196 dataOp.getDefiningOp())) {
197 for (
auto &u : devicePtrOp.getAccPtr().getUses()) {
198 if (mlir::dyn_cast_or_null<acc::DeleteOp>(u.getOwner()))
199 deleteOperands.push_back(devicePtrOp.getVarPtr());
200 else if (mlir::dyn_cast_or_null<acc::CopyoutOp>(u.getOwner()))
201 copyoutOperands.push_back(devicePtrOp.getVarPtr());
206 auto nbTotalOperands = deleteOperands.size() + copyoutOperands.size();
209 if (failed(
processOperands(builder, moduleTranslation, op, deleteOperands,
215 if (failed(
processOperands(builder, moduleTranslation, op, copyoutOperands,
217 index, mapperAllocas)))
229 struct OpenACCIRBuilder::MapperAllocas &mapperAllocas) {
235 for (
mlir::Value dataOp : op.getDataClauseOperands()) {
236 if (
auto getDevicePtrOp = mlir::dyn_cast_or_null<acc::GetDevicePtrOp>(
237 dataOp.getDefiningOp())) {
238 from.push_back(getDevicePtrOp.getVarPtr());
239 }
else if (
auto updateDeviceOp =
240 mlir::dyn_cast_or_null<acc::UpdateDeviceOp>(
241 dataOp.getDefiningOp())) {
242 to.push_back(updateDeviceOp.getVarPtr());
246 if (failed(
processOperands(builder, moduleTranslation, op, from, from.size(),
251 if (failed(
processOperands(builder, moduleTranslation, op, to, to.size(),
264 llvm::IRBuilderBase &builder,
266 llvm::LLVMContext &ctx = builder.getContext();
267 auto enclosingFuncOp = op.getOperation()->getParentOfType<LLVM::LLVMFuncOp>();
268 llvm::Function *enclosingFunction =
275 llvm::Function *beginMapperFunc = accBuilder->getOrCreateRuntimeFunctionPtr(
276 llvm::omp::OMPRTL___tgt_target_data_begin_mapper);
278 llvm::Function *endMapperFunc = accBuilder->getOrCreateRuntimeFunctionPtr(
279 llvm::omp::OMPRTL___tgt_target_data_end_mapper);
282 unsigned totalNbOperand = op.getNumDataOperands();
284 struct OpenACCIRBuilder::MapperAllocas mapperAllocas;
285 OpenACCIRBuilder::InsertPointTy allocaIP(
286 &enclosingFunction->getEntryBlock(),
287 enclosingFunction->getEntryBlock().getFirstInsertionPt());
288 accBuilder->createMapperAllocas(builder.saveIP(), allocaIP, totalNbOperand,
299 for (
mlir::Value dataOp : op.getDataClauseOperands()) {
300 if (
auto devicePtrOp = mlir::dyn_cast_or_null<acc::GetDevicePtrOp>(
301 dataOp.getDefiningOp())) {
302 for (
auto &u : devicePtrOp.getAccPtr().getUses()) {
303 if (mlir::dyn_cast_or_null<acc::DeleteOp>(u.getOwner())) {
304 deleteOperands.push_back(devicePtrOp.getVarPtr());
305 }
else if (mlir::dyn_cast_or_null<acc::CopyoutOp>(u.getOwner())) {
308 copyout.push_back(devicePtrOp.getVarPtr());
311 }
else if (
auto copyinOp = mlir::dyn_cast_or_null<acc::CopyinOp>(
312 dataOp.getDefiningOp())) {
315 copyin.push_back(copyinOp.getVarPtr());
316 }
else if (
auto createOp = mlir::dyn_cast_or_null<acc::CreateOp>(
317 dataOp.getDefiningOp())) {
320 create.push_back(createOp.getVarPtr());
321 }
else if (
auto presentOp = mlir::dyn_cast_or_null<acc::PresentOp>(
322 dataOp.getDefiningOp())) {
323 present.push_back(createOp.getVarPtr());
327 auto nbTotalOperands = copyin.size() + copyout.size() + create.size() +
328 present.size() + deleteOperands.size();
333 flags, names, index, mapperAllocas)))
337 if (failed(
processOperands(builder, moduleTranslation, op, deleteOperands,
345 flags, names, index, mapperAllocas)))
351 names, index, mapperAllocas)))
356 names, index, mapperAllocas)))
359 llvm::GlobalVariable *maptypes =
360 accBuilder->createOffloadMaptypes(flags,
".offload_maptypes");
361 llvm::Value *maptypesArg = builder.CreateConstInBoundsGEP2_32(
365 llvm::GlobalVariable *mapnames =
366 accBuilder->createOffloadMapnames(names,
".offload_mapnames");
367 llvm::Value *mapnamesArg = builder.CreateConstInBoundsGEP2_32(
372 accBuilder->emitMapperCall(builder.saveIP(), beginMapperFunc, srcLocInfo,
373 maptypesArg, mapnamesArg, mapperAllocas,
377 llvm::BasicBlock *entryBlock =
nullptr;
379 for (
Block &bb : op.getRegion()) {
380 llvm::BasicBlock *llvmBB = llvm::BasicBlock::Create(
381 ctx,
"acc.data", builder.GetInsertBlock()->getParent());
382 if (entryBlock ==
nullptr)
384 moduleTranslation.
mapBlock(&bb, llvmBB);
387 auto afterDataRegion = builder.saveIP();
389 llvm::BranchInst *sourceTerminator = builder.CreateBr(entryBlock);
391 builder.restoreIP(afterDataRegion);
392 llvm::BasicBlock *endDataBlock = llvm::BasicBlock::Create(
393 ctx,
"acc.end_data", builder.GetInsertBlock()->getParent());
396 for (
Block *bb : blocks) {
397 llvm::BasicBlock *llvmBB = moduleTranslation.
lookupBlock(bb);
398 if (bb->isEntryBlock()) {
399 assert(sourceTerminator->getNumSuccessors() == 1 &&
400 "provided entry block has multiple successors");
401 sourceTerminator->setSuccessor(0, llvmBB);
405 moduleTranslation.
convertBlock(*bb, bb->isEntryBlock(), builder))) {
409 if (isa<acc::TerminatorOp, acc::YieldOp>(bb->getTerminator()))
410 builder.CreateBr(endDataBlock);
414 builder.SetInsertPoint(endDataBlock);
415 accBuilder->emitMapperCall(builder.saveIP(), endMapperFunc, srcLocInfo,
416 maptypesArg, mapnamesArg, mapperAllocas,
423 template <
typename OpTy>
427 auto enclosingFuncOp =
428 op.getOperation()->template getParentOfType<LLVM::LLVMFuncOp>();
429 llvm::Function *enclosingFunction =
438 unsigned totalNbOperand = op.getNumDataOperands();
440 llvm::LLVMContext &ctx = builder.getContext();
442 struct OpenACCIRBuilder::MapperAllocas mapperAllocas;
443 OpenACCIRBuilder::InsertPointTy allocaIP(
444 &enclosingFunction->getEntryBlock(),
445 enclosingFunction->getEntryBlock().getFirstInsertionPt());
446 accBuilder->createMapperAllocas(builder.saveIP(), allocaIP, totalNbOperand,
456 llvm::GlobalVariable *maptypes =
457 accBuilder->createOffloadMaptypes(flags,
".offload_maptypes");
458 llvm::Value *maptypesArg = builder.CreateConstInBoundsGEP2_32(
462 llvm::GlobalVariable *mapnames =
463 accBuilder->createOffloadMapnames(names,
".offload_mapnames");
464 llvm::Value *mapnamesArg = builder.CreateConstInBoundsGEP2_32(
468 accBuilder->emitMapperCall(builder.saveIP(), mapperFunc, srcLocInfo,
469 maptypesArg, mapnamesArg, mapperAllocas,
479 class OpenACCDialectLLVMIRTranslationInterface
487 convertOperation(
Operation *op, llvm::IRBuilderBase &builder,
495 LogicalResult OpenACCDialectLLVMIRTranslationInterface::convertOperation(
496 Operation *op, llvm::IRBuilderBase &builder,
500 .Case([&](acc::DataOp dataOp) {
503 .Case([&](acc::EnterDataOp enterDataOp) {
504 return convertStandaloneDataOp<acc::EnterDataOp>(enterDataOp, builder,
507 .Case([&](acc::ExitDataOp exitDataOp) {
508 return convertStandaloneDataOp<acc::ExitDataOp>(exitDataOp, builder,
511 .Case([&](acc::UpdateOp updateOp) {
512 return convertStandaloneDataOp<acc::UpdateOp>(updateOp, builder,
515 .Case<acc::TerminatorOp, acc::YieldOp>([](
auto op) {
519 "unexpected OpenACC terminator with operands");
522 .Case<acc::CreateOp, acc::CopyinOp, acc::CopyoutOp, acc::DeleteOp,
523 acc::UpdateDeviceOp, acc::GetDevicePtrOp>([](
auto op) {
528 return op->
emitError(
"unsupported OpenACC operation: ")
534 registry.
insert<acc::OpenACCDialect>();
536 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.
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;.