25 #include "llvm/ADT/ArrayRef.h"
26 #include "llvm/ADT/SetVector.h"
27 #include "llvm/ADT/TypeSwitch.h"
28 #include "llvm/Frontend/OpenMP/OMPConstants.h"
29 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
30 #include "llvm/IR/DebugInfoMetadata.h"
31 #include "llvm/IR/IRBuilder.h"
32 #include "llvm/IR/ReplaceConstant.h"
33 #include "llvm/Support/FileSystem.h"
34 #include "llvm/TargetParser/Triple.h"
35 #include "llvm/Transforms/Utils/ModuleUtils.h"
47 static llvm::omp::ScheduleKind
48 convertToScheduleKind(std::optional<omp::ClauseScheduleKind> schedKind) {
49 if (!schedKind.has_value())
50 return llvm::omp::OMP_SCHEDULE_Default;
51 switch (schedKind.value()) {
52 case omp::ClauseScheduleKind::Static:
53 return llvm::omp::OMP_SCHEDULE_Static;
54 case omp::ClauseScheduleKind::Dynamic:
55 return llvm::omp::OMP_SCHEDULE_Dynamic;
56 case omp::ClauseScheduleKind::Guided:
57 return llvm::omp::OMP_SCHEDULE_Guided;
58 case omp::ClauseScheduleKind::Auto:
59 return llvm::omp::OMP_SCHEDULE_Auto;
61 return llvm::omp::OMP_SCHEDULE_Runtime;
63 llvm_unreachable(
"unhandled schedule clause argument");
68 class OpenMPAllocaStackFrame
73 explicit OpenMPAllocaStackFrame(llvm::OpenMPIRBuilder::InsertPointTy allocaIP)
74 : allocaInsertPoint(allocaIP) {}
75 llvm::OpenMPIRBuilder::InsertPointTy allocaInsertPoint;
80 class OpenMPVarMappingStackFrame
82 OpenMPVarMappingStackFrame> {
86 explicit OpenMPVarMappingStackFrame(
109 class PreviouslyReportedError
110 :
public llvm::ErrorInfo<PreviouslyReportedError> {
112 void log(raw_ostream &)
const override {
116 std::error_code convertToErrorCode()
const override {
118 "PreviouslyReportedError doesn't support ECError conversion");
132 SymbolRefAttr symbolName) {
133 omp::PrivateClauseOp privatizer =
134 SymbolTable::lookupNearestSymbolFrom<omp::PrivateClauseOp>(from,
136 assert(privatizer &&
"privatizer not found in the symbol table");
147 auto todo = [&op](StringRef clauseName) {
148 return op.
emitError() <<
"not yet implemented: Unhandled clause "
149 << clauseName <<
" in " << op.
getName()
153 auto checkAligned = [&todo](
auto op, LogicalResult &result) {
154 if (!op.getAlignedVars().empty() || op.getAlignments())
155 result = todo(
"aligned");
157 auto checkAllocate = [&todo](
auto op, LogicalResult &result) {
158 if (!op.getAllocateVars().empty() || !op.getAllocatorVars().empty())
159 result = todo(
"allocate");
161 auto checkDepend = [&todo](
auto op, LogicalResult &result) {
162 if (!op.getDependVars().empty() || op.getDependKinds())
163 result = todo(
"depend");
165 auto checkDevice = [&todo](
auto op, LogicalResult &result) {
167 result = todo(
"device");
169 auto checkHasDeviceAddr = [&todo](
auto op, LogicalResult &result) {
170 if (!op.getHasDeviceAddrVars().empty())
171 result = todo(
"has_device_addr");
173 auto checkHint = [](
auto op, LogicalResult &) {
177 auto checkIf = [&todo](
auto op, LogicalResult &result) {
181 auto checkInReduction = [&todo](
auto op, LogicalResult &result) {
182 if (!op.getInReductionVars().empty() || op.getInReductionByref() ||
183 op.getInReductionSyms())
184 result = todo(
"in_reduction");
186 auto checkIsDevicePtr = [&todo](
auto op, LogicalResult &result) {
187 if (!op.getIsDevicePtrVars().empty())
188 result = todo(
"is_device_ptr");
190 auto checkLinear = [&todo](
auto op, LogicalResult &result) {
191 if (!op.getLinearVars().empty() || !op.getLinearStepVars().empty())
192 result = todo(
"linear");
194 auto checkMergeable = [&todo](
auto op, LogicalResult &result) {
195 if (op.getMergeable())
196 result = todo(
"mergeable");
198 auto checkNontemporal = [&todo](
auto op, LogicalResult &result) {
199 if (!op.getNontemporalVars().empty())
200 result = todo(
"nontemporal");
202 auto checkNowait = [&todo](
auto op, LogicalResult &result) {
204 result = todo(
"nowait");
206 auto checkOrder = [&todo](
auto op, LogicalResult &result) {
207 if (op.getOrder() || op.getOrderMod())
208 result = todo(
"order");
210 auto checkParLevelSimd = [&todo](
auto op, LogicalResult &result) {
211 if (op.getParLevelSimd())
212 result = todo(
"parallelization-level");
214 auto checkPriority = [&todo](
auto op, LogicalResult &result) {
215 if (op.getPriority())
216 result = todo(
"priority");
218 auto checkPrivate = [&todo](
auto op, LogicalResult &result) {
219 if (!op.getPrivateVars().empty() || op.getPrivateSyms())
220 result = todo(
"privatization");
222 auto checkReduction = [&todo](
auto op, LogicalResult &result) {
223 if (!op.getReductionVars().empty() || op.getReductionByref() ||
224 op.getReductionSyms())
225 result = todo(
"reduction");
227 auto checkThreadLimit = [&todo](
auto op, LogicalResult &result) {
228 if (op.getThreadLimit())
229 result = todo(
"thread_limit");
231 auto checkTaskReduction = [&todo](
auto op, LogicalResult &result) {
232 if (!op.getTaskReductionVars().empty() || op.getTaskReductionByref() ||
233 op.getTaskReductionSyms())
234 result = todo(
"task_reduction");
236 auto checkUntied = [&todo](
auto op, LogicalResult &result) {
238 result = todo(
"untied");
241 LogicalResult result = success();
243 .Case([&](omp::OrderedRegionOp op) { checkParLevelSimd(op, result); })
244 .Case([&](omp::SectionsOp op) {
245 checkAllocate(op, result);
246 checkPrivate(op, result);
248 .Case([&](omp::SingleOp op) {
249 checkAllocate(op, result);
250 checkPrivate(op, result);
252 .Case([&](omp::TeamsOp op) {
253 checkAllocate(op, result);
254 checkPrivate(op, result);
255 checkReduction(op, result);
257 .Case([&](omp::TaskOp op) {
258 checkAllocate(op, result);
259 checkInReduction(op, result);
260 checkMergeable(op, result);
261 checkPriority(op, result);
262 checkUntied(op, result);
264 .Case([&](omp::TaskgroupOp op) {
265 checkAllocate(op, result);
266 checkTaskReduction(op, result);
268 .Case([&](omp::TaskwaitOp op) {
269 checkDepend(op, result);
270 checkNowait(op, result);
272 .Case([&](omp::WsloopOp op) {
273 checkAllocate(op, result);
274 checkLinear(op, result);
275 checkOrder(op, result);
276 checkPrivate(op, result);
278 .Case([&](omp::ParallelOp op) { checkAllocate(op, result); })
279 .Case([&](omp::SimdOp op) {
280 checkAligned(op, result);
281 checkLinear(op, result);
282 checkNontemporal(op, result);
283 checkPrivate(op, result);
284 checkReduction(op, result);
286 .Case<omp::AtomicReadOp, omp::AtomicWriteOp, omp::AtomicUpdateOp,
287 omp::AtomicCaptureOp>([&](
auto op) { checkHint(op, result); })
288 .Case<omp::TargetEnterDataOp, omp::TargetExitDataOp, omp::TargetUpdateOp>(
289 [&](
auto op) { checkDepend(op, result); })
290 .Case([&](omp::TargetOp op) {
291 checkAllocate(op, result);
292 checkDevice(op, result);
293 checkHasDeviceAddr(op, result);
295 checkInReduction(op, result);
296 checkIsDevicePtr(op, result);
300 if (std::optional<ArrayAttr> privateSyms = op.getPrivateSyms()) {
301 for (
Attribute privatizerNameAttr : *privateSyms) {
303 op.getOperation(), cast<SymbolRefAttr>(privatizerNameAttr));
305 if (privatizer.getDataSharingType() ==
306 omp::DataSharingClauseType::FirstPrivate)
307 result = todo(
"firstprivate");
309 if (!privatizer.getDeallocRegion().empty())
310 result = op.
emitError(
"not yet implemented: privatization of "
311 "structures in omp.target operation");
314 checkThreadLimit(op, result);
324 LogicalResult result = success();
326 llvm::handleAllErrors(
328 [&](
const PreviouslyReportedError &) { result = failure(); },
329 [&](
const llvm::ErrorInfoBase &err) {
336 template <
typename T>
346 static llvm::OpenMPIRBuilder::InsertPointTy
352 llvm::OpenMPIRBuilder::InsertPointTy allocaInsertPoint;
354 [&](
const OpenMPAllocaStackFrame &frame) {
355 allocaInsertPoint = frame.allocaInsertPoint;
359 return allocaInsertPoint;
368 if (builder.GetInsertBlock() ==
369 &builder.GetInsertBlock()->getParent()->getEntryBlock()) {
370 assert(builder.GetInsertPoint() == builder.GetInsertBlock()->end() &&
371 "Assuming end of basic block");
372 llvm::BasicBlock *entryBB = llvm::BasicBlock::Create(
373 builder.getContext(),
"entry", builder.GetInsertBlock()->getParent(),
374 builder.GetInsertBlock()->getNextNode());
375 builder.CreateBr(entryBB);
376 builder.SetInsertPoint(entryBB);
379 llvm::BasicBlock &funcEntryBlock =
380 builder.GetInsertBlock()->getParent()->getEntryBlock();
381 return llvm::OpenMPIRBuilder::InsertPointTy(
382 &funcEntryBlock, funcEntryBlock.getFirstInsertionPt());
391 Region ®ion, StringRef blockName, llvm::IRBuilderBase &builder,
394 llvm::BasicBlock *continuationBlock =
395 splitBB(builder,
true,
"omp.region.cont");
396 llvm::BasicBlock *sourceBlock = builder.GetInsertBlock();
398 llvm::LLVMContext &llvmContext = builder.getContext();
399 for (
Block &bb : region) {
400 llvm::BasicBlock *llvmBB = llvm::BasicBlock::Create(
401 llvmContext, blockName, builder.GetInsertBlock()->getParent(),
402 builder.GetInsertBlock()->getNextNode());
403 moduleTranslation.
mapBlock(&bb, llvmBB);
406 llvm::Instruction *sourceTerminator = sourceBlock->getTerminator();
412 bool operandsProcessed =
false;
413 unsigned numYields = 0;
415 if (omp::YieldOp yield = dyn_cast<omp::YieldOp>(bb.getTerminator())) {
416 if (!operandsProcessed) {
417 for (
unsigned i = 0, e = yield->getNumOperands(); i < e; ++i) {
418 continuationBlockPHITypes.push_back(
419 moduleTranslation.
convertType(yield->getOperand(i).getType()));
421 operandsProcessed =
true;
423 assert(continuationBlockPHITypes.size() == yield->getNumOperands() &&
424 "mismatching number of values yielded from the region");
425 for (
unsigned i = 0, e = yield->getNumOperands(); i < e; ++i) {
426 llvm::Type *operandType =
427 moduleTranslation.
convertType(yield->getOperand(i).getType());
429 assert(continuationBlockPHITypes[i] == operandType &&
430 "values of mismatching types yielded from the region");
439 if (!continuationBlockPHITypes.empty())
441 continuationBlockPHIs &&
442 "expected continuation block PHIs if converted regions yield values");
443 if (continuationBlockPHIs) {
444 llvm::IRBuilderBase::InsertPointGuard guard(builder);
445 continuationBlockPHIs->reserve(continuationBlockPHITypes.size());
446 builder.SetInsertPoint(continuationBlock, continuationBlock->begin());
447 for (llvm::Type *ty : continuationBlockPHITypes)
448 continuationBlockPHIs->push_back(builder.CreatePHI(ty, numYields));
454 for (
Block *bb : blocks) {
455 llvm::BasicBlock *llvmBB = moduleTranslation.
lookupBlock(bb);
458 if (bb->isEntryBlock()) {
459 assert(sourceTerminator->getNumSuccessors() == 1 &&
460 "provided entry block has multiple successors");
461 assert(sourceTerminator->getSuccessor(0) == continuationBlock &&
462 "ContinuationBlock is not the successor of the entry block");
463 sourceTerminator->setSuccessor(0, llvmBB);
466 llvm::IRBuilderBase::InsertPointGuard guard(builder);
468 moduleTranslation.
convertBlock(*bb, bb->isEntryBlock(), builder)))
469 return llvm::make_error<PreviouslyReportedError>();
478 Operation *terminator = bb->getTerminator();
479 if (isa<omp::TerminatorOp, omp::YieldOp>(terminator)) {
480 builder.CreateBr(continuationBlock);
482 for (
unsigned i = 0, e = terminator->
getNumOperands(); i < e; ++i)
483 (*continuationBlockPHIs)[i]->addIncoming(
497 return continuationBlock;
503 case omp::ClauseProcBindKind::Close:
504 return llvm::omp::ProcBindKind::OMP_PROC_BIND_close;
505 case omp::ClauseProcBindKind::Master:
506 return llvm::omp::ProcBindKind::OMP_PROC_BIND_master;
507 case omp::ClauseProcBindKind::Primary:
508 return llvm::omp::ProcBindKind::OMP_PROC_BIND_primary;
509 case omp::ClauseProcBindKind::Spread:
510 return llvm::omp::ProcBindKind::OMP_PROC_BIND_spread;
512 llvm_unreachable(
"Unknown ClauseProcBindKind kind");
530 for (
auto [arg, var] : llvm::zip_equal(blockArgs, operands))
535 .Case([&](omp::SimdOp op) {
536 auto blockArgIface = cast<omp::BlockArgOpenMPOpInterface>(*op);
537 forwardArgs(blockArgIface.getPrivateBlockArgs(), op.getPrivateVars());
538 forwardArgs(blockArgIface.getReductionBlockArgs(),
539 op.getReductionVars());
540 op.emitWarning() <<
"simd information on composite construct discarded";
544 return op->emitError() <<
"cannot ignore nested wrapper";
556 omp::LoopWrapperInterface parentOp,
559 loopOp.gatherWrappers(wrappers);
563 std::next(std::find(wrappers.rbegin(), wrappers.rend(), parentOp));
564 it != wrappers.rend(); ++it) {
576 auto maskedOp = cast<omp::MaskedOp>(opInst);
577 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
582 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP) {
584 auto ®ion = maskedOp.getRegion();
585 builder.restoreIP(codeGenIP);
593 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
595 llvm::Value *filterVal =
nullptr;
596 if (
auto filterVar = maskedOp.getFilteredThreadId()) {
597 filterVal = moduleTranslation.
lookupValue(filterVar);
599 llvm::LLVMContext &llvmContext = builder.getContext();
603 assert(filterVal !=
nullptr);
604 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
605 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
612 builder.restoreIP(*afterIP);
620 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
621 auto masterOp = cast<omp::MasterOp>(opInst);
626 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP) {
628 auto ®ion = masterOp.getRegion();
629 builder.restoreIP(codeGenIP);
637 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
639 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
640 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
647 builder.restoreIP(*afterIP);
655 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
656 auto criticalOp = cast<omp::CriticalOp>(opInst);
661 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP) {
663 auto ®ion = cast<omp::CriticalOp>(opInst).getRegion();
664 builder.restoreIP(codeGenIP);
672 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
674 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
675 llvm::LLVMContext &llvmContext = moduleTranslation.
getLLVMContext();
676 llvm::Constant *hint =
nullptr;
679 if (criticalOp.getNameAttr()) {
682 auto symbolRef = cast<SymbolRefAttr>(criticalOp.getNameAttr());
683 auto criticalDeclareOp =
684 SymbolTable::lookupNearestSymbolFrom<omp::CriticalDeclareOp>(criticalOp,
688 static_cast<int>(criticalDeclareOp.getHint()));
690 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
692 ompLoc, bodyGenCB, finiCB, criticalOp.getName().value_or(
""), hint);
697 builder.restoreIP(*afterIP);
706 std::optional<ArrayAttr> attr = op.getPrivateSyms();
710 privatizations.reserve(privatizations.size() + attr->size());
711 for (
auto symbolRef : attr->getAsRange<SymbolRefAttr>()) {
717 template <
typename T>
721 std::optional<ArrayAttr> attr = op.getReductionSyms();
725 reductions.reserve(reductions.size() + op.getNumReductionVars());
726 for (
auto symbolRef : attr->getAsRange<SymbolRefAttr>()) {
727 reductions.push_back(
728 SymbolTable::lookupNearestSymbolFrom<omp::DeclareReductionOp>(
739 Region ®ion, StringRef blockName, llvm::IRBuilderBase &builder,
747 if (llvm::hasSingleElement(region)) {
748 llvm::Instruction *potentialTerminator =
749 builder.GetInsertBlock()->empty() ? nullptr
750 : &builder.GetInsertBlock()->back();
752 if (potentialTerminator && potentialTerminator->isTerminator())
753 potentialTerminator->removeFromParent();
754 moduleTranslation.
mapBlock(®ion.
front(), builder.GetInsertBlock());
757 region.
front(),
true, builder)))
761 if (continuationBlockArgs)
763 *continuationBlockArgs,
770 if (potentialTerminator && potentialTerminator->isTerminator()) {
771 llvm::BasicBlock *block = builder.GetInsertBlock();
772 if (block->empty()) {
778 potentialTerminator->insertInto(block, block->begin());
780 potentialTerminator->insertAfter(&block->back());
794 if (continuationBlockArgs)
795 llvm::append_range(*continuationBlockArgs, phis);
796 builder.SetInsertPoint(*continuationBlock,
797 (*continuationBlock)->getFirstInsertionPt());
804 using OwningReductionGen =
805 std::function<llvm::OpenMPIRBuilder::InsertPointOrErrorTy(
806 llvm::OpenMPIRBuilder::InsertPointTy, llvm::Value *, llvm::Value *,
808 using OwningAtomicReductionGen =
809 std::function<llvm::OpenMPIRBuilder::InsertPointOrErrorTy(
810 llvm::OpenMPIRBuilder::InsertPointTy, llvm::Type *, llvm::Value *,
817 static OwningReductionGen
823 OwningReductionGen gen =
824 [&, decl](llvm::OpenMPIRBuilder::InsertPointTy insertPoint,
825 llvm::Value *lhs, llvm::Value *rhs,
826 llvm::Value *&result)
mutable
827 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
828 moduleTranslation.
mapValue(decl.getReductionLhsArg(), lhs);
829 moduleTranslation.
mapValue(decl.getReductionRhsArg(), rhs);
830 builder.restoreIP(insertPoint);
833 "omp.reduction.nonatomic.body", builder,
834 moduleTranslation, &phis)))
835 return llvm::createStringError(
836 "failed to inline `combiner` region of `omp.declare_reduction`");
837 assert(phis.size() == 1);
839 return builder.saveIP();
848 static OwningAtomicReductionGen
850 llvm::IRBuilderBase &builder,
852 if (decl.getAtomicReductionRegion().empty())
853 return OwningAtomicReductionGen();
858 OwningAtomicReductionGen atomicGen =
859 [&, decl](llvm::OpenMPIRBuilder::InsertPointTy insertPoint, llvm::Type *,
860 llvm::Value *lhs, llvm::Value *rhs)
mutable
861 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
862 moduleTranslation.
mapValue(decl.getAtomicReductionLhsArg(), lhs);
863 moduleTranslation.
mapValue(decl.getAtomicReductionRhsArg(), rhs);
864 builder.restoreIP(insertPoint);
867 "omp.reduction.atomic.body", builder,
868 moduleTranslation, &phis)))
869 return llvm::createStringError(
870 "failed to inline `atomic` region of `omp.declare_reduction`");
871 assert(phis.empty());
872 return builder.saveIP();
881 auto orderedOp = cast<omp::OrderedOp>(opInst);
886 omp::ClauseDepend dependType = *orderedOp.getDoacrossDependType();
887 bool isDependSource = dependType == omp::ClauseDepend::dependsource;
888 unsigned numLoops = *orderedOp.getDoacrossNumLoops();
890 moduleTranslation.
lookupValues(orderedOp.getDoacrossDependVars());
892 size_t indexVecValues = 0;
893 while (indexVecValues < vecValues.size()) {
895 storeValues.reserve(numLoops);
896 for (
unsigned i = 0; i < numLoops; i++) {
897 storeValues.push_back(vecValues[indexVecValues]);
900 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
902 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
903 builder.restoreIP(moduleTranslation.
getOpenMPBuilder()->createOrderedDepend(
904 ompLoc, allocaIP, numLoops, storeValues,
".cnt.addr", isDependSource));
914 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
915 auto orderedRegionOp = cast<omp::OrderedRegionOp>(opInst);
920 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP) {
922 auto ®ion = cast<omp::OrderedRegionOp>(opInst).getRegion();
923 builder.restoreIP(codeGenIP);
931 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
933 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
934 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
936 ompLoc, bodyGenCB, finiCB, !orderedRegionOp.getParLevelSimd());
941 builder.restoreIP(*afterIP);
947 struct DeferredStore {
948 DeferredStore(llvm::Value *value, llvm::Value *address)
949 : value(value), address(address) {}
952 llvm::Value *address;
959 template <
typename T>
962 llvm::IRBuilderBase &builder,
964 const llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
970 llvm::IRBuilderBase::InsertPointGuard guard(builder);
971 builder.SetInsertPoint(allocaIP.getBlock()->getTerminator());
974 deferredStores.reserve(loop.getNumReductionVars());
976 for (std::size_t i = 0; i < loop.getNumReductionVars(); ++i) {
977 Region &allocRegion = reductionDecls[i].getAllocRegion();
979 if (allocRegion.
empty())
984 builder, moduleTranslation, &phis)))
985 return loop.emitError(
986 "failed to inline `alloc` region of `omp.declare_reduction`");
988 assert(phis.size() == 1 &&
"expected one allocation to be yielded");
989 builder.SetInsertPoint(allocaIP.getBlock()->getTerminator());
993 llvm::Value *var = builder.CreateAlloca(
994 moduleTranslation.
convertType(reductionDecls[i].getType()));
995 deferredStores.emplace_back(phis[0], var);
997 privateReductionVariables[i] = var;
998 moduleTranslation.
mapValue(reductionArgs[i], phis[0]);
999 reductionVariableMap.try_emplace(loop.getReductionVars()[i], phis[0]);
1001 assert(allocRegion.
empty() &&
1002 "allocaction is implicit for by-val reduction");
1003 llvm::Value *var = builder.CreateAlloca(
1004 moduleTranslation.
convertType(reductionDecls[i].getType()));
1005 moduleTranslation.
mapValue(reductionArgs[i], var);
1006 privateReductionVariables[i] = var;
1007 reductionVariableMap.try_emplace(loop.getReductionVars()[i], var);
1015 template <
typename T>
1022 mlir::omp::DeclareReductionOp &reduction = reductionDecls[i];
1023 Region &initializerRegion = reduction.getInitializerRegion();
1026 mlir::Value mlirSource = loop.getReductionVars()[i];
1027 llvm::Value *llvmSource = moduleTranslation.
lookupValue(mlirSource);
1028 assert(llvmSource &&
"lookup reduction var");
1029 moduleTranslation.
mapValue(reduction.getInitializerMoldArg(), llvmSource);
1032 llvm::Value *allocation =
1033 reductionVariableMap.lookup(loop.getReductionVars()[i]);
1034 moduleTranslation.
mapValue(reduction.getInitializerAllocArg(), allocation);
1039 template <
typename T>
1041 T loop, llvm::IRBuilderBase &builder,
1048 unsigned numReductions = loop.getNumReductionVars();
1050 for (
unsigned i = 0; i < numReductions; ++i) {
1051 owningReductionGens.push_back(
1053 owningAtomicReductionGens.push_back(
1058 reductionInfos.reserve(numReductions);
1059 for (
unsigned i = 0; i < numReductions; ++i) {
1060 llvm::OpenMPIRBuilder::ReductionGenAtomicCBTy atomicGen =
nullptr;
1061 if (owningAtomicReductionGens[i])
1062 atomicGen = owningAtomicReductionGens[i];
1063 llvm::Value *variable =
1064 moduleTranslation.
lookupValue(loop.getReductionVars()[i]);
1065 reductionInfos.push_back(
1067 privateReductionVariables[i],
1068 llvm::OpenMPIRBuilder::EvalKind::Scalar,
1069 owningReductionGens[i],
1070 nullptr, atomicGen});
1075 static LogicalResult
1079 llvm::IRBuilderBase &builder, StringRef regionName,
1080 bool shouldLoadCleanupRegionArg =
true) {
1082 if (cleanupRegion->empty())
1088 llvm::Instruction *potentialTerminator =
1089 builder.GetInsertBlock()->empty() ? nullptr
1090 : &builder.GetInsertBlock()->back();
1091 if (potentialTerminator && potentialTerminator->isTerminator())
1092 builder.SetInsertPoint(potentialTerminator);
1093 llvm::Value *privateVarValue =
1094 shouldLoadCleanupRegionArg
1095 ? builder.CreateLoad(
1097 privateVariables[i])
1098 : privateVariables[i];
1103 moduleTranslation)))
1116 OP op, llvm::IRBuilderBase &builder,
1118 llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
1122 if (op.getNumReductionVars() == 0)
1133 owningReductionGens, owningAtomicReductionGens,
1134 privateReductionVariables, reductionInfos);
1139 llvm::UnreachableInst *tempTerminator = builder.CreateUnreachable();
1140 builder.SetInsertPoint(tempTerminator);
1141 llvm::OpenMPIRBuilder::InsertPointOrErrorTy contInsertPoint =
1142 ompBuilder->createReductions(builder.saveIP(), allocaIP, reductionInfos,
1143 isByRef, op.getNowait());
1148 if (!contInsertPoint->getBlock())
1149 return op->emitOpError() <<
"failed to convert reductions";
1151 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
1152 ompBuilder->createBarrier(*contInsertPoint, llvm::omp::OMPD_for);
1157 tempTerminator->eraseFromParent();
1158 builder.restoreIP(*afterIP);
1162 llvm::transform(reductionDecls, std::back_inserter(reductionRegions),
1163 [](omp::DeclareReductionOp reductionDecl) {
1164 return &reductionDecl.getCleanupRegion();
1167 moduleTranslation, builder,
1168 "omp.reduction.cleanup");
1179 template <
typename OP>
1183 llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
1188 if (op.getNumReductionVars() == 0)
1194 allocaIP, reductionDecls,
1195 privateReductionVariables, reductionVariableMap,
1196 deferredStores, isByRef)))
1201 for (
auto [data, addr] : deferredStores)
1202 builder.CreateStore(data, addr);
1207 for (
unsigned i = 0; i < op.getNumReductionVars(); ++i) {
1212 reductionVariableMap, i);
1215 "omp.reduction.neutral", builder,
1216 moduleTranslation, &phis)))
1218 assert(phis.size() == 1 &&
"expected one value to be yielded from the "
1219 "reduction neutral element declaration region");
1221 if (!reductionDecls[i].getAllocRegion().empty())
1230 llvm::Value *var = builder.CreateAlloca(
1231 moduleTranslation.
convertType(reductionDecls[i].getType()));
1234 builder.CreateStore(phis[0], var);
1236 privateReductionVariables[i] = var;
1237 moduleTranslation.
mapValue(reductionArgs[i], phis[0]);
1238 reductionVariableMap.try_emplace(op.getReductionVars()[i], phis[0]);
1241 builder.CreateStore(phis[0], privateReductionVariables[i]);
1248 moduleTranslation.
forgetMapping(reductionDecls[i].getInitializerRegion());
1264 const llvm::OpenMPIRBuilder::InsertPointTy &allocaIP) {
1266 llvm::BranchInst *allocaTerminator =
1267 llvm::cast<llvm::BranchInst>(allocaIP.getBlock()->getTerminator());
1268 builder.SetInsertPoint(allocaTerminator);
1269 assert(allocaTerminator->getNumSuccessors() == 1 &&
1270 "This is an unconditional branch created by OpenMPIRBuilder");
1271 llvm::BasicBlock *afterAllocas = allocaTerminator->getSuccessor(0);
1285 llvm::BasicBlock *privAllocBlock =
nullptr;
1286 if (!privateBlockArgs.empty())
1287 privAllocBlock = splitBB(builder,
true,
"omp.private.latealloc");
1288 for (
auto [privDecl, mlirPrivVar, blockArg] :
1289 llvm::zip_equal(privateDecls, mlirPrivateVars, privateBlockArgs)) {
1290 Region &allocRegion = privDecl.getAllocRegion();
1293 llvm::Value *nonPrivateVar = moduleTranslation.
lookupValue(mlirPrivVar);
1294 assert(nonPrivateVar);
1295 moduleTranslation.
mapValue(privDecl.getAllocMoldArg(), nonPrivateVar);
1299 if (privDecl.getAllocMoldArg().getUses().empty()) {
1304 builder.SetInsertPoint(allocaIP.getBlock()->getTerminator());
1306 builder.SetInsertPoint(privAllocBlock->getTerminator());
1309 builder, moduleTranslation, &phis)))
1310 return llvm::createStringError(
1311 "failed to inline `alloc` region of `omp.private`");
1313 assert(phis.size() == 1 &&
"expected one allocation to be yielded");
1315 moduleTranslation.
mapValue(blockArg, phis[0]);
1316 llvmPrivateVars.push_back(phis[0]);
1323 return afterAllocas;
1326 static LogicalResult
1329 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1330 using StorableBodyGenCallbackTy =
1331 llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
1333 auto sectionsOp = cast<omp::SectionsOp>(opInst);
1339 assert(isByRef.size() == sectionsOp.getNumReductionVars());
1343 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
1347 sectionsOp.getNumReductionVars());
1351 cast<omp::BlockArgOpenMPOpInterface>(opInst).getReductionBlockArgs();
1354 sectionsOp, reductionArgs, builder, moduleTranslation, allocaIP,
1355 reductionDecls, privateReductionVariables, reductionVariableMap,
1363 moduleTranslation, reductionVariableMap);
1368 auto sectionOp = dyn_cast<omp::SectionOp>(op);
1372 Region ®ion = sectionOp.getRegion();
1373 auto sectionCB = [§ionsOp, ®ion, &builder, &moduleTranslation](
1374 InsertPointTy allocaIP, InsertPointTy codeGenIP) {
1375 builder.restoreIP(codeGenIP);
1382 sectionsOp.getRegion().getNumArguments());
1383 for (
auto [sectionsArg, sectionArg] : llvm::zip_equal(
1384 sectionsOp.getRegion().getArguments(), region.
getArguments())) {
1385 llvm::Value *llvmVal = moduleTranslation.
lookupValue(sectionsArg);
1387 moduleTranslation.
mapValue(sectionArg, llvmVal);
1394 sectionCBs.push_back(sectionCB);
1400 if (sectionCBs.empty())
1403 assert(isa<omp::SectionOp>(*sectionsOp.getRegion().op_begin()));
1408 auto privCB = [&](InsertPointTy, InsertPointTy codeGenIP, llvm::Value &,
1409 llvm::Value &vPtr, llvm::Value *&replacementValue)
1410 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
1411 replacementValue = &vPtr;
1417 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
1420 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
1421 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
1423 ompLoc, allocaIP, sectionCBs, privCB, finiCB,
false,
1424 sectionsOp.getNowait());
1429 builder.restoreIP(*afterIP);
1433 allocaIP, reductionDecls,
1434 privateReductionVariables, isByRef);
1438 static LogicalResult
1441 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1442 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
1447 auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codegenIP) {
1448 builder.restoreIP(codegenIP);
1450 builder, moduleTranslation)
1453 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
1457 std::optional<ArrayAttr> cpFuncs = singleOp.getCopyprivateSyms();
1460 for (
size_t i = 0, e = cpVars.size(); i < e; ++i) {
1461 llvmCPVars.push_back(moduleTranslation.
lookupValue(cpVars[i]));
1462 auto llvmFuncOp = SymbolTable::lookupNearestSymbolFrom<LLVM::LLVMFuncOp>(
1463 singleOp, cast<SymbolRefAttr>((*cpFuncs)[i]));
1464 llvmCPFuncs.push_back(
1468 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
1470 ompLoc, bodyCB, finiCB, singleOp.getNowait(), llvmCPVars,
1476 builder.restoreIP(*afterIP);
1481 static LogicalResult
1484 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1488 auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codegenIP) {
1490 moduleTranslation, allocaIP);
1491 builder.restoreIP(codegenIP);
1497 llvm::Value *numTeamsLower =
nullptr;
1498 if (
Value numTeamsLowerVar = op.getNumTeamsLower())
1499 numTeamsLower = moduleTranslation.
lookupValue(numTeamsLowerVar);
1501 llvm::Value *numTeamsUpper =
nullptr;
1502 if (
Value numTeamsUpperVar = op.getNumTeamsUpper())
1503 numTeamsUpper = moduleTranslation.
lookupValue(numTeamsUpperVar);
1505 llvm::Value *threadLimit =
nullptr;
1506 if (
Value threadLimitVar = op.getThreadLimit())
1507 threadLimit = moduleTranslation.
lookupValue(threadLimitVar);
1509 llvm::Value *ifExpr =
nullptr;
1510 if (
Value ifVar = op.getIfExpr())
1513 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
1514 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
1516 ompLoc, bodyCB, numTeamsLower, numTeamsUpper, threadLimit, ifExpr);
1521 builder.restoreIP(*afterIP);
1529 if (dependVars.empty())
1531 for (
auto dep : llvm::zip(dependVars, dependKinds->getValue())) {
1532 llvm::omp::RTLDependenceKindTy type;
1534 cast<mlir::omp::ClauseTaskDependAttr>(std::get<1>(dep)).getValue()) {
1535 case mlir::omp::ClauseTaskDepend::taskdependin:
1536 type = llvm::omp::RTLDependenceKindTy::DepIn;
1541 case mlir::omp::ClauseTaskDepend::taskdependout:
1542 case mlir::omp::ClauseTaskDepend::taskdependinout:
1543 type = llvm::omp::RTLDependenceKindTy::DepInOut;
1546 llvm::Value *depVal = moduleTranslation.
lookupValue(std::get<0>(dep));
1547 llvm::OpenMPIRBuilder::DependData dd(type, depVal->getType(), depVal);
1548 dds.emplace_back(dd);
1553 static LogicalResult
1556 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1562 cast<omp::BlockArgOpenMPOpInterface>(*taskOp).getPrivateBlockArgs();
1566 mlirPrivateVars.reserve(privateBlockArgs.size());
1567 llvmPrivateVars.reserve(privateBlockArgs.size());
1569 for (
mlir::Value privateVar : taskOp.getPrivateVars())
1570 mlirPrivateVars.push_back(privateVar);
1572 auto bodyCB = [&](InsertPointTy allocaIP,
1573 InsertPointTy codegenIP) -> llvm::Error {
1577 moduleTranslation, allocaIP);
1580 builder, moduleTranslation, privateBlockArgs, privateDecls,
1581 mlirPrivateVars, llvmPrivateVars, allocaIP);
1583 return llvm::make_error<PreviouslyReportedError>();
1586 bool needsFirstPrivate =
1587 llvm::any_of(privateDecls, [](omp::PrivateClauseOp &privOp) {
1588 return privOp.getDataSharingType() ==
1589 omp::DataSharingClauseType::FirstPrivate;
1591 if (needsFirstPrivate) {
1593 assert(afterAllocas.get()->getSinglePredecessor());
1594 builder.SetInsertPoint(
1595 afterAllocas.get()->getSinglePredecessor()->getTerminator());
1596 llvm::BasicBlock *copyBlock =
1597 splitBB(builder,
true,
"omp.private.copy");
1598 builder.SetInsertPoint(copyBlock->getFirstNonPHIOrDbgOrAlloca());
1600 for (
auto [decl, mlirVar, llvmVar] :
1601 llvm::zip_equal(privateDecls, mlirPrivateVars, llvmPrivateVars)) {
1602 if (decl.getDataSharingType() != omp::DataSharingClauseType::FirstPrivate)
1606 Region ©Region = decl.getCopyRegion();
1609 llvm::Value *nonPrivateVar = moduleTranslation.
lookupValue(mlirVar);
1610 assert(nonPrivateVar);
1611 moduleTranslation.
mapValue(decl.getCopyMoldArg(), nonPrivateVar);
1614 moduleTranslation.
mapValue(decl.getCopyPrivateArg(), llvmVar);
1617 builder.SetInsertPoint(builder.GetInsertBlock()->getTerminator());
1619 builder, moduleTranslation)))
1620 return llvm::createStringError(
1621 "failed to inline `copy` region of an `omp.private` op in taskOp");
1631 builder.restoreIP(codegenIP);
1633 taskOp.getRegion(),
"omp.task.region", builder, moduleTranslation);
1634 if (failed(
handleError(continuationBlockOrError, *taskOp)))
1635 return llvm::make_error<PreviouslyReportedError>();
1639 llvm::transform(privateDecls, std::back_inserter(privateCleanupRegions),
1640 [](omp::PrivateClauseOp privatizer) {
1641 return &privatizer.getDeallocRegion();
1644 builder.SetInsertPoint(continuationBlockOrError.get()->getTerminator());
1646 privateCleanupRegions, llvmPrivateVars, moduleTranslation, builder,
1647 "omp.private.dealloc",
false)))
1648 return llvm::createStringError(
"failed to inline `dealloc` region of an "
1649 "`omp.private` op in an omp.task");
1651 return llvm::Error::success();
1656 moduleTranslation, dds);
1658 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
1660 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
1661 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
1663 ompLoc, allocaIP, bodyCB, !taskOp.getUntied(),
1665 moduleTranslation.
lookupValue(taskOp.getIfExpr()), dds);
1670 builder.restoreIP(*afterIP);
1675 static LogicalResult
1678 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1682 auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codegenIP) {
1683 builder.restoreIP(codegenIP);
1685 builder, moduleTranslation)
1690 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
1691 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
1698 builder.restoreIP(*afterIP);
1702 static LogicalResult
1713 static LogicalResult
1716 auto wsloopOp = cast<omp::WsloopOp>(opInst);
1720 auto loopOp = cast<omp::LoopNestOp>(wsloopOp.getWrappedLoop());
1723 assert(isByRef.size() == wsloopOp.getNumReductionVars());
1727 wsloopOp.getScheduleKind().value_or(omp::ClauseScheduleKind::Static);
1730 llvm::Value *step = moduleTranslation.
lookupValue(loopOp.getLoopSteps()[0]);
1731 llvm::Type *ivType = step->getType();
1732 llvm::Value *chunk =
nullptr;
1733 if (wsloopOp.getScheduleChunk()) {
1734 llvm::Value *chunkVar =
1735 moduleTranslation.
lookupValue(wsloopOp.getScheduleChunk());
1736 chunk = builder.CreateSExtOrTrunc(chunkVar, ivType);
1741 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
1745 wsloopOp.getNumReductionVars());
1749 cast<omp::BlockArgOpenMPOpInterface>(opInst).getReductionBlockArgs();
1752 wsloopOp, reductionArgs, builder, moduleTranslation, allocaIP,
1753 reductionDecls, privateReductionVariables, reductionVariableMap,
1768 moduleTranslation, reductionVariableMap);
1771 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
1776 auto bodyGen = [&](llvm::OpenMPIRBuilder::InsertPointTy ip,
1777 llvm::Value *iv) -> llvm::Error {
1780 loopOp.getRegion().front().getArgument(loopInfos.size()), iv);
1785 bodyInsertPoints.push_back(ip);
1787 if (loopInfos.size() != loopOp.getNumLoops() - 1)
1788 return llvm::Error::success();
1791 builder.restoreIP(ip);
1803 for (
unsigned i = 0, e = loopOp.getNumLoops(); i < e; ++i) {
1804 llvm::Value *lowerBound =
1805 moduleTranslation.
lookupValue(loopOp.getLoopLowerBounds()[i]);
1806 llvm::Value *upperBound =
1807 moduleTranslation.
lookupValue(loopOp.getLoopUpperBounds()[i]);
1808 llvm::Value *step = moduleTranslation.
lookupValue(loopOp.getLoopSteps()[i]);
1813 llvm::OpenMPIRBuilder::LocationDescription loc = ompLoc;
1814 llvm::OpenMPIRBuilder::InsertPointTy computeIP = ompLoc.IP;
1816 loc = llvm::OpenMPIRBuilder::LocationDescription(bodyInsertPoints.back());
1817 computeIP = loopInfos.front()->getPreheaderIP();
1821 ompBuilder->createCanonicalLoop(
1822 loc, bodyGen, lowerBound, upperBound, step,
1823 true, loopOp.getLoopInclusive(), computeIP);
1828 loopInfos.push_back(*loopResult);
1833 llvm::IRBuilderBase::InsertPoint afterIP = loopInfos.front()->getAfterIP();
1834 llvm::CanonicalLoopInfo *loopInfo =
1835 ompBuilder->collapseLoops(ompLoc.DL, loopInfos, {});
1840 bool isOrdered = wsloopOp.getOrdered().has_value();
1841 std::optional<omp::ScheduleModifier> scheduleMod = wsloopOp.getScheduleMod();
1842 bool isSimd = wsloopOp.getScheduleSimd();
1844 llvm::OpenMPIRBuilder::InsertPointOrErrorTy wsloopIP =
1845 ompBuilder->applyWorkshareLoop(
1846 ompLoc.DL, loopInfo, allocaIP, !wsloopOp.getNowait(),
1847 convertToScheduleKind(schedule), chunk, isSimd,
1848 scheduleMod == omp::ScheduleModifier::monotonic,
1849 scheduleMod == omp::ScheduleModifier::nonmonotonic, isOrdered);
1858 builder.restoreIP(afterIP);
1862 allocaIP, reductionDecls,
1863 privateReductionVariables, isByRef);
1867 static LogicalResult
1870 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1872 assert(isByRef.size() == opInst.getNumReductionVars());
1880 cast<omp::BlockArgOpenMPOpInterface>(*opInst).getPrivateBlockArgs();
1884 mlirPrivateVars.reserve(privateBlockArgs.size());
1885 llvmPrivateVars.reserve(privateBlockArgs.size());
1887 for (
mlir::Value privateVar : opInst.getPrivateVars())
1888 mlirPrivateVars.push_back(privateVar);
1894 opInst.getNumReductionVars());
1897 auto bodyGenCB = [&](InsertPointTy allocaIP,
1898 InsertPointTy codeGenIP) -> llvm::Error {
1900 builder, moduleTranslation, privateBlockArgs, privateDecls,
1901 mlirPrivateVars, llvmPrivateVars, allocaIP);
1903 return llvm::make_error<PreviouslyReportedError>();
1909 cast<omp::BlockArgOpenMPOpInterface>(*opInst).getReductionBlockArgs();
1912 InsertPointTy(allocaIP.getBlock(),
1913 allocaIP.getBlock()->getTerminator()->getIterator());
1916 opInst, reductionArgs, builder, moduleTranslation, allocaIP,
1917 reductionDecls, privateReductionVariables, reductionVariableMap,
1918 deferredStores, isByRef)))
1919 return llvm::make_error<PreviouslyReportedError>();
1922 bool needsFirstprivate =
1923 llvm::any_of(privateDecls, [](omp::PrivateClauseOp &privOp) {
1924 return privOp.getDataSharingType() ==
1925 omp::DataSharingClauseType::FirstPrivate;
1927 if (needsFirstprivate) {
1929 assert(afterAllocas.get()->getSinglePredecessor());
1930 builder.SetInsertPoint(
1931 afterAllocas.get()->getSinglePredecessor()->getTerminator());
1932 llvm::BasicBlock *copyBlock =
1933 splitBB(builder,
true,
"omp.private.copy");
1934 builder.SetInsertPoint(copyBlock->getFirstNonPHIOrDbgOrAlloca());
1936 for (
auto [decl, mlirVar, llvmVar] :
1937 llvm::zip_equal(privateDecls, mlirPrivateVars, llvmPrivateVars)) {
1938 if (decl.getDataSharingType() != omp::DataSharingClauseType::FirstPrivate)
1942 Region ©Region = decl.getCopyRegion();
1945 llvm::Value *nonPrivateVar = moduleTranslation.
lookupValue(mlirVar);
1946 assert(nonPrivateVar);
1947 moduleTranslation.
mapValue(decl.getCopyMoldArg(), nonPrivateVar);
1950 moduleTranslation.
mapValue(decl.getCopyPrivateArg(), llvmVar);
1953 builder.SetInsertPoint(builder.GetInsertBlock()->getTerminator());
1955 builder, moduleTranslation)))
1956 return llvm::createStringError(
1957 "failed to inline `copy` region of `omp.private`");
1968 builder.SetInsertPoint(builder.GetInsertBlock()->getTerminator());
1969 llvm::BasicBlock *initBlock = splitBB(builder,
true,
"omp.reduction.init");
1971 InsertPointTy(allocaIP.getBlock(),
1972 allocaIP.getBlock()->getTerminator()->getIterator());
1974 builder.restoreIP(allocaIP);
1976 for (
unsigned i = 0; i < opInst.getNumReductionVars(); ++i) {
1978 if (!reductionDecls[i].getAllocRegion().empty())
1984 byRefVars[i] = builder.CreateAlloca(
1985 moduleTranslation.
convertType(reductionDecls[i].getType()));
1989 builder.SetInsertPoint(initBlock->getFirstNonPHIOrDbgOrAlloca());
1994 for (
auto [data, addr] : deferredStores)
1995 builder.CreateStore(data, addr);
1997 for (
unsigned i = 0; i < opInst.getNumReductionVars(); ++i) {
2002 reductionVariableMap, i);
2004 reductionDecls[i].getInitializerRegion(),
"omp.reduction.neutral",
2005 builder, moduleTranslation, &phis)))
2006 return llvm::createStringError(
2007 "failed to inline `init` region of `omp.declare_reduction`");
2008 assert(phis.size() == 1 &&
2009 "expected one value to be yielded from the "
2010 "reduction neutral element declaration region");
2012 builder.SetInsertPoint(builder.GetInsertBlock()->getTerminator());
2015 if (!reductionDecls[i].getAllocRegion().empty())
2022 builder.CreateStore(phis[0], byRefVars[i]);
2024 privateReductionVariables[i] = byRefVars[i];
2025 moduleTranslation.
mapValue(reductionArgs[i], phis[0]);
2026 reductionVariableMap.try_emplace(opInst.getReductionVars()[i], phis[0]);
2029 builder.CreateStore(phis[0], privateReductionVariables[i]);
2035 moduleTranslation.
forgetMapping(reductionDecls[i].getInitializerRegion());
2042 moduleTranslation, reductionVariableMap);
2047 moduleTranslation, allocaIP);
2050 builder.restoreIP(codeGenIP);
2052 opInst.getRegion(),
"omp.par.region", builder, moduleTranslation);
2054 return regionBlock.takeError();
2057 if (opInst.getNumReductionVars() > 0) {
2063 owningReductionGens, owningAtomicReductionGens,
2064 privateReductionVariables, reductionInfos);
2067 builder.SetInsertPoint((*regionBlock)->getTerminator());
2070 llvm::UnreachableInst *tempTerminator = builder.CreateUnreachable();
2071 builder.SetInsertPoint(tempTerminator);
2073 llvm::OpenMPIRBuilder::InsertPointOrErrorTy contInsertPoint =
2074 ompBuilder->createReductions(builder.saveIP(), allocaIP,
2075 reductionInfos, isByRef,
false);
2076 if (!contInsertPoint)
2077 return contInsertPoint.takeError();
2079 if (!contInsertPoint->getBlock())
2080 return llvm::make_error<PreviouslyReportedError>();
2082 tempTerminator->eraseFromParent();
2083 builder.restoreIP(*contInsertPoint);
2085 return llvm::Error::success();
2088 auto privCB = [](InsertPointTy allocaIP, InsertPointTy codeGenIP,
2089 llvm::Value &, llvm::Value &val, llvm::Value *&replVal) {
2098 auto finiCB = [&](InsertPointTy codeGenIP) -> llvm::Error {
2099 InsertPointTy oldIP = builder.saveIP();
2100 builder.restoreIP(codeGenIP);
2105 llvm::transform(reductionDecls, std::back_inserter(reductionCleanupRegions),
2106 [](omp::DeclareReductionOp reductionDecl) {
2107 return &reductionDecl.getCleanupRegion();
2110 reductionCleanupRegions, privateReductionVariables,
2111 moduleTranslation, builder,
"omp.reduction.cleanup")))
2112 return llvm::createStringError(
2113 "failed to inline `cleanup` region of `omp.declare_reduction`");
2116 llvm::transform(privateDecls, std::back_inserter(privateCleanupRegions),
2117 [](omp::PrivateClauseOp privatizer) {
2118 return &privatizer.getDeallocRegion();
2122 privateCleanupRegions, llvmPrivateVars, moduleTranslation, builder,
2123 "omp.private.dealloc",
false)))
2124 return llvm::createStringError(
2125 "failed to inline `dealloc` region of `omp.private`");
2127 builder.restoreIP(oldIP);
2128 return llvm::Error::success();
2131 llvm::Value *ifCond =
nullptr;
2132 if (
auto ifVar = opInst.getIfExpr())
2134 llvm::Value *numThreads =
nullptr;
2135 if (
auto numThreadsVar = opInst.getNumThreads())
2136 numThreads = moduleTranslation.
lookupValue(numThreadsVar);
2137 auto pbKind = llvm::omp::OMP_PROC_BIND_default;
2138 if (
auto bind = opInst.getProcBindKind())
2141 bool isCancellable =
false;
2143 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
2145 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2147 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2148 ompBuilder->createParallel(ompLoc, allocaIP, bodyGenCB, privCB, finiCB,
2149 ifCond, numThreads, pbKind, isCancellable);
2154 builder.restoreIP(*afterIP);
2159 static llvm::omp::OrderKind
2162 return llvm::omp::OrderKind::OMP_ORDER_unknown;
2164 case omp::ClauseOrderKind::Concurrent:
2165 return llvm::omp::OrderKind::OMP_ORDER_concurrent;
2167 llvm_unreachable(
"Unknown ClauseOrderKind kind");
2171 static LogicalResult
2174 auto simdOp = cast<omp::SimdOp>(opInst);
2175 auto loopOp = cast<omp::LoopNestOp>(simdOp.getWrappedLoop());
2180 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2185 auto bodyGen = [&](llvm::OpenMPIRBuilder::InsertPointTy ip,
2186 llvm::Value *iv) -> llvm::Error {
2189 loopOp.getRegion().front().getArgument(loopInfos.size()), iv);
2194 bodyInsertPoints.push_back(ip);
2196 if (loopInfos.size() != loopOp.getNumLoops() - 1)
2197 return llvm::Error::success();
2200 builder.restoreIP(ip);
2212 for (
unsigned i = 0, e = loopOp.getNumLoops(); i < e; ++i) {
2213 llvm::Value *lowerBound =
2214 moduleTranslation.
lookupValue(loopOp.getLoopLowerBounds()[i]);
2215 llvm::Value *upperBound =
2216 moduleTranslation.
lookupValue(loopOp.getLoopUpperBounds()[i]);
2217 llvm::Value *step = moduleTranslation.
lookupValue(loopOp.getLoopSteps()[i]);
2222 llvm::OpenMPIRBuilder::LocationDescription loc = ompLoc;
2223 llvm::OpenMPIRBuilder::InsertPointTy computeIP = ompLoc.IP;
2225 loc = llvm::OpenMPIRBuilder::LocationDescription(bodyInsertPoints.back(),
2227 computeIP = loopInfos.front()->getPreheaderIP();
2231 ompBuilder->createCanonicalLoop(
2232 loc, bodyGen, lowerBound, upperBound, step,
2233 true,
true, computeIP);
2238 loopInfos.push_back(*loopResult);
2242 llvm::IRBuilderBase::InsertPoint afterIP = loopInfos.front()->getAfterIP();
2243 llvm::CanonicalLoopInfo *loopInfo =
2244 ompBuilder->collapseLoops(ompLoc.DL, loopInfos, {});
2246 llvm::ConstantInt *simdlen =
nullptr;
2247 if (std::optional<uint64_t> simdlenVar = simdOp.getSimdlen())
2248 simdlen = builder.getInt64(simdlenVar.value());
2250 llvm::ConstantInt *safelen =
nullptr;
2251 if (std::optional<uint64_t> safelenVar = simdOp.getSafelen())
2252 safelen = builder.getInt64(safelenVar.value());
2254 llvm::MapVector<llvm::Value *, llvm::Value *> alignedVars;
2256 ompBuilder->applySimd(loopInfo, alignedVars,
2258 ? moduleTranslation.
lookupValue(simdOp.getIfExpr())
2260 order, simdlen, safelen);
2262 builder.restoreIP(afterIP);
2267 static llvm::AtomicOrdering
2270 return llvm::AtomicOrdering::Monotonic;
2273 case omp::ClauseMemoryOrderKind::Seq_cst:
2274 return llvm::AtomicOrdering::SequentiallyConsistent;
2275 case omp::ClauseMemoryOrderKind::Acq_rel:
2276 return llvm::AtomicOrdering::AcquireRelease;
2277 case omp::ClauseMemoryOrderKind::Acquire:
2278 return llvm::AtomicOrdering::Acquire;
2279 case omp::ClauseMemoryOrderKind::Release:
2280 return llvm::AtomicOrdering::Release;
2281 case omp::ClauseMemoryOrderKind::Relaxed:
2282 return llvm::AtomicOrdering::Monotonic;
2284 llvm_unreachable(
"Unknown ClauseMemoryOrderKind kind");
2288 static LogicalResult
2291 auto readOp = cast<omp::AtomicReadOp>(opInst);
2297 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2300 llvm::Value *x = moduleTranslation.
lookupValue(readOp.getX());
2301 llvm::Value *v = moduleTranslation.
lookupValue(readOp.getV());
2303 llvm::Type *elementType =
2304 moduleTranslation.
convertType(readOp.getElementType());
2306 llvm::OpenMPIRBuilder::AtomicOpValue V = {v, elementType,
false,
false};
2307 llvm::OpenMPIRBuilder::AtomicOpValue X = {x, elementType,
false,
false};
2308 builder.restoreIP(ompBuilder->createAtomicRead(ompLoc, X, V, AO));
2313 static LogicalResult
2316 auto writeOp = cast<omp::AtomicWriteOp>(opInst);
2322 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2324 llvm::Value *expr = moduleTranslation.
lookupValue(writeOp.getExpr());
2325 llvm::Value *dest = moduleTranslation.
lookupValue(writeOp.getX());
2326 llvm::Type *ty = moduleTranslation.
convertType(writeOp.getExpr().getType());
2327 llvm::OpenMPIRBuilder::AtomicOpValue x = {dest, ty,
false,
2329 builder.restoreIP(ompBuilder->createAtomicWrite(ompLoc, x, expr, ao));
2337 .Case([&](LLVM::AddOp) {
return llvm::AtomicRMWInst::BinOp::Add; })
2338 .Case([&](LLVM::SubOp) {
return llvm::AtomicRMWInst::BinOp::Sub; })
2339 .Case([&](LLVM::AndOp) {
return llvm::AtomicRMWInst::BinOp::And; })
2340 .Case([&](LLVM::OrOp) {
return llvm::AtomicRMWInst::BinOp::Or; })
2341 .Case([&](LLVM::XOrOp) {
return llvm::AtomicRMWInst::BinOp::Xor; })
2342 .Case([&](LLVM::UMaxOp) {
return llvm::AtomicRMWInst::BinOp::UMax; })
2343 .Case([&](LLVM::UMinOp) {
return llvm::AtomicRMWInst::BinOp::UMin; })
2344 .Case([&](LLVM::FAddOp) {
return llvm::AtomicRMWInst::BinOp::FAdd; })
2345 .Case([&](LLVM::FSubOp) {
return llvm::AtomicRMWInst::BinOp::FSub; })
2346 .Default(llvm::AtomicRMWInst::BinOp::BAD_BINOP);
2350 static LogicalResult
2352 llvm::IRBuilderBase &builder,
2359 auto &innerOpList = opInst.getRegion().front().getOperations();
2360 bool isXBinopExpr{
false};
2361 llvm::AtomicRMWInst::BinOp binop;
2363 llvm::Value *llvmExpr =
nullptr;
2364 llvm::Value *llvmX =
nullptr;
2365 llvm::Type *llvmXElementType =
nullptr;
2366 if (innerOpList.size() == 2) {
2372 opInst.getRegion().getArgument(0))) {
2373 return opInst.emitError(
"no atomic update operation with region argument"
2374 " as operand found inside atomic.update region");
2377 isXBinopExpr = innerOp.
getOperand(0) == opInst.getRegion().getArgument(0);
2379 llvmExpr = moduleTranslation.
lookupValue(mlirExpr);
2383 binop = llvm::AtomicRMWInst::BinOp::BAD_BINOP;
2385 llvmX = moduleTranslation.
lookupValue(opInst.getX());
2387 opInst.getRegion().getArgument(0).getType());
2388 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {llvmX, llvmXElementType,
2392 llvm::AtomicOrdering atomicOrdering =
2397 [&opInst, &moduleTranslation](
2398 llvm::Value *atomicx,
2401 moduleTranslation.
mapValue(*opInst.getRegion().args_begin(), atomicx);
2402 moduleTranslation.
mapBlock(&bb, builder.GetInsertBlock());
2403 if (failed(moduleTranslation.
convertBlock(bb,
true, builder)))
2404 return llvm::make_error<PreviouslyReportedError>();
2406 omp::YieldOp yieldop = dyn_cast<omp::YieldOp>(bb.
getTerminator());
2407 assert(yieldop && yieldop.getResults().size() == 1 &&
2408 "terminator must be omp.yield op and it must have exactly one "
2410 return moduleTranslation.
lookupValue(yieldop.getResults()[0]);
2415 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2416 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2417 ompBuilder->createAtomicUpdate(ompLoc, allocaIP, llvmAtomicX, llvmExpr,
2418 atomicOrdering, binop, updateFn,
2424 builder.restoreIP(*afterIP);
2428 static LogicalResult
2430 llvm::IRBuilderBase &builder,
2437 bool isXBinopExpr =
false, isPostfixUpdate =
false;
2438 llvm::AtomicRMWInst::BinOp binop = llvm::AtomicRMWInst::BinOp::BAD_BINOP;
2440 omp::AtomicUpdateOp atomicUpdateOp = atomicCaptureOp.getAtomicUpdateOp();
2441 omp::AtomicWriteOp atomicWriteOp = atomicCaptureOp.getAtomicWriteOp();
2443 assert((atomicUpdateOp || atomicWriteOp) &&
2444 "internal op must be an atomic.update or atomic.write op");
2446 if (atomicWriteOp) {
2447 isPostfixUpdate =
true;
2448 mlirExpr = atomicWriteOp.getExpr();
2450 isPostfixUpdate = atomicCaptureOp.getSecondOp() ==
2451 atomicCaptureOp.getAtomicUpdateOp().getOperation();
2452 auto &innerOpList = atomicUpdateOp.getRegion().front().getOperations();
2455 if (innerOpList.size() == 2) {
2458 atomicUpdateOp.getRegion().getArgument(0))) {
2459 return atomicUpdateOp.emitError(
2460 "no atomic update operation with region argument"
2461 " as operand found inside atomic.update region");
2465 innerOp.
getOperand(0) == atomicUpdateOp.getRegion().getArgument(0);
2468 binop = llvm::AtomicRMWInst::BinOp::BAD_BINOP;
2472 llvm::Value *llvmExpr = moduleTranslation.
lookupValue(mlirExpr);
2473 llvm::Value *llvmX =
2474 moduleTranslation.
lookupValue(atomicCaptureOp.getAtomicReadOp().getX());
2475 llvm::Value *llvmV =
2476 moduleTranslation.
lookupValue(atomicCaptureOp.getAtomicReadOp().getV());
2477 llvm::Type *llvmXElementType = moduleTranslation.
convertType(
2478 atomicCaptureOp.getAtomicReadOp().getElementType());
2479 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {llvmX, llvmXElementType,
2482 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicV = {llvmV, llvmXElementType,
2486 llvm::AtomicOrdering atomicOrdering =
2490 [&](llvm::Value *atomicx,
2493 return moduleTranslation.
lookupValue(atomicWriteOp.getExpr());
2494 Block &bb = *atomicUpdateOp.getRegion().
begin();
2495 moduleTranslation.
mapValue(*atomicUpdateOp.getRegion().args_begin(),
2497 moduleTranslation.
mapBlock(&bb, builder.GetInsertBlock());
2498 if (failed(moduleTranslation.
convertBlock(bb,
true, builder)))
2499 return llvm::make_error<PreviouslyReportedError>();
2501 omp::YieldOp yieldop = dyn_cast<omp::YieldOp>(bb.
getTerminator());
2502 assert(yieldop && yieldop.getResults().size() == 1 &&
2503 "terminator must be omp.yield op and it must have exactly one "
2505 return moduleTranslation.
lookupValue(yieldop.getResults()[0]);
2510 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2511 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2512 ompBuilder->createAtomicCapture(
2513 ompLoc, allocaIP, llvmAtomicX, llvmAtomicV, llvmExpr, atomicOrdering,
2514 binop, updateFn, atomicUpdateOp, isPostfixUpdate, isXBinopExpr);
2516 if (failed(
handleError(afterIP, *atomicCaptureOp)))
2519 builder.restoreIP(*afterIP);
2525 static LogicalResult
2528 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2529 auto threadprivateOp = cast<omp::ThreadprivateOp>(opInst);
2534 Value symAddr = threadprivateOp.getSymAddr();
2536 if (!isa<LLVM::AddressOfOp>(symOp))
2537 return opInst.
emitError(
"Addressing symbol not found");
2538 LLVM::AddressOfOp addressOfOp = dyn_cast<LLVM::AddressOfOp>(symOp);
2540 LLVM::GlobalOp global =
2541 addressOfOp.getGlobal(moduleTranslation.
symbolTable());
2542 llvm::GlobalValue *globalValue = moduleTranslation.
lookupGlobal(global);
2543 llvm::Type *type = globalValue->getValueType();
2544 llvm::TypeSize typeSize =
2545 builder.GetInsertBlock()->getModule()->getDataLayout().getTypeStoreSize(
2547 llvm::ConstantInt *size = builder.getInt64(typeSize.getFixedValue());
2548 llvm::StringRef suffix = llvm::StringRef(
".cache", 6);
2549 std::string cacheName = (Twine(global.getSymName()).concat(suffix)).str();
2550 llvm::Value *callInst =
2552 ompLoc, globalValue, size, cacheName);
2557 static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind
2559 switch (deviceClause) {
2560 case mlir::omp::DeclareTargetDeviceType::host:
2561 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseHost;
2563 case mlir::omp::DeclareTargetDeviceType::nohost:
2564 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNoHost;
2566 case mlir::omp::DeclareTargetDeviceType::any:
2567 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny;
2570 llvm_unreachable(
"unhandled device clause");
2573 static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind
2575 mlir::omp::DeclareTargetCaptureClause captureClause) {
2576 switch (captureClause) {
2577 case mlir::omp::DeclareTargetCaptureClause::to:
2578 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo;
2579 case mlir::omp::DeclareTargetCaptureClause::link:
2580 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink;
2581 case mlir::omp::DeclareTargetCaptureClause::enter:
2582 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter;
2584 llvm_unreachable(
"unhandled capture clause");
2589 llvm::OpenMPIRBuilder &ompBuilder) {
2591 llvm::raw_svector_ostream os(suffix);
2593 auto loc = globalOp->getLoc()->findInstanceOf<FileLineColLoc>();
2594 auto fileInfoCallBack = [&loc]() {
2595 return std::pair<std::string, uint64_t>(
2596 llvm::StringRef(loc.getFilename()), loc.getLine());
2600 "_%x", ompBuilder.getTargetEntryUniqueInfo(fileInfoCallBack).FileID);
2602 os <<
"_decl_tgt_ref_ptr";
2608 if (
auto addressOfOp =
2609 llvm::dyn_cast_if_present<LLVM::AddressOfOp>(value.
getDefiningOp())) {
2610 auto modOp = addressOfOp->getParentOfType<mlir::ModuleOp>();
2611 Operation *gOp = modOp.lookupSymbol(addressOfOp.getGlobalName());
2612 if (
auto declareTargetGlobal =
2613 llvm::dyn_cast<mlir::omp::DeclareTargetInterface>(gOp))
2614 if (declareTargetGlobal.getDeclareTargetCaptureClause() ==
2615 mlir::omp::DeclareTargetCaptureClause::link)
2624 static llvm::Value *
2631 if (
auto addressOfOp =
2632 llvm::dyn_cast_if_present<LLVM::AddressOfOp>(value.
getDefiningOp())) {
2633 if (
auto gOp = llvm::dyn_cast_or_null<LLVM::GlobalOp>(
2634 addressOfOp->getParentOfType<mlir::ModuleOp>().lookupSymbol(
2635 addressOfOp.getGlobalName()))) {
2637 if (
auto declareTargetGlobal =
2638 llvm::dyn_cast<mlir::omp::DeclareTargetInterface>(
2639 gOp.getOperation())) {
2643 if ((declareTargetGlobal.getDeclareTargetCaptureClause() ==
2644 mlir::omp::DeclareTargetCaptureClause::link) ||
2645 (declareTargetGlobal.getDeclareTargetCaptureClause() ==
2646 mlir::omp::DeclareTargetCaptureClause::to &&
2647 ompBuilder->Config.hasRequiresUnifiedSharedMemory())) {
2651 if (gOp.getSymName().contains(suffix))
2656 (gOp.getSymName().str() + suffix.str()).str());
2672 struct MapInfoData : llvm::OpenMPIRBuilder::MapInfosTy {
2684 void append(MapInfoData &CurInfo) {
2685 IsDeclareTarget.append(CurInfo.IsDeclareTarget.begin(),
2686 CurInfo.IsDeclareTarget.end());
2687 MapClause.append(CurInfo.MapClause.begin(), CurInfo.MapClause.end());
2688 OriginalValue.append(CurInfo.OriginalValue.begin(),
2689 CurInfo.OriginalValue.end());
2690 BaseType.append(CurInfo.BaseType.begin(), CurInfo.BaseType.end());
2691 llvm::OpenMPIRBuilder::MapInfosTy::append(CurInfo);
2697 if (
auto nestedArrTy = llvm::dyn_cast_if_present<LLVM::LLVMArrayType>(
2698 arrTy.getElementType()))
2714 Operation *clauseOp, llvm::Value *basePointer,
2715 llvm::Type *baseType, llvm::IRBuilderBase &builder,
2717 if (
auto memberClause =
2718 mlir::dyn_cast_if_present<mlir::omp::MapInfoOp>(clauseOp)) {
2723 if (!memberClause.getBounds().empty()) {
2724 llvm::Value *elementCount = builder.getInt64(1);
2725 for (
auto bounds : memberClause.getBounds()) {
2726 if (
auto boundOp = mlir::dyn_cast_if_present<mlir::omp::MapBoundsOp>(
2727 bounds.getDefiningOp())) {
2732 elementCount = builder.CreateMul(
2736 moduleTranslation.
lookupValue(boundOp.getUpperBound()),
2737 moduleTranslation.
lookupValue(boundOp.getLowerBound())),
2738 builder.getInt64(1)));
2745 if (
auto arrTy = llvm::dyn_cast_if_present<LLVM::LLVMArrayType>(type))
2753 return builder.CreateMul(elementCount,
2754 builder.getInt64(underlyingTypeSzInBits / 8));
2764 llvm::IRBuilderBase &builder,
const ArrayRef<Value> &useDevPtrOperands = {},
2766 auto checkIsAMember = [](
const auto &mapVars,
auto mapOp) {
2774 for (
Value mapValue : mapVars) {
2775 auto map = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
2776 for (
auto member : map.getMembers())
2777 if (member == mapOp)
2784 for (
Value mapValue : mapVars) {
2785 auto mapOp = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
2787 mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtr() : mapOp.getVarPtr();
2788 mapData.OriginalValue.push_back(moduleTranslation.
lookupValue(offloadPtr));
2789 mapData.Pointers.push_back(mapData.OriginalValue.back());
2791 if (llvm::Value *refPtr =
2793 moduleTranslation)) {
2794 mapData.IsDeclareTarget.push_back(
true);
2795 mapData.BasePointers.push_back(refPtr);
2797 mapData.IsDeclareTarget.push_back(
false);
2798 mapData.BasePointers.push_back(mapData.OriginalValue.back());
2801 mapData.BaseType.push_back(
2802 moduleTranslation.
convertType(mapOp.getVarType()));
2803 mapData.Sizes.push_back(
2804 getSizeInBytes(dl, mapOp.getVarType(), mapOp, mapData.Pointers.back(),
2805 mapData.BaseType.back(), builder, moduleTranslation));
2806 mapData.MapClause.push_back(mapOp.getOperation());
2807 mapData.Types.push_back(
2808 llvm::omp::OpenMPOffloadMappingFlags(mapOp.getMapType().value()));
2812 mapData.IsAMapping.push_back(
true);
2813 mapData.IsAMember.push_back(checkIsAMember(mapVars, mapOp));
2816 auto findMapInfo = [&mapData](llvm::Value *val,
2817 llvm::OpenMPIRBuilder::DeviceInfoTy devInfoTy) {
2820 for (llvm::Value *basePtr : mapData.OriginalValue) {
2821 if (basePtr == val && mapData.IsAMapping[index]) {
2823 mapData.Types[index] |=
2824 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
2825 mapData.DevicePointers[index] = devInfoTy;
2834 llvm::OpenMPIRBuilder::DeviceInfoTy devInfoTy) {
2835 for (
Value mapValue : useDevOperands) {
2836 auto mapOp = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
2838 mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtr() : mapOp.getVarPtr();
2839 llvm::Value *origValue = moduleTranslation.
lookupValue(offloadPtr);
2842 if (!findMapInfo(origValue, devInfoTy)) {
2843 mapData.OriginalValue.push_back(origValue);
2844 mapData.Pointers.push_back(mapData.OriginalValue.back());
2845 mapData.IsDeclareTarget.push_back(
false);
2846 mapData.BasePointers.push_back(mapData.OriginalValue.back());
2847 mapData.BaseType.push_back(
2848 moduleTranslation.
convertType(mapOp.getVarType()));
2849 mapData.Sizes.push_back(builder.getInt64(0));
2850 mapData.MapClause.push_back(mapOp.getOperation());
2851 mapData.Types.push_back(
2852 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM);
2855 mapData.DevicePointers.push_back(devInfoTy);
2856 mapData.IsAMapping.push_back(
false);
2857 mapData.IsAMember.push_back(checkIsAMember(useDevOperands, mapOp));
2862 addDevInfos(useDevAddrOperands, llvm::OpenMPIRBuilder::DeviceInfoTy::Address);
2863 addDevInfos(useDevPtrOperands, llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer);
2867 auto *res = llvm::find(mapData.MapClause, memberOp);
2868 assert(res != mapData.MapClause.end() &&
2869 "MapInfoOp for member not found in MapData, cannot return index");
2870 return std::distance(mapData.MapClause.begin(), res);
2875 ArrayAttr indexAttr = mapInfo.getMembersIndexAttr();
2877 if (indexAttr.size() == 1)
2878 return cast<omp::MapInfoOp>(mapInfo.getMembers()[0].getDefiningOp());
2881 std::iota(indices.begin(), indices.end(), 0);
2883 llvm::sort(indices.begin(), indices.end(),
2884 [&](
const size_t a,
const size_t b) {
2885 auto memberIndicesA = cast<ArrayAttr>(indexAttr[a]);
2886 auto memberIndicesB = cast<ArrayAttr>(indexAttr[b]);
2887 for (const auto it : llvm::zip(memberIndicesA, memberIndicesB)) {
2888 int64_t aIndex = cast<IntegerAttr>(std::get<0>(it)).getInt();
2889 int64_t bIndex = cast<IntegerAttr>(std::get<1>(it)).getInt();
2891 if (aIndex == bIndex)
2894 if (aIndex < bIndex)
2897 if (aIndex > bIndex)
2904 return memberIndicesA.size() < memberIndicesB.size();
2907 return llvm::cast<omp::MapInfoOp>(
2908 mapInfo.getMembers()[indices.front()].getDefiningOp());
2930 std::vector<llvm::Value *>
2932 llvm::IRBuilderBase &builder,
bool isArrayTy,
2934 std::vector<llvm::Value *> idx;
2945 idx.push_back(builder.getInt64(0));
2946 for (
int i = bounds.size() - 1; i >= 0; --i) {
2947 if (
auto boundOp = dyn_cast_if_present<omp::MapBoundsOp>(
2948 bounds[i].getDefiningOp())) {
2949 idx.push_back(moduleTranslation.
lookupValue(boundOp.getLowerBound()));
2971 std::vector<llvm::Value *> dimensionIndexSizeOffset{builder.getInt64(1)};
2972 for (
size_t i = 1; i < bounds.size(); ++i) {
2973 if (
auto boundOp = dyn_cast_if_present<omp::MapBoundsOp>(
2974 bounds[i].getDefiningOp())) {
2975 dimensionIndexSizeOffset.push_back(builder.CreateMul(
2976 moduleTranslation.
lookupValue(boundOp.getExtent()),
2977 dimensionIndexSizeOffset[i - 1]));
2985 for (
int i = bounds.size() - 1; i >= 0; --i) {
2986 if (
auto boundOp = dyn_cast_if_present<omp::MapBoundsOp>(
2987 bounds[i].getDefiningOp())) {
2989 idx.emplace_back(builder.CreateMul(
2990 moduleTranslation.
lookupValue(boundOp.getLowerBound()),
2991 dimensionIndexSizeOffset[i]));
2993 idx.back() = builder.CreateAdd(
2994 idx.back(), builder.CreateMul(moduleTranslation.
lookupValue(
2995 boundOp.getLowerBound()),
2996 dimensionIndexSizeOffset[i]));
3021 llvm::OpenMPIRBuilder &ompBuilder,
DataLayout &dl,
3022 llvm::OpenMPIRBuilder::MapInfosTy &combinedInfo, MapInfoData &mapData,
3023 uint64_t mapDataIndex,
bool isTargetParams) {
3025 combinedInfo.Types.emplace_back(
3027 ? llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM
3028 : llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE);
3029 combinedInfo.DevicePointers.emplace_back(
3030 mapData.DevicePointers[mapDataIndex]);
3032 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder));
3033 combinedInfo.BasePointers.emplace_back(mapData.BasePointers[mapDataIndex]);
3043 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
3045 llvm::Value *lowAddr, *highAddr;
3046 if (!parentClause.getPartialMap()) {
3047 lowAddr = builder.CreatePointerCast(mapData.Pointers[mapDataIndex],
3048 builder.getPtrTy());
3049 highAddr = builder.CreatePointerCast(
3050 builder.CreateConstGEP1_32(mapData.BaseType[mapDataIndex],
3051 mapData.Pointers[mapDataIndex], 1),
3052 builder.getPtrTy());
3053 combinedInfo.Pointers.emplace_back(mapData.Pointers[mapDataIndex]);
3055 auto mapOp = dyn_cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
3058 lowAddr = builder.CreatePointerCast(mapData.Pointers[firstMemberIdx],
3059 builder.getPtrTy());
3062 highAddr = builder.CreatePointerCast(
3063 builder.CreateGEP(mapData.BaseType[lastMemberIdx],
3064 mapData.Pointers[lastMemberIdx], builder.getInt64(1)),
3065 builder.getPtrTy());
3066 combinedInfo.Pointers.emplace_back(mapData.Pointers[firstMemberIdx]);
3069 llvm::Value *size = builder.CreateIntCast(
3070 builder.CreatePtrDiff(builder.getInt8Ty(), highAddr, lowAddr),
3071 builder.getInt64Ty(),
3073 combinedInfo.Sizes.push_back(size);
3075 llvm::omp::OpenMPOffloadMappingFlags memberOfFlag =
3076 ompBuilder.getMemberOfFlag(combinedInfo.BasePointers.size() - 1);
3084 if (!parentClause.getPartialMap()) {
3089 llvm::omp::OpenMPOffloadMappingFlags mapFlag = mapData.Types[mapDataIndex];
3090 ompBuilder.setCorrectMemberOfFlag(mapFlag, memberOfFlag);
3091 combinedInfo.Types.emplace_back(mapFlag);
3092 combinedInfo.DevicePointers.emplace_back(
3095 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder));
3096 combinedInfo.BasePointers.emplace_back(mapData.BasePointers[mapDataIndex]);
3097 combinedInfo.Pointers.emplace_back(mapData.Pointers[mapDataIndex]);
3098 combinedInfo.Sizes.emplace_back(mapData.Sizes[mapDataIndex]);
3100 return memberOfFlag;
3112 if (mapOp.getVarPtrPtr())
3127 llvm::OpenMPIRBuilder &ompBuilder,
DataLayout &dl,
3128 llvm::OpenMPIRBuilder::MapInfosTy &combinedInfo, MapInfoData &mapData,
3129 uint64_t mapDataIndex, llvm::omp::OpenMPOffloadMappingFlags memberOfFlag) {
3132 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
3134 for (
auto mappedMembers : parentClause.getMembers()) {
3136 llvm::cast<omp::MapInfoOp>(mappedMembers.getDefiningOp());
3139 assert(memberDataIdx >= 0 &&
"could not find mapped member of structure");
3149 auto mapFlag = llvm::omp::OpenMPOffloadMappingFlags(
3150 memberClause.getMapType().value());
3151 mapFlag &= ~
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
3152 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
3153 ompBuilder.setCorrectMemberOfFlag(mapFlag, memberOfFlag);
3154 combinedInfo.Types.emplace_back(mapFlag);
3155 combinedInfo.DevicePointers.emplace_back(
3157 combinedInfo.Names.emplace_back(
3159 combinedInfo.BasePointers.emplace_back(
3160 mapData.BasePointers[mapDataIndex]);
3161 combinedInfo.Pointers.emplace_back(mapData.BasePointers[memberDataIdx]);
3162 combinedInfo.Sizes.emplace_back(builder.getInt64(
3163 moduleTranslation.
getLLVMModule()->getDataLayout().getPointerSize()));
3169 llvm::omp::OpenMPOffloadMappingFlags(memberClause.getMapType().value());
3170 mapFlag &= ~
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
3171 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
3172 ompBuilder.setCorrectMemberOfFlag(mapFlag, memberOfFlag);
3174 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
3176 combinedInfo.Types.emplace_back(mapFlag);
3177 combinedInfo.DevicePointers.emplace_back(
3178 mapData.DevicePointers[memberDataIdx]);
3179 combinedInfo.Names.emplace_back(
3181 uint64_t basePointerIndex =
3183 combinedInfo.BasePointers.emplace_back(
3184 mapData.BasePointers[basePointerIndex]);
3185 combinedInfo.Pointers.emplace_back(mapData.Pointers[memberDataIdx]);
3186 combinedInfo.Sizes.emplace_back(mapData.Sizes[memberDataIdx]);
3192 llvm::OpenMPIRBuilder::MapInfosTy &combinedInfo,
3193 bool isTargetParams,
int mapDataParentIdx = -1) {
3197 auto mapFlag = mapData.Types[mapDataIdx];
3198 auto mapInfoOp = llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIdx]);
3202 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
3204 if (isTargetParams && !mapData.IsDeclareTarget[mapDataIdx])
3205 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
3207 if (mapInfoOp.getMapCaptureType().value() ==
3208 omp::VariableCaptureKind::ByCopy &&
3210 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL;
3215 if (mapDataParentIdx >= 0)
3216 combinedInfo.BasePointers.emplace_back(
3217 mapData.BasePointers[mapDataParentIdx]);
3219 combinedInfo.BasePointers.emplace_back(mapData.BasePointers[mapDataIdx]);
3221 combinedInfo.Pointers.emplace_back(mapData.Pointers[mapDataIdx]);
3222 combinedInfo.DevicePointers.emplace_back(mapData.DevicePointers[mapDataIdx]);
3223 combinedInfo.Names.emplace_back(mapData.Names[mapDataIdx]);
3224 combinedInfo.Types.emplace_back(mapFlag);
3225 combinedInfo.Sizes.emplace_back(mapData.Sizes[mapDataIdx]);
3230 llvm::OpenMPIRBuilder &ompBuilder,
DataLayout &dl,
3231 llvm::OpenMPIRBuilder::MapInfosTy &combinedInfo, MapInfoData &mapData,
3232 uint64_t mapDataIndex,
bool isTargetParams) {
3234 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
3239 if (parentClause.getMembers().size() == 1 && parentClause.getPartialMap()) {
3240 auto memberClause = llvm::cast<omp::MapInfoOp>(
3241 parentClause.getMembers()[0].getDefiningOp());
3258 llvm::omp::OpenMPOffloadMappingFlags memberOfParentFlag =
3260 combinedInfo, mapData, mapDataIndex, isTargetParams);
3262 combinedInfo, mapData, mapDataIndex,
3263 memberOfParentFlag);
3273 llvm::IRBuilderBase &builder) {
3274 for (
size_t i = 0; i < mapData.MapClause.size(); ++i) {
3276 if (!mapData.IsDeclareTarget[i]) {
3277 auto mapOp = cast<omp::MapInfoOp>(mapData.MapClause[i]);
3278 omp::VariableCaptureKind captureKind =
3279 mapOp.getMapCaptureType().value_or(omp::VariableCaptureKind::ByRef);
3289 switch (captureKind) {
3290 case omp::VariableCaptureKind::ByRef: {
3291 llvm::Value *newV = mapData.Pointers[i];
3293 moduleTranslation, builder, mapData.BaseType[i]->isArrayTy(),
3296 newV = builder.CreateLoad(builder.getPtrTy(), newV);
3298 if (!offsetIdx.empty())
3299 newV = builder.CreateInBoundsGEP(mapData.BaseType[i], newV, offsetIdx,
3301 mapData.Pointers[i] = newV;
3303 case omp::VariableCaptureKind::ByCopy: {
3304 llvm::Type *type = mapData.BaseType[i];
3306 if (mapData.Pointers[i]->getType()->isPointerTy())
3307 newV = builder.CreateLoad(type, mapData.Pointers[i]);
3309 newV = mapData.Pointers[i];
3312 auto curInsert = builder.saveIP();
3314 auto *memTempAlloc =
3315 builder.CreateAlloca(builder.getPtrTy(),
nullptr,
".casted");
3316 builder.restoreIP(curInsert);
3318 builder.CreateStore(newV, memTempAlloc);
3319 newV = builder.CreateLoad(builder.getPtrTy(), memTempAlloc);
3322 mapData.Pointers[i] = newV;
3323 mapData.BasePointers[i] = newV;
3325 case omp::VariableCaptureKind::This:
3326 case omp::VariableCaptureKind::VLAType:
3327 mapData.MapClause[i]->emitOpError(
"Unhandled capture kind");
3338 llvm::OpenMPIRBuilder::MapInfosTy &combinedInfo,
3339 MapInfoData &mapData,
bool isTargetParams =
false) {
3361 for (
size_t i = 0; i < mapData.MapClause.size(); ++i) {
3364 if (mapData.IsAMember[i])
3367 auto mapInfoOp = dyn_cast<omp::MapInfoOp>(mapData.MapClause[i]);
3368 if (!mapInfoOp.getMembers().empty()) {
3370 combinedInfo, mapData, i, isTargetParams);
3378 static LogicalResult
3381 llvm::Value *ifCond =
nullptr;
3382 int64_t deviceID = llvm::omp::OMP_DEVICEID_UNDEF;
3386 llvm::omp::RuntimeFunction RTLFn;
3390 llvm::OpenMPIRBuilder::TargetDataInfo info(
true,
3393 LogicalResult result =
3395 .Case([&](omp::TargetDataOp dataOp) {
3399 if (
auto ifVar = dataOp.getIfExpr())
3402 if (
auto devId = dataOp.getDevice())
3404 dyn_cast<LLVM::ConstantOp>(devId.getDefiningOp()))
3405 if (
auto intAttr = dyn_cast<IntegerAttr>(constOp.getValue()))
3406 deviceID = intAttr.getInt();
3408 mapVars = dataOp.getMapVars();
3409 useDevicePtrVars = dataOp.getUseDevicePtrVars();
3410 useDeviceAddrVars = dataOp.getUseDeviceAddrVars();
3413 .Case([&](omp::TargetEnterDataOp enterDataOp) -> LogicalResult {
3417 if (
auto ifVar = enterDataOp.getIfExpr())
3420 if (
auto devId = enterDataOp.getDevice())
3422 dyn_cast<LLVM::ConstantOp>(devId.getDefiningOp()))
3423 if (
auto intAttr = dyn_cast<IntegerAttr>(constOp.getValue()))
3424 deviceID = intAttr.getInt();
3426 enterDataOp.getNowait()
3427 ? llvm::omp::OMPRTL___tgt_target_data_begin_nowait_mapper
3428 : llvm::omp::OMPRTL___tgt_target_data_begin_mapper;
3429 mapVars = enterDataOp.getMapVars();
3430 info.HasNoWait = enterDataOp.getNowait();
3433 .Case([&](omp::TargetExitDataOp exitDataOp) -> LogicalResult {
3437 if (
auto ifVar = exitDataOp.getIfExpr())
3440 if (
auto devId = exitDataOp.getDevice())
3442 dyn_cast<LLVM::ConstantOp>(devId.getDefiningOp()))
3443 if (
auto intAttr = dyn_cast<IntegerAttr>(constOp.getValue()))
3444 deviceID = intAttr.getInt();
3446 RTLFn = exitDataOp.getNowait()
3447 ? llvm::omp::OMPRTL___tgt_target_data_end_nowait_mapper
3448 : llvm::omp::OMPRTL___tgt_target_data_end_mapper;
3449 mapVars = exitDataOp.getMapVars();
3450 info.HasNoWait = exitDataOp.getNowait();
3453 .Case([&](omp::TargetUpdateOp updateDataOp) -> LogicalResult {
3457 if (
auto ifVar = updateDataOp.getIfExpr())
3460 if (
auto devId = updateDataOp.getDevice())
3462 dyn_cast<LLVM::ConstantOp>(devId.getDefiningOp()))
3463 if (
auto intAttr = dyn_cast<IntegerAttr>(constOp.getValue()))
3464 deviceID = intAttr.getInt();
3467 updateDataOp.getNowait()
3468 ? llvm::omp::OMPRTL___tgt_target_data_update_nowait_mapper
3469 : llvm::omp::OMPRTL___tgt_target_data_update_mapper;
3470 mapVars = updateDataOp.getMapVars();
3471 info.HasNoWait = updateDataOp.getNowait();
3475 llvm_unreachable(
"unexpected operation");
3482 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
3484 MapInfoData mapData;
3486 builder, useDevicePtrVars, useDeviceAddrVars);
3489 llvm::OpenMPIRBuilder::MapInfosTy combinedInfo;
3491 [&](InsertPointTy codeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & {
3492 builder.restoreIP(codeGenIP);
3493 genMapInfos(builder, moduleTranslation, DL, combinedInfo, mapData);
3494 return combinedInfo;
3500 [&moduleTranslation](
3501 llvm::OpenMPIRBuilder::DeviceInfoTy type,
3505 for (
auto [arg, useDevVar] :
3506 llvm::zip_equal(blockArgs, useDeviceVars)) {
3508 auto getMapBasePtr = [](omp::MapInfoOp mapInfoOp) {
3509 return mapInfoOp.getVarPtrPtr() ? mapInfoOp.getVarPtrPtr()
3510 : mapInfoOp.getVarPtr();
3513 auto useDevMap = cast<omp::MapInfoOp>(useDevVar.getDefiningOp());
3514 for (
auto [mapClause, devicePointer, basePointer] : llvm::zip_equal(
3515 mapInfoData.MapClause, mapInfoData.DevicePointers,
3516 mapInfoData.BasePointers)) {
3517 auto mapOp = cast<omp::MapInfoOp>(mapClause);
3518 if (getMapBasePtr(mapOp) != getMapBasePtr(useDevMap) ||
3519 devicePointer != type)
3522 if (llvm::Value *devPtrInfoMap =
3523 mapper ? mapper(basePointer) : basePointer) {
3524 moduleTranslation.
mapValue(arg, devPtrInfoMap);
3531 using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy;
3532 auto bodyGenCB = [&](InsertPointTy codeGenIP, BodyGenTy bodyGenType)
3533 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
3534 assert(isa<omp::TargetDataOp>(op) &&
3535 "BodyGen requested for non TargetDataOp");
3536 auto blockArgIface = cast<omp::BlockArgOpenMPOpInterface>(op);
3537 Region ®ion = cast<omp::TargetDataOp>(op).getRegion();
3538 switch (bodyGenType) {
3539 case BodyGenTy::Priv:
3541 if (!info.DevicePtrInfoMap.empty()) {
3542 builder.restoreIP(codeGenIP);
3544 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Address,
3545 blockArgIface.getUseDeviceAddrBlockArgs(),
3546 useDeviceAddrVars, mapData,
3547 [&](llvm::Value *basePointer) -> llvm::Value * {
3548 if (!info.DevicePtrInfoMap[basePointer].second)
3550 return builder.CreateLoad(
3552 info.DevicePtrInfoMap[basePointer].second);
3554 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer,
3555 blockArgIface.getUseDevicePtrBlockArgs(), useDevicePtrVars,
3556 mapData, [&](llvm::Value *basePointer) {
3557 return info.DevicePtrInfoMap[basePointer].second;
3561 moduleTranslation)))
3562 return llvm::make_error<PreviouslyReportedError>();
3565 case BodyGenTy::DupNoPriv:
3567 case BodyGenTy::NoPriv:
3569 if (info.DevicePtrInfoMap.empty()) {
3570 builder.restoreIP(codeGenIP);
3573 if (ompBuilder->Config.IsTargetDevice.value_or(
false)) {
3574 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Address,
3575 blockArgIface.getUseDeviceAddrBlockArgs(),
3576 useDeviceAddrVars, mapData);
3577 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer,
3578 blockArgIface.getUseDevicePtrBlockArgs(),
3579 useDevicePtrVars, mapData);
3583 moduleTranslation)))
3584 return llvm::make_error<PreviouslyReportedError>();
3588 return builder.saveIP();
3591 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
3592 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
3594 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP = [&]() {
3595 if (isa<omp::TargetDataOp>(op))
3596 return ompBuilder->createTargetData(
3597 ompLoc, allocaIP, builder.saveIP(), builder.getInt64(deviceID),
3598 ifCond, info, genMapInfoCB,
nullptr, bodyGenCB);
3599 return ompBuilder->createTargetData(ompLoc, allocaIP, builder.saveIP(),
3600 builder.getInt64(deviceID), ifCond,
3601 info, genMapInfoCB, &RTLFn);
3607 builder.restoreIP(*afterIP);
3616 if (!cast<mlir::ModuleOp>(op))
3621 ompBuilder->M.addModuleFlag(llvm::Module::Max,
"openmp-device",
3622 attribute.getOpenmpDeviceVersion());
3624 if (attribute.getNoGpuLib())
3627 ompBuilder->createGlobalFlag(
3628 attribute.getDebugKind() ,
3629 "__omp_rtl_debug_kind");
3630 ompBuilder->createGlobalFlag(
3632 .getAssumeTeamsOversubscription()
3634 "__omp_rtl_assume_teams_oversubscription");
3635 ompBuilder->createGlobalFlag(
3637 .getAssumeThreadsOversubscription()
3639 "__omp_rtl_assume_threads_oversubscription");
3640 ompBuilder->createGlobalFlag(
3641 attribute.getAssumeNoThreadState() ,
3642 "__omp_rtl_assume_no_thread_state");
3643 ompBuilder->createGlobalFlag(
3645 .getAssumeNoNestedParallelism()
3647 "__omp_rtl_assume_no_nested_parallelism");
3652 omp::TargetOp targetOp,
3653 llvm::StringRef parentName =
"") {
3654 auto fileLoc = targetOp.getLoc()->findInstanceOf<FileLineColLoc>();
3656 assert(fileLoc &&
"No file found from location");
3657 StringRef fileName = fileLoc.getFilename().getValue();
3659 llvm::sys::fs::UniqueID id;
3660 if (
auto ec = llvm::sys::fs::getUniqueID(fileName,
id)) {
3661 targetOp.emitError(
"Unable to get unique ID for file");
3665 uint64_t line = fileLoc.getLine();
3666 targetInfo = llvm::TargetRegionEntryInfo(parentName,
id.getDevice(),
3667 id.getFile(), line);
3674 llvm::IRBuilderBase &builder, llvm::Function *func) {
3675 for (
size_t i = 0; i < mapData.MapClause.size(); ++i) {
3688 if (mapData.IsDeclareTarget[i]) {
3695 if (
auto *constant = dyn_cast<llvm::Constant>(mapData.OriginalValue[i]))
3696 convertUsersOfConstantsToInstructions(constant, func,
false);
3703 for (llvm::User *user : mapData.OriginalValue[i]->users())
3704 userVec.push_back(user);
3706 for (llvm::User *user : userVec) {
3707 if (
auto *insn = dyn_cast<llvm::Instruction>(user)) {
3708 if (insn->getFunction() == func) {
3709 auto *load = builder.CreateLoad(mapData.BasePointers[i]->getType(),
3710 mapData.BasePointers[i]);
3711 load->moveBefore(insn);
3712 user->replaceUsesOfWith(mapData.OriginalValue[i], load);
3759 static llvm::IRBuilderBase::InsertPoint
3761 llvm::Value *input, llvm::Value *&retVal,
3762 llvm::IRBuilderBase &builder,
3763 llvm::OpenMPIRBuilder &ompBuilder,
3765 llvm::IRBuilderBase::InsertPoint allocaIP,
3766 llvm::IRBuilderBase::InsertPoint codeGenIP) {
3767 builder.restoreIP(allocaIP);
3769 omp::VariableCaptureKind capture = omp::VariableCaptureKind::ByRef;
3772 for (
size_t i = 0; i < mapData.MapClause.size(); ++i)
3773 if (mapData.OriginalValue[i] == input) {
3774 auto mapOp = cast<omp::MapInfoOp>(mapData.MapClause[i]);
3776 mapOp.getMapCaptureType().value_or(omp::VariableCaptureKind::ByRef);
3781 unsigned int allocaAS = ompBuilder.M.getDataLayout().getAllocaAddrSpace();
3782 unsigned int defaultAS =
3783 ompBuilder.M.getDataLayout().getProgramAddressSpace();
3786 llvm::Value *v = builder.CreateAlloca(arg.getType(), allocaAS);
3788 if (allocaAS != defaultAS && arg.getType()->isPointerTy())
3789 v = builder.CreateAddrSpaceCast(v, builder.getPtrTy(defaultAS));
3791 builder.CreateStore(&arg, v);
3793 builder.restoreIP(codeGenIP);
3796 case omp::VariableCaptureKind::ByCopy: {
3800 case omp::VariableCaptureKind::ByRef: {
3801 retVal = builder.CreateAlignedLoad(
3803 ompBuilder.M.getDataLayout().getPrefTypeAlign(v->getType()));
3806 case omp::VariableCaptureKind::This:
3807 case omp::VariableCaptureKind::VLAType:
3810 assert(
false &&
"Currently unsupported capture kind");
3814 return builder.saveIP();
3817 static LogicalResult
3820 auto targetOp = cast<omp::TargetOp>(opInst);
3825 bool isTargetDevice = ompBuilder->Config.isTargetDevice();
3827 auto &targetRegion = targetOp.getRegion();
3831 cast<omp::BlockArgOpenMPOpInterface>(opInst).getMapBlockArgs();
3832 llvm::Function *llvmOutlinedFn =
nullptr;
3836 bool isOffloadEntry =
3837 isTargetDevice || !ompBuilder->Config.TargetTriples.empty();
3839 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
3840 auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP)
3841 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
3844 llvm::Function *llvmParentFn =
3846 llvmOutlinedFn = codeGenIP.getBlock()->getParent();
3847 assert(llvmParentFn && llvmOutlinedFn &&
3848 "Both parent and outlined functions must exist at this point");
3850 if (
auto attr = llvmParentFn->getFnAttribute(
"target-cpu");
3851 attr.isStringAttribute())
3852 llvmOutlinedFn->addFnAttr(attr);
3854 if (
auto attr = llvmParentFn->getFnAttribute(
"target-features");
3855 attr.isStringAttribute())
3856 llvmOutlinedFn->addFnAttr(attr);
3858 builder.restoreIP(codeGenIP);
3859 for (
auto [arg, mapOp] : llvm::zip_equal(mapBlockArgs, mapVars)) {
3860 auto mapInfoOp = cast<omp::MapInfoOp>(mapOp.getDefiningOp());
3861 llvm::Value *mapOpValue =
3862 moduleTranslation.
lookupValue(mapInfoOp.getVarPtr());
3863 moduleTranslation.
mapValue(arg, mapOpValue);
3868 if (!targetOp.getPrivateVars().empty()) {
3869 builder.restoreIP(allocaIP);
3872 std::optional<ArrayAttr> privateSyms = targetOp.getPrivateSyms();
3874 cast<omp::BlockArgOpenMPOpInterface>(opInst).getPrivateBlockArgs();
3876 for (
auto [privVar, privatizerNameAttr, privBlockArg] :
3877 llvm::zip_equal(privateVars, *privateSyms, privateBlockArgs)) {
3879 SymbolRefAttr privSym = cast<SymbolRefAttr>(privatizerNameAttr);
3880 omp::PrivateClauseOp privatizer =
findPrivatizer(&opInst, privSym);
3881 assert(privatizer.getDataSharingType() !=
3882 omp::DataSharingClauseType::FirstPrivate &&
3883 privatizer.getDeallocRegion().empty() &&
3884 "unsupported privatizer");
3885 moduleTranslation.
mapValue(privatizer.getAllocMoldArg(),
3887 Region &allocRegion = privatizer.getAllocRegion();
3890 allocRegion,
"omp.targetop.privatizer", builder,
3891 moduleTranslation, &yieldedValues))) {
3892 return llvm::createStringError(
3893 "failed to inline `alloc` region of `omp.private`");
3895 assert(yieldedValues.size() == 1);
3896 moduleTranslation.
mapValue(privBlockArg, yieldedValues.front());
3898 builder.restoreIP(builder.saveIP());
3903 targetRegion,
"omp.target", builder, moduleTranslation);
3905 return exitBlock.takeError();
3907 builder.SetInsertPoint(*exitBlock);
3908 return builder.saveIP();
3911 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
3912 StringRef parentName = parentFn.getName();
3914 llvm::TargetRegionEntryInfo entryInfo;
3919 int32_t defaultValTeams = -1;
3920 int32_t defaultValThreads = 0;
3922 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
3925 MapInfoData mapData;
3929 llvm::OpenMPIRBuilder::MapInfosTy combinedInfos;
3930 auto genMapInfoCB = [&](llvm::OpenMPIRBuilder::InsertPointTy codeGenIP)
3931 -> llvm::OpenMPIRBuilder::MapInfosTy & {
3932 builder.restoreIP(codeGenIP);
3933 genMapInfos(builder, moduleTranslation, dl, combinedInfos, mapData,
true);
3934 return combinedInfos;
3937 auto argAccessorCB = [&](llvm::Argument &arg, llvm::Value *input,
3938 llvm::Value *&retVal, InsertPointTy allocaIP,
3939 InsertPointTy codeGenIP)
3940 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
3946 if (!isTargetDevice) {
3947 retVal = cast<llvm::Value>(&arg);
3952 *ompBuilder, moduleTranslation,
3953 allocaIP, codeGenIP);
3957 for (
size_t i = 0; i < mapVars.size(); ++i) {
3964 if (!mapData.IsDeclareTarget[i] && !mapData.IsAMember[i])
3965 kernelInput.push_back(mapData.OriginalValue[i]);
3970 moduleTranslation, dds);
3972 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
3974 ompLoc, isOffloadEntry, allocaIP, builder.saveIP(), entryInfo,
3975 defaultValTeams, defaultValThreads, kernelInput, genMapInfoCB, bodyCB,
3976 argAccessorCB, dds, targetOp.getNowait());
3981 builder.restoreIP(*afterIP);
3992 static LogicalResult
4002 if (FunctionOpInterface funcOp = dyn_cast<FunctionOpInterface>(op)) {
4003 if (
auto offloadMod = dyn_cast<omp::OffloadModuleInterface>(
4005 if (!offloadMod.getIsTargetDevice())
4008 omp::DeclareTargetDeviceType declareType =
4009 attribute.getDeviceType().getValue();
4011 if (declareType == omp::DeclareTargetDeviceType::host) {
4012 llvm::Function *llvmFunc =
4014 llvmFunc->dropAllReferences();
4015 llvmFunc->eraseFromParent();
4021 if (LLVM::GlobalOp gOp = dyn_cast<LLVM::GlobalOp>(op)) {
4022 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
4023 if (
auto *gVal = llvmModule->getNamedValue(gOp.getSymName())) {
4025 bool isDeclaration = gOp.isDeclaration();
4026 bool isExternallyVisible =
4029 llvm::StringRef mangledName = gOp.getSymName();
4030 auto captureClause =
4036 std::vector<llvm::GlobalVariable *> generatedRefs;
4038 std::vector<llvm::Triple> targetTriple;
4039 auto targetTripleAttr = dyn_cast_or_null<mlir::StringAttr>(
4041 LLVM::LLVMDialect::getTargetTripleAttrName()));
4042 if (targetTripleAttr)
4043 targetTriple.emplace_back(targetTripleAttr.data());
4045 auto fileInfoCallBack = [&loc]() {
4046 std::string filename =
"";
4047 std::uint64_t lineNo = 0;
4050 filename = loc.getFilename().str();
4051 lineNo = loc.getLine();
4054 return std::pair<std::string, std::uint64_t>(llvm::StringRef(filename),
4058 ompBuilder->registerTargetGlobalVariable(
4059 captureClause, deviceClause, isDeclaration, isExternallyVisible,
4060 ompBuilder->getTargetEntryUniqueInfo(fileInfoCallBack), mangledName,
4061 generatedRefs,
false, targetTriple,
4063 gVal->getType(), gVal);
4065 if (ompBuilder->Config.isTargetDevice() &&
4066 (attribute.getCaptureClause().getValue() !=
4067 mlir::omp::DeclareTargetCaptureClause::to ||
4068 ompBuilder->Config.hasRequiresUnifiedSharedMemory())) {
4069 ompBuilder->getAddrOfDeclareTargetVar(
4070 captureClause, deviceClause, isDeclaration, isExternallyVisible,
4071 ompBuilder->getTargetEntryUniqueInfo(fileInfoCallBack), mangledName,
4072 generatedRefs,
false, targetTriple, gVal->getType(),
4090 if (
auto declareTargetIface =
4091 llvm::dyn_cast<mlir::omp::DeclareTargetInterface>(
4092 parentFn.getOperation()))
4093 if (declareTargetIface.isDeclareTarget() &&
4094 declareTargetIface.getDeclareTargetDeviceType() !=
4095 mlir::omp::DeclareTargetDeviceType::host)
4103 static LogicalResult
4110 .Case([&](omp::BarrierOp op) -> LogicalResult {
4114 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
4115 ompBuilder->createBarrier(builder.saveIP(),
4116 llvm::omp::OMPD_barrier);
4119 .Case([&](omp::TaskyieldOp op) {
4123 ompBuilder->createTaskyield(builder.saveIP());
4126 .Case([&](omp::FlushOp op) {
4138 ompBuilder->createFlush(builder.saveIP());
4141 .Case([&](omp::ParallelOp op) {
4144 .Case([&](omp::MaskedOp) {
4147 .Case([&](omp::MasterOp) {
4150 .Case([&](omp::CriticalOp) {
4153 .Case([&](omp::OrderedRegionOp) {
4156 .Case([&](omp::OrderedOp) {
4159 .Case([&](omp::WsloopOp) {
4162 .Case([&](omp::SimdOp) {
4165 .Case([&](omp::AtomicReadOp) {
4168 .Case([&](omp::AtomicWriteOp) {
4171 .Case([&](omp::AtomicUpdateOp op) {
4174 .Case([&](omp::AtomicCaptureOp op) {
4177 .Case([&](omp::SectionsOp) {
4180 .Case([&](omp::SingleOp op) {
4183 .Case([&](omp::TeamsOp op) {
4186 .Case([&](omp::TaskOp op) {
4189 .Case([&](omp::TaskgroupOp op) {
4192 .Case([&](omp::TaskwaitOp op) {
4195 .Case<omp::YieldOp, omp::TerminatorOp, omp::DeclareReductionOp,
4196 omp::CriticalDeclareOp>([](
auto op) {
4207 .Case([&](omp::ThreadprivateOp) {
4210 .Case<omp::TargetDataOp, omp::TargetEnterDataOp, omp::TargetExitDataOp,
4211 omp::TargetUpdateOp>([&](
auto op) {
4214 .Case([&](omp::TargetOp) {
4217 .Case<omp::MapInfoOp, omp::MapBoundsOp, omp::PrivateClauseOp>(
4229 static LogicalResult
4235 static LogicalResult
4238 if (isa<omp::TargetOp>(op))
4240 if (isa<omp::TargetDataOp>(op))
4244 if (isa<omp::TargetOp>(oper)) {
4246 return WalkResult::interrupt();
4247 return WalkResult::skip();
4249 if (isa<omp::TargetDataOp>(oper)) {
4251 return WalkResult::interrupt();
4252 return WalkResult::skip();
4254 return WalkResult::advance();
4255 }).wasInterrupted();
4256 return failure(interrupted);
4263 class OpenMPDialectLLVMIRTranslationInterface
4284 LogicalResult OpenMPDialectLLVMIRTranslationInterface::amendOperation(
4290 .Case(
"omp.is_target_device",
4292 if (
auto deviceAttr = dyn_cast<BoolAttr>(attr)) {
4293 llvm::OpenMPIRBuilderConfig &config =
4295 config.setIsTargetDevice(deviceAttr.getValue());
4302 if (
auto gpuAttr = dyn_cast<BoolAttr>(attr)) {
4303 llvm::OpenMPIRBuilderConfig &config =
4305 config.setIsGPU(gpuAttr.getValue());
4310 .Case(
"omp.host_ir_filepath",
4312 if (
auto filepathAttr = dyn_cast<StringAttr>(attr)) {
4313 llvm::OpenMPIRBuilder *ompBuilder =
4315 ompBuilder->loadOffloadInfoMetadata(filepathAttr.getValue());
4322 if (
auto rtlAttr = dyn_cast<omp::FlagsAttr>(attr))
4326 .Case(
"omp.version",
4328 if (
auto versionAttr = dyn_cast<omp::VersionAttr>(attr)) {
4329 llvm::OpenMPIRBuilder *ompBuilder =
4331 ompBuilder->M.addModuleFlag(llvm::Module::Max,
"openmp",
4332 versionAttr.getVersion());
4337 .Case(
"omp.declare_target",
4339 if (
auto declareTargetAttr =
4340 dyn_cast<omp::DeclareTargetAttr>(attr))
4345 .Case(
"omp.requires",
4347 if (
auto requiresAttr = dyn_cast<omp::ClauseRequiresAttr>(attr)) {
4348 using Requires = omp::ClauseRequires;
4349 Requires flags = requiresAttr.getValue();
4350 llvm::OpenMPIRBuilderConfig &config =
4352 config.setHasRequiresReverseOffload(
4353 bitEnumContainsAll(flags, Requires::reverse_offload));
4354 config.setHasRequiresUnifiedAddress(
4355 bitEnumContainsAll(flags, Requires::unified_address));
4356 config.setHasRequiresUnifiedSharedMemory(
4357 bitEnumContainsAll(flags, Requires::unified_shared_memory));
4358 config.setHasRequiresDynamicAllocators(
4359 bitEnumContainsAll(flags, Requires::dynamic_allocators));
4364 .Case(
"omp.target_triples",
4366 if (
auto triplesAttr = dyn_cast<ArrayAttr>(attr)) {
4367 llvm::OpenMPIRBuilderConfig &config =
4369 config.TargetTriples.clear();
4370 config.TargetTriples.reserve(triplesAttr.size());
4371 for (
Attribute tripleAttr : triplesAttr) {
4372 if (
auto tripleStrAttr = dyn_cast<StringAttr>(tripleAttr))
4373 config.TargetTriples.emplace_back(tripleStrAttr.getValue());
4391 LogicalResult OpenMPDialectLLVMIRTranslationInterface::convertOperation(
4392 Operation *op, llvm::IRBuilderBase &builder,
4396 if (ompBuilder->Config.isTargetDevice()) {
4407 registry.
insert<omp::OpenMPDialect>();
4409 dialect->addInterfaces<OpenMPDialectLLVMIRTranslationInterface>();
static llvm::Value * getRefPtrIfDeclareTarget(mlir::Value value, LLVM::ModuleTranslation &moduleTranslation)
static void handleDeclareTargetMapVar(MapInfoData &mapData, LLVM::ModuleTranslation &moduleTranslation, llvm::IRBuilderBase &builder, llvm::Function *func)
static LogicalResult convertOmpAtomicUpdate(omp::AtomicUpdateOp &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP atomic update operation using OpenMPIRBuilder.
static llvm::omp::OrderKind convertOrderKind(std::optional< omp::ClauseOrderKind > o)
Convert Order attribute to llvm::omp::OrderKind.
static LogicalResult convertOmpAtomicCapture(omp::AtomicCaptureOp atomicCaptureOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind convertToCaptureClauseKind(mlir::omp::DeclareTargetCaptureClause captureClause)
static llvm::Expected< llvm::BasicBlock * > allocatePrivateVars(llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, MutableArrayRef< BlockArgument > privateBlockArgs, MutableArrayRef< omp::PrivateClauseOp > privateDecls, MutableArrayRef< mlir::Value > mlirPrivateVars, llvm::SmallVectorImpl< llvm::Value * > &llvmPrivateVars, const llvm::OpenMPIRBuilder::InsertPointTy &allocaIP)
Allocate delayed private variables.
static omp::MapInfoOp getFirstOrLastMappedMemberPtr(omp::MapInfoOp mapInfo, bool first)
static LogicalResult convertIgnoredWrappers(omp::LoopNestOp loopOp, omp::LoopWrapperInterface parentOp, LLVM::ModuleTranslation &moduleTranslation)
Helper function to call convertIgnoredWrapper() for all wrappers of the given loopOp nested inside of...
static LogicalResult convertOmpOrderedRegion(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP 'ordered_region' operation into LLVM IR using OpenMPIRBuilder.
static llvm::OpenMPIRBuilder::InsertPointTy findAllocaInsertPoint(llvm::IRBuilderBase &builder, const LLVM::ModuleTranslation &moduleTranslation)
Find the insertion point for allocas given the current insertion point for normal operations in the b...
static LogicalResult convertOmpAtomicWrite(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an omp.atomic.write operation to LLVM IR.
static OwningAtomicReductionGen makeAtomicReductionGen(omp::DeclareReductionOp decl, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Create an OpenMPIRBuilder-compatible atomic reduction generator for the given reduction declaration.
static LogicalResult convertOmpWsloop(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP workshare loop into LLVM IR using OpenMPIRBuilder.
static LogicalResult convertOmpMaster(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP 'master' operation into LLVM IR using OpenMPIRBuilder.
static LogicalResult convertOmpTaskwaitOp(omp::TaskwaitOp twOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static void createAlteredByCaptureMap(MapInfoData &mapData, LLVM::ModuleTranslation &moduleTranslation, llvm::IRBuilderBase &builder)
static LogicalResult convertOmpTaskOp(omp::TaskOp taskOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP task construct into LLVM IR using OpenMPIRBuilder.
llvm::AtomicRMWInst::BinOp convertBinOpToAtomic(Operation &op)
Converts an LLVM dialect binary operation to the corresponding enum value for atomicrmw supported bin...
static llvm::AtomicOrdering convertAtomicOrdering(std::optional< omp::ClauseMemoryOrderKind > ao)
Convert an Atomic Ordering attribute to llvm::AtomicOrdering.
static LogicalResult convertOmpSections(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static LogicalResult convertOmpCritical(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP 'critical' operation into LLVM IR using OpenMPIRBuilder.
static LogicalResult convertOmpTargetData(Operation *op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static LogicalResult allocAndInitializeReductionVars(OP op, ArrayRef< BlockArgument > reductionArgs, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, llvm::OpenMPIRBuilder::InsertPointTy &allocaIP, SmallVectorImpl< omp::DeclareReductionOp > &reductionDecls, SmallVectorImpl< llvm::Value * > &privateReductionVariables, DenseMap< Value, llvm::Value * > &reductionVariableMap, llvm::ArrayRef< bool > isByRef)
static LogicalResult convertOmpSimd(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP simd loop into LLVM IR using OpenMPIRBuilder.
static LogicalResult convertOmpOrdered(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP 'ordered' operation into LLVM IR using OpenMPIRBuilder.
static LogicalResult convertOmpMasked(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP 'masked' operation into LLVM IR using OpenMPIRBuilder.
static bool isTargetDeviceOp(Operation *op)
static LogicalResult inlineOmpRegionCleanup(llvm::SmallVectorImpl< Region * > &cleanupRegions, llvm::ArrayRef< llvm::Value * > privateVariables, LLVM::ModuleTranslation &moduleTranslation, llvm::IRBuilderBase &builder, StringRef regionName, bool shouldLoadCleanupRegionArg=true)
handling of DeclareReductionOp's cleanup region
static void mapInitializationArgs(T loop, LLVM::ModuleTranslation &moduleTranslation, SmallVectorImpl< omp::DeclareReductionOp > &reductionDecls, DenseMap< Value, llvm::Value * > &reductionVariableMap, unsigned i)
Map input arguments to reduction initialization region.
static int getMapDataMemberIdx(MapInfoData &mapData, omp::MapInfoOp memberOp)
static llvm::SmallString< 64 > getDeclareTargetRefPtrSuffix(LLVM::GlobalOp globalOp, llvm::OpenMPIRBuilder &ompBuilder)
static void collectPrivatizationDecls(OP op, SmallVectorImpl< omp::PrivateClauseOp > &privatizations)
Populates privatizations with privatization declarations used for the given op.
static OwningReductionGen makeReductionGen(omp::DeclareReductionOp decl, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Create an OpenMPIRBuilder-compatible reduction generator for the given reduction declaration.
static LogicalResult convertOmpParallel(omp::ParallelOp opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts the OpenMP parallel operation to LLVM IR.
static llvm::omp::OpenMPOffloadMappingFlags mapParentWithMembers(LLVM::ModuleTranslation &moduleTranslation, llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder &ompBuilder, DataLayout &dl, llvm::OpenMPIRBuilder::MapInfosTy &combinedInfo, MapInfoData &mapData, uint64_t mapDataIndex, bool isTargetParams)
static LogicalResult inlineConvertOmpRegions(Region ®ion, StringRef blockName, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, SmallVectorImpl< llvm::Value * > *continuationBlockArgs=nullptr)
Translates the blocks contained in the given region and appends them to at the current insertion poin...
static LogicalResult convertOmpThreadprivate(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP Threadprivate operation into LLVM IR using OpenMPIRBuilder.
static omp::PrivateClauseOp findPrivatizer(Operation *from, SymbolRefAttr symbolName)
Looks up from the operation from and returns the PrivateClauseOp with name symbolName.
static LogicalResult convertDeclareTargetAttr(Operation *op, mlir::omp::DeclareTargetAttr attribute, LLVM::ModuleTranslation &moduleTranslation)
static LogicalResult createReductionsAndCleanup(OP op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, llvm::OpenMPIRBuilder::InsertPointTy &allocaIP, SmallVectorImpl< omp::DeclareReductionOp > &reductionDecls, ArrayRef< llvm::Value * > privateReductionVariables, ArrayRef< bool > isByRef)
LogicalResult convertFlagsAttr(Operation *op, mlir::omp::FlagsAttr attribute, LLVM::ModuleTranslation &moduleTranslation)
Lowers the FlagsAttr which is applied to the module on the device pass when offloading,...
uint64_t getArrayElementSizeInBits(LLVM::LLVMArrayType arrTy, DataLayout &dl)
std::vector< llvm::Value * > calculateBoundsOffset(LLVM::ModuleTranslation &moduleTranslation, llvm::IRBuilderBase &builder, bool isArrayTy, OperandRange bounds)
This function calculates the array/pointer offset for map data provided with bounds operations,...
static void processIndividualMap(MapInfoData &mapData, size_t mapDataIdx, llvm::OpenMPIRBuilder::MapInfosTy &combinedInfo, bool isTargetParams, int mapDataParentIdx=-1)
static LogicalResult allocReductionVars(T loop, ArrayRef< BlockArgument > reductionArgs, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, const llvm::OpenMPIRBuilder::InsertPointTy &allocaIP, SmallVectorImpl< omp::DeclareReductionOp > &reductionDecls, SmallVectorImpl< llvm::Value * > &privateReductionVariables, DenseMap< Value, llvm::Value * > &reductionVariableMap, SmallVectorImpl< DeferredStore > &deferredStores, llvm::ArrayRef< bool > isByRefs)
Allocate space for privatized reduction variables.
static ArrayRef< bool > getIsByRef(std::optional< ArrayRef< bool >> attr)
static void genMapInfos(llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, DataLayout &dl, llvm::OpenMPIRBuilder::MapInfosTy &combinedInfo, MapInfoData &mapData, bool isTargetParams=false)
static llvm::IRBuilderBase::InsertPoint createDeviceArgumentAccessor(MapInfoData &mapData, llvm::Argument &arg, llvm::Value *input, llvm::Value *&retVal, llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder &ompBuilder, LLVM::ModuleTranslation &moduleTranslation, llvm::IRBuilderBase::InsertPoint allocaIP, llvm::IRBuilderBase::InsertPoint codeGenIP)
static llvm::omp::ProcBindKind getProcBindKind(omp::ClauseProcBindKind kind)
Convert ProcBindKind from MLIR-generated enum to LLVM enum.
static LogicalResult convertTargetOpsInNest(Operation *op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static void processMapMembersWithParent(LLVM::ModuleTranslation &moduleTranslation, llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder &ompBuilder, DataLayout &dl, llvm::OpenMPIRBuilder::MapInfosTy &combinedInfo, MapInfoData &mapData, uint64_t mapDataIndex, llvm::omp::OpenMPOffloadMappingFlags memberOfFlag)
static LogicalResult convertOmpSingle(omp::SingleOp &singleOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP single construct into LLVM IR using OpenMPIRBuilder.
static void collectReductionDecls(T op, SmallVectorImpl< omp::DeclareReductionOp > &reductions)
Populates reductions with reduction declarations used in the given op.
static LogicalResult handleError(llvm::Error error, Operation &op)
static void processMapWithMembersOf(LLVM::ModuleTranslation &moduleTranslation, llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder &ompBuilder, DataLayout &dl, llvm::OpenMPIRBuilder::MapInfosTy &combinedInfo, MapInfoData &mapData, uint64_t mapDataIndex, bool isTargetParams)
static LogicalResult convertOmpTarget(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind convertToDeviceClauseKind(mlir::omp::DeclareTargetDeviceType deviceClause)
static LogicalResult checkImplementationStatus(Operation &op)
Check whether translation to LLVM IR for the given operation is currently supported.
static LogicalResult convertIgnoredWrapper(omp::LoopWrapperInterface &opInst, LLVM::ModuleTranslation &moduleTranslation)
Helper function to map block arguments defined by ignored loop wrappers to LLVM values and prevent an...
static LogicalResult convertOmpAtomicRead(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Convert omp.atomic.read operation to LLVM IR.
static void collectMapDataFromMapOperands(MapInfoData &mapData, SmallVectorImpl< Value > &mapVars, LLVM::ModuleTranslation &moduleTranslation, DataLayout &dl, llvm::IRBuilderBase &builder, const ArrayRef< Value > &useDevPtrOperands={}, const ArrayRef< Value > &useDevAddrOperands={})
static bool getTargetEntryUniqueInfo(llvm::TargetRegionEntryInfo &targetInfo, omp::TargetOp targetOp, llvm::StringRef parentName="")
static void collectReductionInfo(T loop, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, SmallVectorImpl< omp::DeclareReductionOp > &reductionDecls, SmallVectorImpl< OwningReductionGen > &owningReductionGens, SmallVectorImpl< OwningAtomicReductionGen > &owningAtomicReductionGens, const ArrayRef< llvm::Value * > privateReductionVariables, SmallVectorImpl< llvm::OpenMPIRBuilder::ReductionInfo > &reductionInfos)
Collect reduction info.
static LogicalResult convertOmpTeams(omp::TeamsOp op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static LogicalResult convertHostOrTargetOperation(Operation *op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Given an OpenMP MLIR operation, create the corresponding LLVM IR (including OpenMP runtime calls).
static bool checkIfPointerMap(omp::MapInfoOp mapOp)
static LogicalResult convertTargetDeviceOp(Operation *op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static void buildDependData(std::optional< ArrayAttr > dependKinds, OperandRange dependVars, LLVM::ModuleTranslation &moduleTranslation, SmallVectorImpl< llvm::OpenMPIRBuilder::DependData > &dds)
static llvm::Expected< llvm::BasicBlock * > convertOmpOpRegions(Region ®ion, StringRef blockName, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, SmallVectorImpl< llvm::PHINode * > *continuationBlockPHIs=nullptr)
Converts the given region that appears within an OpenMP dialect operation to LLVM IR,...
static LogicalResult convertOmpTaskgroupOp(omp::TaskgroupOp tgOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP taskgroup construct into LLVM IR using OpenMPIRBuilder.
llvm::Value * getSizeInBytes(DataLayout &dl, const mlir::Type &type, Operation *clauseOp, llvm::Value *basePointer, llvm::Type *baseType, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static bool isDeclareTargetLink(mlir::Value value)
#define MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(CLASS_NAME)
Attributes are known-constant values of operations.
Block represents an ordered list of Operations.
BlockArgument getArgument(unsigned i)
unsigned getNumArguments()
Operation * getTerminator()
Get the terminator operation of this block.
The main mechanism for performing data layout queries.
llvm::TypeSize getTypeSizeInBits(Type t) const
Returns the size in bits of the given type in the current scope.
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.
virtual LogicalResult amendOperation(Operation *op, ArrayRef< llvm::Instruction * > instructions, NamedAttribute attribute, LLVM::ModuleTranslation &moduleTranslation) const
Hook for derived dialect interface to act on an operation that has dialect attributes from the derive...
virtual LogicalResult convertOperation(Operation *op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation) const
Hook for derived dialect interface to provide translation of the operations to LLVM IR.
LLVMTranslationDialectInterface(Dialect *dialect)
Concrete CRTP base class for ModuleTranslation stack frames.
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.
SmallVector< llvm::Value * > lookupValues(ValueRange values)
Looks up remapped a list of remapped values.
llvm::BasicBlock * lookupBlock(Block *block) const
Finds an LLVM IR basic block that corresponds to the given MLIR block.
SymbolTableCollection & symbolTable()
llvm::Type * convertType(Type type)
Converts the type from MLIR LLVM dialect to LLVM.
llvm::OpenMPIRBuilder * getOpenMPBuilder()
Returns the OpenMP IR builder associated with the LLVM IR module being constructed.
llvm::LLVMContext & getLLVMContext() const
Returns the LLVM context in which the IR is being constructed.
llvm::GlobalValue * lookupGlobal(Operation *op)
Finds an LLVM IR global value that corresponds to the given MLIR operation defining a global value.
llvm::Module * getLLVMModule()
Returns the LLVM module in which the IR is 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.
WalkResult stackWalk(llvm::function_ref< WalkResult(const T &)> callback) const
Calls callback for every ModuleTranslation stack frame of type T starting from the top of the stack.
void forgetMapping(Region ®ion)
Removes the mapping for blocks contained in the region and values defined in these blocks.
void mapValue(Value mlir, llvm::Value *llvm)
Stores the mapping between an MLIR value and its LLVM IR counterpart.
T findInstanceOf()
Return an instance of the given location type if one is nested under the current location.
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.
NamedAttribute represents a combination of a name and an Attribute value.
StringAttr getName() const
Return the name of the attribute.
Attribute getValue() const
Return the value of the attribute.
This class implements the operand iterators for the Operation class.
Operation is the basic unit of execution within MLIR.
Value getOperand(unsigned idx)
InFlightDiagnostic emitWarning(const Twine &message={})
Emit a warning about this operation, reporting up to any diagnostic handlers that may be listening.
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
std::enable_if_t< llvm::function_traits< std::decay_t< FnT > >::num_args==1, RetT > walk(FnT &&callback)
Walk the operation by calling the callback for each nested operation (including this one),...
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.
operand_range getOperands()
Returns an iterator on the underlying Value's.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
BlockArgListType getArguments()
Operation * getParentOp()
Return the parent operation this region is attached to.
unsigned getNumArguments()
BlockListType & getBlocks()
@ Private
The symbol is private and may only be referenced by SymbolRefAttrs local to the operations within the...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
A utility result that is used to signal how to proceed with an ongoing walk:
bool wasInterrupted() const
Returns true if the walk was interrupted.
static WalkResult interrupt()
The OpAsmOpInterface, see OpAsmInterface.td for more details.
void connectPHINodes(Region ®ion, const ModuleTranslation &state)
For all blocks in the region that were converted to LLVM IR using the given ModuleTranslation,...
llvm::Constant * createMappingInformation(Location loc, llvm::OpenMPIRBuilder &builder)
Create a constant string representing the mapping information extracted from the MLIR location inform...
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
Runtime
Potential runtimes for AMD GPU kernels.
Include the generated interface declarations.
SetVector< Block * > getBlocksSortedByDominance(Region ®ion)
Gets a list of blocks that is sorted according to dominance.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
void registerOpenMPDialectTranslation(DialectRegistry ®istry)
Register the OpenMP dialect and the translation from it to the LLVM IR in the given registry;.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
RAII object calling stackPush/stackPop on construction/destruction.