26#include "llvm/ADT/ArrayRef.h"
27#include "llvm/ADT/SmallVector.h"
28#include "llvm/ADT/TypeSwitch.h"
29#include "llvm/Frontend/OpenMP/OMPConstants.h"
30#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
31#include "llvm/IR/Constants.h"
32#include "llvm/IR/DebugInfoMetadata.h"
33#include "llvm/IR/DerivedTypes.h"
34#include "llvm/IR/IRBuilder.h"
35#include "llvm/IR/MDBuilder.h"
36#include "llvm/IR/ReplaceConstant.h"
37#include "llvm/Support/AMDGPUAddrSpace.h"
38#include "llvm/Support/FileSystem.h"
39#include "llvm/Support/NVPTXAddrSpace.h"
40#include "llvm/Support/VirtualFileSystem.h"
41#include "llvm/TargetParser/Triple.h"
42#include "llvm/Transforms/Utils/ModuleUtils.h"
53static llvm::omp::ScheduleKind
54convertToScheduleKind(std::optional<omp::ClauseScheduleKind> schedKind) {
55 if (!schedKind.has_value())
56 return llvm::omp::OMP_SCHEDULE_Default;
57 switch (schedKind.value()) {
58 case omp::ClauseScheduleKind::Static:
59 return llvm::omp::OMP_SCHEDULE_Static;
60 case omp::ClauseScheduleKind::Dynamic:
61 return llvm::omp::OMP_SCHEDULE_Dynamic;
62 case omp::ClauseScheduleKind::Guided:
63 return llvm::omp::OMP_SCHEDULE_Guided;
64 case omp::ClauseScheduleKind::Auto:
65 return llvm::omp::OMP_SCHEDULE_Auto;
66 case omp::ClauseScheduleKind::Runtime:
67 return llvm::omp::OMP_SCHEDULE_Runtime;
68 case omp::ClauseScheduleKind::Distribute:
69 return llvm::omp::OMP_SCHEDULE_Distribute;
71 llvm_unreachable(
"unhandled schedule clause argument");
76class OpenMPAllocStackFrame
81 explicit OpenMPAllocStackFrame(
82 llvm::OpenMPIRBuilder::InsertPointTy allocaIP,
83 llvm::ArrayRef<llvm::BasicBlock *> deallocBlocks)
84 : allocInsertPoint(allocaIP), deallocBlocks(deallocBlocks) {}
85 llvm::OpenMPIRBuilder::InsertPointTy allocInsertPoint;
86 llvm::SmallVector<llvm::BasicBlock *> deallocBlocks;
92class OpenMPLoopInfoStackFrame
96 llvm::CanonicalLoopInfo *loopInfo =
nullptr;
115class PreviouslyReportedError
116 :
public llvm::ErrorInfo<PreviouslyReportedError> {
118 void log(raw_ostream &)
const override {
122 std::error_code convertToErrorCode()
const override {
124 "PreviouslyReportedError doesn't support ECError conversion");
131char PreviouslyReportedError::ID = 0;
142class LinearClauseProcessor {
145 SmallVector<llvm::Value *> linearPreconditionVars;
146 SmallVector<llvm::Value *> linearLoopBodyTemps;
147 SmallVector<llvm::Value *> linearOrigVal;
148 SmallVector<llvm::Value *> linearSteps;
149 SmallVector<llvm::Type *> linearVarTypes;
150 llvm::BasicBlock *linearFinalizationBB;
151 llvm::BasicBlock *linearExitBB;
152 llvm::BasicBlock *linearLastIterExitBB;
156 void registerType(LLVM::ModuleTranslation &moduleTranslation,
157 mlir::Attribute &ty) {
158 linearVarTypes.push_back(moduleTranslation.
convertType(
159 mlir::cast<mlir::TypeAttr>(ty).getValue()));
163 void createLinearVar(llvm::IRBuilderBase &builder,
164 LLVM::ModuleTranslation &moduleTranslation,
165 llvm::Value *linearVar,
int idx) {
166 linearPreconditionVars.push_back(
167 builder.CreateAlloca(linearVarTypes[idx],
nullptr,
".linear_var"));
168 llvm::Value *linearLoopBodyTemp =
169 builder.CreateAlloca(linearVarTypes[idx],
nullptr,
".linear_result");
170 linearOrigVal.push_back(linearVar);
171 linearLoopBodyTemps.push_back(linearLoopBodyTemp);
175 inline void initLinearStep(LLVM::ModuleTranslation &moduleTranslation,
176 mlir::Value &linearStep) {
177 linearSteps.push_back(moduleTranslation.
lookupValue(linearStep));
181 void initLinearVar(llvm::IRBuilderBase &builder,
182 LLVM::ModuleTranslation &moduleTranslation,
183 llvm::BasicBlock *loopPreHeader) {
184 builder.SetInsertPoint(loopPreHeader->getTerminator());
185 for (
size_t index = 0; index < linearOrigVal.size(); index++) {
186 llvm::LoadInst *linearVarLoad =
187 builder.CreateLoad(linearVarTypes[index], linearOrigVal[index]);
188 builder.CreateStore(linearVarLoad, linearPreconditionVars[index]);
193 void updateLinearVar(llvm::IRBuilderBase &builder, llvm::BasicBlock *loopBody,
194 llvm::Value *loopInductionVar) {
195 builder.SetInsertPoint(loopBody->getTerminator());
196 for (
size_t index = 0; index < linearPreconditionVars.size(); index++) {
197 llvm::Type *linearVarType = linearVarTypes[index];
198 llvm::Value *iv = loopInductionVar;
199 llvm::Value *step = linearSteps[index];
201 if (!iv->getType()->isIntegerTy())
202 llvm_unreachable(
"OpenMP loop induction variable must be an integer "
205 if (linearVarType->isIntegerTy()) {
207 iv = builder.CreateSExtOrTrunc(iv, linearVarType);
208 step = builder.CreateSExtOrTrunc(step, linearVarType);
210 llvm::LoadInst *linearVarStart =
211 builder.CreateLoad(linearVarType, linearPreconditionVars[index]);
212 llvm::Value *mulInst = builder.CreateMul(iv, step);
213 llvm::Value *addInst = builder.CreateAdd(linearVarStart, mulInst);
214 builder.CreateStore(addInst, linearLoopBodyTemps[index]);
215 }
else if (linearVarType->isFloatingPointTy()) {
217 step = builder.CreateSExtOrTrunc(step, iv->getType());
218 llvm::Value *mulInst = builder.CreateMul(iv, step);
220 llvm::LoadInst *linearVarStart =
221 builder.CreateLoad(linearVarType, linearPreconditionVars[index]);
222 llvm::Value *mulFp = builder.CreateSIToFP(mulInst, linearVarType);
223 llvm::Value *addInst = builder.CreateFAdd(linearVarStart, mulFp);
224 builder.CreateStore(addInst, linearLoopBodyTemps[index]);
227 "Linear variable must be of integer or floating-point type");
234 void splitLinearFiniBB(llvm::IRBuilderBase &builder,
235 llvm::BasicBlock *loopExit) {
236 linearFinalizationBB = loopExit->splitBasicBlock(
237 loopExit->getTerminator(),
"omp_loop.linear_finalization");
238 linearExitBB = linearFinalizationBB->splitBasicBlock(
239 linearFinalizationBB->getTerminator(),
"omp_loop.linear_exit");
240 linearLastIterExitBB = linearFinalizationBB->splitBasicBlock(
241 linearFinalizationBB->getTerminator(),
"omp_loop.linear_lastiter_exit");
245 llvm::OpenMPIRBuilder::InsertPointOrErrorTy
246 finalizeLinearVar(llvm::IRBuilderBase &builder,
247 LLVM::ModuleTranslation &moduleTranslation,
248 llvm::Value *lastIter) {
250 builder.SetInsertPoint(linearFinalizationBB->getTerminator());
251 llvm::Value *loopLastIterLoad = builder.CreateLoad(
252 llvm::Type::getInt32Ty(builder.getContext()), lastIter);
253 llvm::Value *isLast =
254 builder.CreateCmp(llvm::CmpInst::ICMP_NE, loopLastIterLoad,
255 llvm::ConstantInt::get(
256 llvm::Type::getInt32Ty(builder.getContext()), 0));
258 builder.SetInsertPoint(linearLastIterExitBB->getTerminator());
259 for (
size_t index = 0; index < linearOrigVal.size(); index++) {
260 llvm::LoadInst *linearVarTemp =
261 builder.CreateLoad(linearVarTypes[index], linearLoopBodyTemps[index]);
262 builder.CreateStore(linearVarTemp, linearOrigVal[index]);
268 builder.SetInsertPoint(linearFinalizationBB->getTerminator());
269 builder.CreateCondBr(isLast, linearLastIterExitBB, linearExitBB);
270 linearFinalizationBB->getTerminator()->eraseFromParent();
272 builder.SetInsertPoint(linearExitBB->getTerminator());
274 builder.saveIP(), llvm::omp::OMPD_barrier);
279 void emitStoresForLinearVar(llvm::IRBuilderBase &builder) {
280 for (
size_t index = 0; index < linearOrigVal.size(); index++) {
281 llvm::LoadInst *linearVarTemp =
282 builder.CreateLoad(linearVarTypes[index], linearLoopBodyTemps[index]);
283 builder.CreateStore(linearVarTemp, linearOrigVal[index]);
289 void rewriteInPlace(llvm::IRBuilderBase &builder, llvm::BasicBlock *startBB,
290 llvm::BasicBlock *endBB,
size_t varIndex) {
291 llvm::SmallVector<llvm::BasicBlock *, 32> worklist;
292 llvm::SmallPtrSet<llvm::BasicBlock *, 32> collectedBBs;
294 assert(startBB && endBB &&
"Invalid startBB/endBB");
297 worklist.push_back(startBB);
298 collectedBBs.insert(startBB);
300 while (!worklist.empty()) {
301 llvm::BasicBlock *bb = worklist.pop_back_val();
306 for (llvm::BasicBlock *succ : llvm::successors(bb)) {
307 if (collectedBBs.insert(succ).second)
308 worklist.push_back(succ);
313 llvm::SmallVector<llvm::User *> users(linearOrigVal[varIndex]->users());
314 for (
auto *user : users) {
315 if (
auto *userInst = dyn_cast<llvm::Instruction>(user)) {
316 if (collectedBBs.contains(userInst->getParent()))
317 user->replaceUsesOfWith(linearOrigVal[varIndex],
318 linearLoopBodyTemps[varIndex]);
329 SymbolRefAttr symbolName) {
330 omp::PrivateClauseOp privatizer =
333 assert(privatizer &&
"privatizer not found in the symbol table");
344 auto todo = [&op](StringRef clauseName) {
345 return op.
emitError() <<
"not yet implemented: Unhandled clause "
346 << clauseName <<
" in " << op.
getName()
350 auto checkAllocate = [&todo](
auto op, LogicalResult &
result) {
351 if (!op.getAllocateVars().empty() || !op.getAllocatorVars().empty())
352 result = todo(
"allocate");
354 auto checkBare = [&todo](
auto op, LogicalResult &
result) {
355 if (op.getKernelType() == omp::TargetExecMode::bare)
356 result = todo(
"ompx_bare");
358 auto checkDepend = [&todo](
auto op, LogicalResult &
result) {
359 if (!op.getDependVars().empty() || op.getDependKinds())
362 auto checkHint = [](
auto op, LogicalResult &) {
366 auto checkInReduction = [&todo](
auto op, LogicalResult &
result) {
367 if (!op.getInReductionVars().empty() || op.getInReductionByref() ||
368 op.getInReductionSyms())
369 result = todo(
"in_reduction");
371 auto checkNowait = [&todo](
auto op, LogicalResult &
result) {
375 auto checkOrder = [&todo](
auto op, LogicalResult &
result) {
376 if (op.getOrder() || op.getOrderMod())
379 auto checkPrivate = [&todo](
auto op, LogicalResult &
result) {
380 if (!op.getPrivateVars().empty() || op.getPrivateSyms())
381 result = todo(
"privatization");
383 auto checkReduction = [&todo](
auto op, LogicalResult &
result) {
384 if (isa<omp::TeamsOp>(op))
385 if (!op.getReductionVars().empty() || op.getReductionByref() ||
386 op.getReductionSyms())
387 result = todo(
"reduction");
388 if (op.getReductionMod() &&
389 op.getReductionMod().value() != omp::ReductionModifier::defaultmod) {
390 omp::ReductionModifier mod = op.getReductionMod().value();
394 bool taskModifierSupported =
395 mod == omp::ReductionModifier::task &&
396 isa<omp::ParallelOp, omp::WsloopOp, omp::SectionsOp>(op);
397 if (!taskModifierSupported) {
398 result = todo(
"reduction with modifier");
399 }
else if (
auto byref = op.getReductionByref()) {
402 for (
bool isByRef : *byref)
404 result = todo(
"task reduction modifier with by-ref reduction");
410 auto checkTaskReductionByref = [&todo](
auto op, LogicalResult &
result) {
411 if (
auto byrefAttr = op.getTaskReductionByref())
412 for (
bool isByRef : *byrefAttr)
414 result = todo(
"task_reduction with byref modifier");
418 auto checkReductionByref = [&todo](
auto op, LogicalResult &
result) {
419 if (
auto byrefAttr = op.getReductionByref())
420 for (
bool isByRef : *byrefAttr)
422 result = todo(
"reduction with byref modifier");
426 auto checkInReductionByref = [&todo](
auto op, LogicalResult &
result) {
427 if (
auto byrefAttr = op.getInReductionByref())
428 for (
bool isByRef : *byrefAttr)
430 result = todo(
"in_reduction with byref modifier");
434 auto checkNumTeams = [&todo](
auto op, LogicalResult &
result) {
435 if (op.hasNumTeamsMultiDim())
436 result = todo(
"num_teams with multi-dimensional values");
438 auto checkNumThreads = [&todo](
auto op, LogicalResult &
result) {
439 if (op.hasNumThreadsMultiDim())
440 result = todo(
"num_threads with multi-dimensional values");
443 auto checkThreadLimit = [&todo](
auto op, LogicalResult &
result) {
444 if (op.hasThreadLimitMultiDim())
445 result = todo(
"thread_limit with multi-dimensional values");
447 auto checkMap = [&todo](
auto op, LogicalResult &
result) {
448 if (!op.getMapIterated().empty())
449 result = todo(
"map/motion clause with iterator modifier");
452 auto checkDynGroupprivate = [&todo](
auto op, LogicalResult &
result) {
453 if (op.getDynGroupprivateSize())
454 result = todo(
"dyn_groupprivate");
459 .Case([&](omp::DistributeOp op) {
460 checkAllocate(op,
result);
463 .Case([&](omp::SectionsOp op) {
464 checkAllocate(op,
result);
466 checkReduction(op,
result);
468 .Case([&](omp::ScopeOp op) {
469 checkAllocate(op,
result);
470 checkReduction(op,
result);
472 .Case([&](omp::SingleOp op) {
473 checkAllocate(op,
result);
476 .Case([&](omp::TeamsOp op) {
477 checkAllocate(op,
result);
479 checkNumTeams(op,
result);
480 checkThreadLimit(op,
result);
481 checkDynGroupprivate(op,
result);
483 .Case([&](omp::TaskOp op) {
484 checkAllocate(op,
result);
485 checkInReductionByref(op,
result);
487 .Case([&](omp::TaskgroupOp op) {
488 checkAllocate(op,
result);
489 checkTaskReductionByref(op,
result);
491 .Case([&](omp::TaskwaitOp op) {
495 .Case([&](omp::TaskloopContextOp op) {
496 checkAllocate(op,
result);
497 checkInReductionByref(op,
result);
498 checkReduction(op,
result);
499 checkReductionByref(op,
result);
501 .Case([&](omp::WsloopOp op) {
502 checkAllocate(op,
result);
504 checkReduction(op,
result);
506 .Case([&](omp::ParallelOp op) {
507 checkAllocate(op,
result);
508 checkReduction(op,
result);
509 checkNumThreads(op,
result);
511 .Case([&](omp::SimdOp op) { checkReduction(op,
result); })
512 .Case<omp::AtomicReadOp, omp::AtomicWriteOp, omp::AtomicUpdateOp,
513 omp::AtomicCaptureOp>([&](
auto op) { checkHint(op,
result); })
514 .Case([&](omp::AtomicCompareOp op) {
520 auto structTy = dyn_cast<LLVM::LLVMStructType>(argType);
526 result = todo(
"compare for complex types wider than 128 bits");
528 .Case<omp::TargetEnterDataOp, omp::TargetExitDataOp>([&](
auto op) {
532 .Case([&](omp::TargetUpdateOp op) {
536 .Case([&](omp::TargetOp op) {
537 checkAllocate(op,
result);
539 checkInReduction(op,
result);
541 checkThreadLimit(op,
result);
543 .Case([&](omp::TargetDataOp op) { checkMap(op,
result); })
544 .Case([&](omp::DeclareMapperInfoOp op) { checkMap(op,
result); })
555 llvm::handleAllErrors(
557 [&](
const PreviouslyReportedError &) {
result = failure(); },
558 [&](
const llvm::ErrorInfoBase &err) {
581 llvm::OpenMPIRBuilder::InsertPointTy allocInsertPoint;
584 [&](OpenMPAllocStackFrame &frame) {
585 allocInsertPoint = frame.allocInsertPoint;
586 deallocInsertPoints = frame.deallocBlocks;
594 allocInsertPoint.getBlock()->getParent() ==
595 builder.GetInsertBlock()->getParent()) {
597 deallocBlocks->insert(deallocBlocks->end(), deallocInsertPoints.begin(),
598 deallocInsertPoints.end());
599 return allocInsertPoint;
609 if (builder.GetInsertBlock() ==
610 &builder.GetInsertBlock()->getParent()->getEntryBlock()) {
611 assert(builder.GetInsertPoint() == builder.GetInsertBlock()->end() &&
612 "Assuming end of basic block");
613 llvm::BasicBlock *entryBB = llvm::BasicBlock::Create(
614 builder.getContext(),
"entry", builder.GetInsertBlock()->getParent(),
615 builder.GetInsertBlock()->getNextNode());
616 builder.CreateBr(entryBB);
617 builder.SetInsertPoint(entryBB);
623 for (llvm::BasicBlock &block : *builder.GetInsertBlock()->getParent()) {
627 llvm::Instruction *terminator = block.getTerminatorOrNull();
628 if (isa_and_present<llvm::ReturnInst>(terminator))
629 deallocBlocks->emplace_back(&block);
633 llvm::BasicBlock &funcEntryBlock =
634 builder.GetInsertBlock()->getParent()->getEntryBlock();
635 return llvm::OpenMPIRBuilder::InsertPointTy(
636 &funcEntryBlock, funcEntryBlock.getFirstInsertionPt());
642static llvm::CanonicalLoopInfo *
644 llvm::CanonicalLoopInfo *loopInfo =
nullptr;
645 moduleTranslation.
stackWalk<OpenMPLoopInfoStackFrame>(
646 [&](OpenMPLoopInfoStackFrame &frame) {
647 loopInfo = frame.loopInfo;
659 Region ®ion, StringRef blockName, llvm::IRBuilderBase &builder,
662 bool isLoopWrapper = isa<omp::LoopWrapperInterface>(region.
getParentOp());
664 llvm::BasicBlock *continuationBlock =
665 splitBB(builder,
true,
"omp.region.cont");
666 llvm::BasicBlock *sourceBlock = builder.GetInsertBlock();
668 llvm::LLVMContext &llvmContext = builder.getContext();
669 for (
Block &bb : region) {
670 llvm::BasicBlock *llvmBB = llvm::BasicBlock::Create(
671 llvmContext, blockName, builder.GetInsertBlock()->getParent(),
672 builder.GetInsertBlock()->getNextNode());
673 moduleTranslation.
mapBlock(&bb, llvmBB);
676 llvm::Instruction *sourceTerminator = sourceBlock->getTerminator();
683 unsigned numYields = 0;
685 if (!isLoopWrapper) {
686 bool operandsProcessed =
false;
688 if (omp::YieldOp yield = dyn_cast<omp::YieldOp>(bb.getTerminator())) {
689 if (!operandsProcessed) {
690 for (
unsigned i = 0, e = yield->getNumOperands(); i < e; ++i) {
691 continuationBlockPHITypes.push_back(
692 moduleTranslation.
convertType(yield->getOperand(i).getType()));
694 operandsProcessed =
true;
696 assert(continuationBlockPHITypes.size() == yield->getNumOperands() &&
697 "mismatching number of values yielded from the region");
698 for (
unsigned i = 0, e = yield->getNumOperands(); i < e; ++i) {
699 llvm::Type *operandType =
700 moduleTranslation.
convertType(yield->getOperand(i).getType());
702 assert(continuationBlockPHITypes[i] == operandType &&
703 "values of mismatching types yielded from the region");
713 if (!continuationBlockPHITypes.empty())
715 continuationBlockPHIs &&
716 "expected continuation block PHIs if converted regions yield values");
717 if (continuationBlockPHIs) {
718 llvm::IRBuilderBase::InsertPointGuard guard(builder);
719 continuationBlockPHIs->reserve(continuationBlockPHITypes.size());
720 builder.SetInsertPoint(continuationBlock, continuationBlock->begin());
721 for (llvm::Type *ty : continuationBlockPHITypes)
722 continuationBlockPHIs->push_back(builder.CreatePHI(ty, numYields));
728 for (
Block *bb : blocks) {
729 llvm::BasicBlock *llvmBB = moduleTranslation.
lookupBlock(bb);
732 if (bb->isEntryBlock()) {
733 assert(sourceTerminator->getNumSuccessors() == 1 &&
734 "provided entry block has multiple successors");
735 assert(sourceTerminator->getSuccessor(0) == continuationBlock &&
736 "ContinuationBlock is not the successor of the entry block");
737 sourceTerminator->setSuccessor(0, llvmBB);
740 llvm::IRBuilderBase::InsertPointGuard guard(builder);
742 moduleTranslation.
convertBlock(*bb, bb->isEntryBlock(), builder)))
743 return llvm::make_error<PreviouslyReportedError>();
748 builder.CreateBr(continuationBlock);
759 Operation *terminator = bb->getTerminator();
760 if (isa<omp::TerminatorOp, omp::YieldOp>(terminator)) {
761 builder.CreateBr(continuationBlock);
763 for (
unsigned i = 0, e = terminator->
getNumOperands(); i < e; ++i)
764 (*continuationBlockPHIs)[i]->addIncoming(
778 return continuationBlock;
784 case omp::ClauseProcBindKind::Close:
785 return llvm::omp::ProcBindKind::OMP_PROC_BIND_close;
786 case omp::ClauseProcBindKind::Master:
787 return llvm::omp::ProcBindKind::OMP_PROC_BIND_master;
788 case omp::ClauseProcBindKind::Primary:
789 return llvm::omp::ProcBindKind::OMP_PROC_BIND_primary;
790 case omp::ClauseProcBindKind::Spread:
791 return llvm::omp::ProcBindKind::OMP_PROC_BIND_spread;
793 llvm_unreachable(
"Unknown ClauseProcBindKind kind");
800 auto maskedOp = cast<omp::MaskedOp>(opInst);
801 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
806 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
809 auto ®ion = maskedOp.getRegion();
810 builder.restoreIP(codeGenIP);
818 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
820 llvm::Value *filterVal =
nullptr;
821 if (
auto filterVar = maskedOp.getFilteredThreadId()) {
822 filterVal = moduleTranslation.
lookupValue(filterVar);
824 llvm::LLVMContext &llvmContext = builder.getContext();
826 llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvmContext), 0);
828 assert(filterVal !=
nullptr);
829 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
830 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
837 builder.restoreIP(*afterIP);
845 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
846 auto masterOp = cast<omp::MasterOp>(opInst);
851 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
854 auto ®ion = masterOp.getRegion();
855 builder.restoreIP(codeGenIP);
863 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
865 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
866 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
873 builder.restoreIP(*afterIP);
881 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
882 auto criticalOp = cast<omp::CriticalOp>(opInst);
887 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
890 auto ®ion = cast<omp::CriticalOp>(opInst).getRegion();
891 builder.restoreIP(codeGenIP);
899 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
901 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
902 llvm::LLVMContext &llvmContext = moduleTranslation.
getLLVMContext();
903 llvm::Constant *hint =
nullptr;
906 if (criticalOp.getNameAttr()) {
909 auto symbolRef = cast<SymbolRefAttr>(criticalOp.getNameAttr());
910 auto criticalDeclareOp =
914 llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvmContext),
915 static_cast<int>(criticalDeclareOp.getHint()));
917 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
919 ompLoc, bodyGenCB, finiCB, criticalOp.getName().value_or(
""), hint);
924 builder.restoreIP(*afterIP);
931 template <
typename OP>
934 cast<
omp::BlockArgOpenMPOpInterface>(*op).getPrivateBlockArgs()) {
937 collectPrivatizationDecls<OP>(op);
952 void collectPrivatizationDecls(OP op) {
953 std::optional<ArrayAttr> attr = op.getPrivateSyms();
958 for (
auto symbolRef : attr->getAsRange<SymbolRefAttr>()) {
969 std::optional<ArrayAttr> attr = op.getReductionSyms();
973 reductions.reserve(reductions.size() + op.getNumReductionVars());
974 for (
auto symbolRef : attr->getAsRange<SymbolRefAttr>()) {
975 reductions.push_back(
990 Operation *contextOp, std::optional<ArrayAttr> syms, StringRef opName,
994 out.reserve(out.size() + syms->size());
995 for (
auto sym : syms->getAsRange<SymbolRefAttr>()) {
1000 <<
"failed to resolve " << clauseName
1001 <<
" declare_reduction symbol " << sym.getRootReference() <<
" in "
1003 if (decl.getInitializerRegion().front().getNumArguments() != 1)
1005 <<
"not yet implemented: " << clauseName
1006 <<
" with two-argument initializer in " << opName;
1007 if (!decl.getCleanupRegion().empty())
1008 return contextOp->
emitError() <<
"not yet implemented: " << clauseName
1009 <<
" with cleanup region in " << opName;
1010 if (decl.getReductionRegion().empty())
1012 << clauseName <<
" declare_reduction is missing a combiner region";
1013 out.push_back(decl);
1024 Region ®ion, StringRef blockName, llvm::IRBuilderBase &builder,
1033 llvm::Instruction *potentialTerminator =
1034 builder.GetInsertBlock()->empty() ?
nullptr
1035 : &builder.GetInsertBlock()->back();
1037 if (potentialTerminator && potentialTerminator->isTerminator())
1038 potentialTerminator->removeFromParent();
1039 moduleTranslation.
mapBlock(®ion.
front(), builder.GetInsertBlock());
1042 region.
front(),
true, builder)))
1046 if (continuationBlockArgs)
1048 *continuationBlockArgs,
1055 if (potentialTerminator && potentialTerminator->isTerminator()) {
1056 llvm::BasicBlock *block = builder.GetInsertBlock();
1057 if (block->empty()) {
1063 potentialTerminator->insertInto(block, block->begin());
1065 potentialTerminator->insertAfter(&block->back());
1079 if (continuationBlockArgs)
1080 llvm::append_range(*continuationBlockArgs, phis);
1081 builder.SetInsertPoint(*continuationBlock,
1082 (*continuationBlock)->getFirstInsertionPt());
1089using OwningReductionGen =
1090 std::function<llvm::OpenMPIRBuilder::InsertPointOrErrorTy(
1091 llvm::OpenMPIRBuilder::InsertPointTy, llvm::Value *, llvm::Value *,
1093using OwningAtomicReductionGen =
1094 std::function<llvm::OpenMPIRBuilder::InsertPointOrErrorTy(
1095 llvm::OpenMPIRBuilder::InsertPointTy, llvm::Type *, llvm::Value *,
1097using OwningDataPtrPtrReductionGen =
1098 std::function<llvm::OpenMPIRBuilder::InsertPointOrErrorTy(
1099 llvm::OpenMPIRBuilder::InsertPointTy, llvm::Value *, llvm::Value *&)>;
1105static OwningReductionGen
1111 OwningReductionGen gen =
1112 [&, decl](llvm::OpenMPIRBuilder::InsertPointTy insertPoint,
1113 llvm::Value *
lhs, llvm::Value *
rhs,
1114 llvm::Value *&
result)
mutable
1115 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
1116 moduleTranslation.
mapValue(decl.getReductionLhsArg(),
lhs);
1117 moduleTranslation.
mapValue(decl.getReductionRhsArg(),
rhs);
1118 builder.restoreIP(insertPoint);
1121 "omp.reduction.nonatomic.body", builder,
1122 moduleTranslation, &phis)))
1123 return llvm::createStringError(
1124 "failed to inline `combiner` region of `omp.declare_reduction`");
1125 result = llvm::getSingleElement(phis);
1126 return builder.saveIP();
1135static OwningAtomicReductionGen
1137 llvm::IRBuilderBase &builder,
1139 if (decl.getAtomicReductionRegion().empty())
1140 return OwningAtomicReductionGen();
1146 [&, decl](llvm::OpenMPIRBuilder::InsertPointTy insertPoint, llvm::Type *,
1147 llvm::Value *
lhs, llvm::Value *
rhs)
mutable
1148 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
1149 moduleTranslation.
mapValue(decl.getAtomicReductionLhsArg(),
lhs);
1150 moduleTranslation.
mapValue(decl.getAtomicReductionRhsArg(),
rhs);
1151 builder.restoreIP(insertPoint);
1154 "omp.reduction.atomic.body", builder,
1155 moduleTranslation, &phis)))
1156 return llvm::createStringError(
1157 "failed to inline `atomic` region of `omp.declare_reduction`");
1158 assert(phis.empty());
1159 return builder.saveIP();
1168static OwningDataPtrPtrReductionGen
1171 if (!isByRef || decl.getDataPtrPtrRegion().empty())
1172 return OwningDataPtrPtrReductionGen();
1174 OwningDataPtrPtrReductionGen refDataPtrGen =
1175 [&, decl](llvm::OpenMPIRBuilder::InsertPointTy insertPoint,
1176 llvm::Value *byRefVal, llvm::Value *&
result)
mutable
1177 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
1178 moduleTranslation.
mapValue(decl.getDataPtrPtrRegionArg(), byRefVal);
1179 builder.restoreIP(insertPoint);
1182 "omp.data_ptr_ptr.body", builder,
1183 moduleTranslation, &phis)))
1184 return llvm::createStringError(
1185 "failed to inline `data_ptr_ptr` region of `omp.declare_reduction`");
1186 result = llvm::getSingleElement(phis);
1187 return builder.saveIP();
1190 return refDataPtrGen;
1197 auto orderedOp = cast<omp::OrderedOp>(opInst);
1202 omp::ClauseDepend dependType = *orderedOp.getDoacrossDependType();
1203 bool isDependSource = dependType == omp::ClauseDepend::dependsource;
1204 unsigned numLoops = *orderedOp.getDoacrossNumLoops();
1206 moduleTranslation.
lookupValues(orderedOp.getDoacrossDependVars());
1208 size_t indexVecValues = 0;
1209 while (indexVecValues < vecValues.size()) {
1211 storeValues.reserve(numLoops);
1212 for (
unsigned i = 0; i < numLoops; i++) {
1213 storeValues.push_back(vecValues[indexVecValues]);
1216 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
1218 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
1219 builder.restoreIP(moduleTranslation.
getOpenMPBuilder()->createOrderedDepend(
1220 ompLoc, allocaIP, numLoops, storeValues,
".cnt.addr", isDependSource));
1230 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1231 auto orderedRegionOp = cast<omp::OrderedRegionOp>(opInst);
1236 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
1239 auto ®ion = cast<omp::OrderedRegionOp>(opInst).getRegion();
1240 builder.restoreIP(codeGenIP);
1248 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
1250 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
1251 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
1253 ompLoc, bodyGenCB, finiCB, !orderedRegionOp.getParLevelSimd());
1258 builder.restoreIP(*afterIP);
1264struct DeferredStore {
1265 DeferredStore(llvm::Value *value, llvm::Value *address)
1266 : value(value), address(address) {}
1269 llvm::Value *address;
1276template <
typename T>
1279 llvm::IRBuilderBase &builder,
1281 const llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
1287 llvm::IRBuilderBase::InsertPointGuard guard(builder);
1288 builder.SetInsertPoint(allocaIP.getBlock()->getTerminator());
1294 deferredStores.reserve(op.getNumReductionVars());
1296 for (std::size_t i = 0; i < op.getNumReductionVars(); ++i) {
1297 Region &allocRegion = reductionDecls[i].getAllocRegion();
1299 if (allocRegion.
empty())
1304 builder, moduleTranslation, &phis)))
1305 return op.emitError(
1306 "failed to inline `alloc` region of `omp.declare_reduction`");
1308 assert(phis.size() == 1 &&
"expected one allocation to be yielded");
1309 builder.SetInsertPoint(allocaIP.getBlock()->getTerminator());
1313 llvm::Type *ptrTy = builder.getPtrTy();
1317 if (useDeviceSharedMem) {
1318 var = ompBuilder->createOMPAllocShared(builder, varTy);
1320 var = builder.CreateAlloca(varTy);
1321 var = builder.CreatePointerBitCastOrAddrSpaceCast(var, ptrTy);
1324 llvm::Value *castPhi =
1325 builder.CreatePointerBitCastOrAddrSpaceCast(phis[0], ptrTy);
1327 deferredStores.emplace_back(castPhi, var);
1329 privateReductionVariables[i] = var;
1330 moduleTranslation.
mapValue(reductionArgs[i], castPhi);
1331 reductionVariableMap.try_emplace(op.getReductionVars()[i], castPhi);
1333 assert(allocRegion.
empty() &&
1334 "allocaction is implicit for by-val reduction");
1336 llvm::Type *ptrTy = builder.getPtrTy();
1340 if (useDeviceSharedMem) {
1341 var = ompBuilder->createOMPAllocShared(builder, varTy);
1343 var = builder.CreateAlloca(varTy);
1344 var = builder.CreatePointerBitCastOrAddrSpaceCast(var, ptrTy);
1347 moduleTranslation.
mapValue(reductionArgs[i], var);
1348 privateReductionVariables[i] = var;
1349 reductionVariableMap.try_emplace(op.getReductionVars()[i], var);
1357template <
typename T>
1360 llvm::IRBuilderBase &builder,
1365 mlir::omp::DeclareReductionOp &reduction = reductionDecls[i];
1366 Region &initializerRegion = reduction.getInitializerRegion();
1369 mlir::Value mlirSource = loop.getReductionVars()[i];
1370 llvm::Value *llvmSource = moduleTranslation.
lookupValue(mlirSource);
1371 llvm::Value *origVal = llvmSource;
1373 if (!isa<LLVM::LLVMPointerType>(
1374 reduction.getInitializerMoldArg().getType()) &&
1375 isa<LLVM::LLVMPointerType>(mlirSource.
getType())) {
1378 reduction.getInitializerMoldArg().getType()),
1379 llvmSource,
"omp_orig");
1381 moduleTranslation.
mapValue(reduction.getInitializerMoldArg(), origVal);
1384 llvm::Value *allocation =
1385 reductionVariableMap.lookup(loop.getReductionVars()[i]);
1386 moduleTranslation.
mapValue(reduction.getInitializerAllocArg(), allocation);
1392 llvm::BasicBlock *block =
nullptr) {
1393 if (block ==
nullptr)
1394 block = builder.GetInsertBlock();
1396 if (!block->hasTerminator())
1397 builder.SetInsertPoint(block);
1399 builder.SetInsertPoint(block->getTerminator());
1407template <
typename OP>
1410 llvm::IRBuilderBase &builder,
1412 llvm::BasicBlock *latestAllocaBlock,
1418 if (op.getNumReductionVars() == 0)
1424 llvm::BasicBlock *initBlock = splitBB(builder,
true,
"omp.reduction.init");
1425 auto allocaIP = llvm::IRBuilderBase::InsertPoint(
1426 latestAllocaBlock, latestAllocaBlock->getTerminator()->getIterator());
1427 builder.restoreIP(allocaIP);
1430 for (
unsigned i = 0; i < op.getNumReductionVars(); ++i) {
1432 if (!reductionDecls[i].getAllocRegion().empty())
1440 if (useDeviceSharedMem)
1441 byRefVars[i] = ompBuilder->createOMPAllocShared(builder, varTy);
1443 byRefVars[i] = builder.CreateAlloca(varTy);
1451 for (
auto [data, addr] : deferredStores)
1452 builder.CreateStore(data, addr);
1457 for (
unsigned i = 0; i < op.getNumReductionVars(); ++i) {
1462 reductionVariableMap, i);
1470 "omp.reduction.neutral", builder,
1471 moduleTranslation, &phis)))
1474 assert(phis.size() == 1 &&
"expected one value to be yielded from the "
1475 "reduction neutral element declaration region");
1480 if (!reductionDecls[i].getAllocRegion().empty())
1489 builder.CreateStore(phis[0], byRefVars[i]);
1491 privateReductionVariables[i] = byRefVars[i];
1492 moduleTranslation.
mapValue(reductionArgs[i], phis[0]);
1493 reductionVariableMap.try_emplace(op.getReductionVars()[i], phis[0]);
1496 builder.CreateStore(phis[0], privateReductionVariables[i]);
1503 moduleTranslation.
forgetMapping(reductionDecls[i].getInitializerRegion());
1510template <
typename T>
1511static void collectReductionInfo(
1512 T loop, llvm::IRBuilderBase &builder,
1521 unsigned numReductions = loop.getNumReductionVars();
1523 for (
unsigned i = 0; i < numReductions; ++i) {
1526 owningAtomicReductionGens.push_back(
1529 reductionDecls[i], builder, moduleTranslation, isByRef[i]));
1533 reductionInfos.reserve(numReductions);
1534 for (
unsigned i = 0; i < numReductions; ++i) {
1535 llvm::OpenMPIRBuilder::ReductionGenAtomicCBTy
atomicGen =
nullptr;
1536 if (owningAtomicReductionGens[i])
1537 atomicGen = owningAtomicReductionGens[i];
1538 llvm::Value *variable =
1539 moduleTranslation.
lookupValue(loop.getReductionVars()[i]);
1542 if (
auto alloca = mlir::dyn_cast<LLVM::AllocaOp>(op)) {
1543 allocatedType = alloca.getElemType();
1550 reductionInfos.push_back(
1552 privateReductionVariables[i],
1553 llvm::OpenMPIRBuilder::EvalKind::Scalar,
1557 allocatedType ? moduleTranslation.
convertType(allocatedType) :
nullptr,
1558 reductionDecls[i].getByrefElementType()
1560 *reductionDecls[i].getByrefElementType())
1570 llvm::IRBuilderBase &builder, StringRef regionName,
1571 bool shouldLoadCleanupRegionArg =
true) {
1572 for (
auto [i, cleanupRegion] : llvm::enumerate(cleanupRegions)) {
1573 if (cleanupRegion->empty())
1579 llvm::Instruction *potentialTerminator =
1580 builder.GetInsertBlock()->empty() ?
nullptr
1581 : &builder.GetInsertBlock()->back();
1582 if (potentialTerminator && potentialTerminator->isTerminator())
1583 builder.SetInsertPoint(potentialTerminator);
1584 llvm::Value *privateVarValue =
1585 shouldLoadCleanupRegionArg
1586 ? builder.CreateLoad(
1588 privateVariables[i])
1589 : privateVariables[i];
1594 moduleTranslation)))
1607 OP op, llvm::IRBuilderBase &builder,
1609 llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
1612 bool isNowait =
false,
bool isTeamsReduction =
false) {
1614 if (op.getNumReductionVars() == 0)
1626 collectReductionInfo(op, builder, moduleTranslation, reductionDecls,
1628 owningReductionGenRefDataPtrGens,
1629 privateReductionVariables, reductionInfos, isByRef);
1634 llvm::UnreachableInst *tempTerminator = builder.CreateUnreachable();
1635 builder.SetInsertPoint(tempTerminator);
1636 llvm::OpenMPIRBuilder::InsertPointOrErrorTy contInsertPoint =
1637 ompBuilder->createReductions(builder.saveIP(), allocaIP, reductionInfos,
1638 isByRef, isNowait, isTeamsReduction);
1643 if (!contInsertPoint->getBlock())
1644 return op->emitOpError() <<
"failed to convert reductions";
1646 llvm::OpenMPIRBuilder::InsertPointTy afterIP = *contInsertPoint;
1647 if (!isTeamsReduction) {
1648 llvm::OpenMPIRBuilder::InsertPointOrErrorTy barrierIP =
1649 ompBuilder->createBarrier(*contInsertPoint, llvm::omp::OMPD_for);
1653 afterIP = *barrierIP;
1656 tempTerminator->eraseFromParent();
1657 builder.restoreIP(afterIP);
1661 llvm::transform(reductionDecls, std::back_inserter(reductionRegions),
1662 [](omp::DeclareReductionOp reductionDecl) {
1663 return &reductionDecl.getCleanupRegion();
1666 reductionRegions, privateReductionVariables, moduleTranslation, builder,
1667 "omp.reduction.cleanup");
1670 if (useDeviceSharedMem) {
1671 for (
auto [var, reductionDecl] :
1672 llvm::zip_equal(privateReductionVariables, reductionDecls))
1673 ompBuilder->createOMPFreeShared(
1674 builder, var, moduleTranslation.
convertType(reductionDecl.getType()));
1687template <
typename OP>
1691 llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
1696 if (op.getNumReductionVars() == 0)
1702 allocaIP, reductionDecls,
1703 privateReductionVariables, reductionVariableMap,
1704 deferredStores, isByRef)))
1707 return initReductionVars(op, reductionArgs, builder, moduleTranslation,
1708 allocaIP.getBlock(), reductionDecls,
1709 privateReductionVariables, reductionVariableMap,
1710 isByRef, deferredStores);
1724 if (mappedPrivateVars ==
nullptr || !mappedPrivateVars->contains(privateVar))
1727 Value blockArg = (*mappedPrivateVars)[privateVar];
1730 assert(isa<LLVM::LLVMPointerType>(blockArgType) &&
1731 "A block argument corresponding to a mapped var should have "
1734 if (privVarType == blockArgType)
1741 if (!isa<LLVM::LLVMPointerType>(privVarType))
1742 return builder.CreateLoad(moduleTranslation.
convertType(privVarType),
1759 llvm::Type *regionArgType =
1761 if (regionArgType->isPointerTy() || !value->getType()->isPointerTy())
1764 return builder.CreateLoad(regionArgType, value);
1774 omp::PrivateClauseOp &privDecl, llvm::Value *nonPrivateVar,
1776 llvm::BasicBlock *privInitBlock,
1778 Region &initRegion = privDecl.getInitRegion();
1779 if (initRegion.
empty())
1780 return llvmPrivateVar;
1782 assert(nonPrivateVar);
1783 moduleTranslation.
mapValue(privDecl.getInitMoldArg(), nonPrivateVar);
1784 moduleTranslation.
mapValue(privDecl.getInitPrivateArg(), llvmPrivateVar);
1789 moduleTranslation, &phis)))
1790 return llvm::createStringError(
1791 "failed to inline `init` region of `omp.private`");
1793 assert(phis.size() == 1 &&
"expected one allocation to be yielded");
1810 llvm::Value *llvmPrivateVar, llvm::BasicBlock *privInitBlock,
1813 builder, moduleTranslation, privDecl,
1816 blockArg, llvmPrivateVar, privInitBlock, mappedPrivateVars);
1825 return llvm::Error::success();
1827 llvm::BasicBlock *privInitBlock = splitBB(builder,
true,
"omp.private.init");
1830 for (
auto [idx, zip] : llvm::enumerate(llvm::zip_equal(
1833 auto [privDecl, mlirPrivVar, blockArg, llvmPrivateVar] = zip;
1835 builder, moduleTranslation, privDecl, mlirPrivVar, blockArg,
1836 llvmPrivateVar, privInitBlock, mappedPrivateVars);
1839 return privVarOrErr.takeError();
1841 llvmPrivateVar = privVarOrErr.get();
1842 moduleTranslation.
mapValue(blockArg, llvmPrivateVar);
1847 return llvm::Error::success();
1853template <
typename T>
1858 const llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
1861 llvm::Instruction *allocaTerminator = allocaIP.getBlock()->getTerminator();
1862 splitBB(llvm::OpenMPIRBuilder::InsertPointTy(allocaIP.getBlock(),
1863 allocaTerminator->getIterator()),
1864 true, allocaTerminator->getStableDebugLoc(),
1865 "omp.region.after_alloca");
1867 llvm::IRBuilderBase::InsertPointGuard guard(builder);
1869 allocaTerminator = allocaIP.getBlock()->getTerminator();
1870 builder.SetInsertPoint(allocaTerminator);
1872 assert(allocaTerminator->getNumSuccessors() == 1 &&
1873 "This is an unconditional branch created by splitBB");
1875 llvm::DataLayout dataLayout = builder.GetInsertBlock()->getDataLayout();
1876 llvm::BasicBlock *afterAllocas = allocaTerminator->getSuccessor(0);
1880 unsigned int allocaAS =
1881 moduleTranslation.
getLLVMModule()->getDataLayout().getAllocaAddrSpace();
1884 .getProgramAddressSpace();
1886 for (
auto [privDecl, mlirPrivVar, blockArg] :
1889 llvm::Type *llvmAllocType =
1890 moduleTranslation.
convertType(privDecl.getType());
1891 builder.SetInsertPoint(allocaIP.getBlock()->getTerminator());
1892 llvm::Value *llvmPrivateVar =
nullptr;
1894 llvmPrivateVar = ompBuilder->createOMPAllocShared(builder, llvmAllocType);
1896 llvmPrivateVar = builder.CreateAlloca(
1897 llvmAllocType,
nullptr,
"omp.private.alloc");
1898 if (allocaAS != defaultAS)
1899 llvmPrivateVar = builder.CreateAddrSpaceCast(
1900 llvmPrivateVar, builder.getPtrTy(defaultAS));
1903 privateVarsInfo.
llvmVars.push_back(llvmPrivateVar);
1906 return afterAllocas;
1914 if (mlir::isa<omp::SingleOp, omp::CriticalOp>(parent))
1923 if (mlir::isa<omp::ParallelOp>(parent))
1937 bool needsFirstprivate =
1938 llvm::any_of(privateDecls, [](omp::PrivateClauseOp &privOp) {
1939 return privOp.getDataSharingType() ==
1940 omp::DataSharingClauseType::FirstPrivate;
1943 if (!needsFirstprivate)
1946 llvm::BasicBlock *copyBlock =
1947 splitBB(builder,
true,
"omp.private.copy");
1950 for (
auto [decl, moldVar, llvmVar] :
1951 llvm::zip_equal(privateDecls, moldVars, llvmPrivateVars)) {
1952 if (decl.getDataSharingType() != omp::DataSharingClauseType::FirstPrivate)
1956 Region ©Region = decl.getCopyRegion();
1959 builder, moduleTranslation, decl.getCopyMoldArg(), moldVar);
1961 builder, moduleTranslation, decl.getCopyPrivateArg(), llvmVar);
1963 moduleTranslation.
mapValue(decl.getCopyMoldArg(), copyMoldVar);
1966 moduleTranslation.
mapValue(decl.getCopyPrivateArg(), copyPrivateVar);
1970 moduleTranslation)))
1971 return decl.emitError(
"failed to inline `copy` region of `omp.private`");
1985 llvm::OpenMPIRBuilder::InsertPointOrErrorTy res =
1986 ompBuilder->createBarrier(builder.saveIP(), llvm::omp::OMPD_barrier);
2002 llvm::transform(mlirPrivateVars, moldVars.begin(), [&](
mlir::Value mlirVar) {
2004 llvm::Value *moldVar = findAssociatedValue(
2005 mlirVar, builder, moduleTranslation, mappedPrivateVars);
2010 llvmPrivateVars, privateDecls, insertBarrier,
2014template <
typename T>
2022 std::back_inserter(privateCleanupRegions),
2023 [](omp::PrivateClauseOp privatizer) {
2024 return &privatizer.getDeallocRegion();
2028 privateVarsInfo.
llvmVars, moduleTranslation,
2029 builder,
"omp.private.dealloc",
2031 return mlir::emitError(loc,
"failed to inline `dealloc` region of an "
2032 "`omp.private` op in");
2036 for (
auto [privDecl, llvmPrivVar, blockArg] :
2040 ompBuilder->createOMPFreeShared(
2041 builder, llvmPrivVar,
2042 moduleTranslation.
convertType(privDecl.getType()));
2056 if (mlir::isa<omp::CancelOp, omp::CancellationPointOp>(child))
2073 llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder::InsertPointTy allocaIP,
2075 bool isWorksharing =
false);
2083 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2084 using StorableBodyGenCallbackTy =
2085 llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
2087 auto sectionsOp = cast<omp::SectionsOp>(opInst);
2093 assert(isByRef.size() == sectionsOp.getNumReductionVars());
2097 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
2101 sectionsOp.getNumReductionVars());
2105 cast<omp::BlockArgOpenMPOpInterface>(opInst).getReductionBlockArgs();
2108 sectionsOp, reductionArgs, builder, moduleTranslation, allocaIP,
2109 reductionDecls, privateReductionVariables, reductionVariableMap,
2113 bool isTaskReductionMod =
2114 sectionsOp.getReductionMod() == omp::ReductionModifier::task &&
2115 sectionsOp.getNumReductionVars() > 0;
2120 auto sectionOp = dyn_cast<omp::SectionOp>(op);
2124 Region ®ion = sectionOp.getRegion();
2125 auto sectionCB = [§ionsOp, ®ion, &builder, &moduleTranslation](
2126 InsertPointTy allocaIP, InsertPointTy codeGenIP,
2128 builder.restoreIP(codeGenIP);
2135 sectionsOp.getRegion().getNumArguments());
2136 for (
auto [sectionsArg, sectionArg] : llvm::zip_equal(
2137 sectionsOp.getRegion().getArguments(), region.
getArguments())) {
2138 llvm::Value *llvmVal = moduleTranslation.
lookupValue(sectionsArg);
2140 moduleTranslation.
mapValue(sectionArg, llvmVal);
2147 sectionCBs.push_back(sectionCB);
2153 if (sectionCBs.empty())
2161 if (isTaskReductionMod &&
2163 "__omp_taskred_mod_", builder, allocaIP,
2164 moduleTranslation,
true,
2166 return sectionsOp.emitError(
2167 "failed to emit task reduction modifier initialization");
2169 assert(isa<omp::SectionOp>(*sectionsOp.getRegion().op_begin()));
2174 auto privCB = [&](InsertPointTy, InsertPointTy codeGenIP, llvm::Value &,
2175 llvm::Value &vPtr, llvm::Value *&replacementValue)
2176 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
2177 replacementValue = &vPtr;
2183 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
2187 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2188 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2190 ompLoc, allocaIP, sectionCBs, privCB, finiCB, isCancellable,
2191 sectionsOp.getNowait());
2196 builder.restoreIP(*afterIP);
2199 if (isTaskReductionMod)
2205 sectionsOp, builder, moduleTranslation, allocaIP, reductionDecls,
2206 privateReductionVariables, isByRef, sectionsOp.getNowait());
2213 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2220 assert(isByRef.size() == scopeOp.getNumReductionVars());
2229 scopeOp.getNumReductionVars());
2233 cast<omp::BlockArgOpenMPOpInterface>(*scopeOp).getReductionBlockArgs();
2237 scopeOp, builder, moduleTranslation, privateVarsInfo, allocaIP);
2242 scopeOp, reductionArgs, builder, moduleTranslation, allocaIP,
2243 reductionDecls, privateReductionVariables, reductionVariableMap,
2248 [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
2250 builder.restoreIP(codeGenIP);
2256 return llvm::make_error<PreviouslyReportedError>();
2259 scopeOp, builder, moduleTranslation, privateVarsInfo.
mlirVars,
2261 scopeOp.getPrivateNeedsBarrier())))
2262 return llvm::make_error<PreviouslyReportedError>();
2269 auto finiCB = [&](InsertPointTy codeGenIP) -> llvm::Error {
2270 InsertPointTy oldIP = builder.saveIP();
2271 builder.restoreIP(codeGenIP);
2273 scopeOp.getLoc(), privateVarsInfo)))
2274 return llvm::make_error<PreviouslyReportedError>();
2275 builder.restoreIP(oldIP);
2276 return llvm::Error::success();
2279 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2280 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2281 ompBuilder->createScope(ompLoc, bodyCB, finiCB, scopeOp.getNowait());
2286 builder.restoreIP(*afterIP);
2290 scopeOp, builder, moduleTranslation, allocaIP, reductionDecls,
2291 privateReductionVariables, isByRef, scopeOp.getNowait(),
2299 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2300 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2305 auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
2307 builder.restoreIP(codegenIP);
2309 builder, moduleTranslation)
2312 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
2316 std::optional<ArrayAttr> cpFuncs = singleOp.getCopyprivateSyms();
2319 for (
size_t i = 0, e = cpVars.size(); i < e; ++i) {
2320 llvmCPVars.push_back(moduleTranslation.
lookupValue(cpVars[i]));
2322 singleOp, cast<SymbolRefAttr>((*cpFuncs)[i]));
2323 llvmCPFuncs.push_back(
2327 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2329 ompLoc, bodyCB, finiCB, singleOp.getNowait(), llvmCPVars,
2335 builder.restoreIP(*afterIP);
2339static omp::DistributeOp
2343 omp::DistributeOp distOp;
2344 WalkResult walk = teamsOp.getRegion().walk([&](omp::DistributeOp op) {
2350 if (walk.wasInterrupted() || !distOp)
2354 llvm::cast<mlir::omp::BlockArgOpenMPOpInterface>(teamsOp.getOperation());
2358 for (
auto ra : iface.getReductionBlockArgs())
2359 for (
auto &use : ra.getUses()) {
2360 auto *useOp = use.getOwner();
2362 if (mlir::isa<LLVM::DbgDeclareOp, LLVM::DbgValueOp>(useOp)) {
2363 debugUses.push_back(useOp);
2366 if (!distOp->isProperAncestor(useOp))
2373 for (
auto *use : debugUses)
2382 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2387 unsigned numReductionVars = op.getNumReductionVars();
2391 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
2397 if (doTeamsReduction) {
2398 isByRef =
getIsByRef(op.getReductionByref());
2400 assert(isByRef.size() == op.getNumReductionVars());
2403 llvm::cast<omp::BlockArgOpenMPOpInterface>(*op).getReductionBlockArgs();
2408 op, reductionArgs, builder, moduleTranslation, allocaIP,
2409 reductionDecls, privateReductionVariables, reductionVariableMap,
2414 auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
2417 moduleTranslation, allocaIP, deallocBlocks);
2418 builder.restoreIP(codegenIP);
2424 llvm::Value *numTeamsLower =
nullptr;
2425 if (
Value numTeamsLowerVar = op.getNumTeamsLower())
2426 numTeamsLower = moduleTranslation.
lookupValue(numTeamsLowerVar);
2428 llvm::Value *numTeamsUpper =
nullptr;
2429 if (!op.getNumTeamsUpperVars().empty())
2430 numTeamsUpper = moduleTranslation.
lookupValue(op.getNumTeams(0));
2432 llvm::Value *threadLimit =
nullptr;
2433 if (!op.getThreadLimitVars().empty())
2434 threadLimit = moduleTranslation.
lookupValue(op.getThreadLimit(0));
2436 llvm::Value *ifExpr =
nullptr;
2437 if (
Value ifVar = op.getIfExpr())
2440 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2441 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2443 ompLoc, bodyCB, numTeamsLower, numTeamsUpper, threadLimit, ifExpr);
2448 builder.restoreIP(*afterIP);
2449 if (doTeamsReduction) {
2452 op, builder, moduleTranslation, allocaIP, reductionDecls,
2453 privateReductionVariables, isByRef,
2459static llvm::omp::RTLDependenceKindTy
2462 case mlir::omp::ClauseTaskDepend::taskdependin:
2463 return llvm::omp::RTLDependenceKindTy::DepIn;
2467 case mlir::omp::ClauseTaskDepend::taskdependout:
2468 case mlir::omp::ClauseTaskDepend::taskdependinout:
2469 return llvm::omp::RTLDependenceKindTy::DepInOut;
2470 case mlir::omp::ClauseTaskDepend::taskdependmutexinoutset:
2471 return llvm::omp::RTLDependenceKindTy::DepMutexInOutSet;
2472 case mlir::omp::ClauseTaskDepend::taskdependinoutset:
2473 return llvm::omp::RTLDependenceKindTy::DepInOutSet;
2475 llvm_unreachable(
"unhandled depend kind");
2479 std::optional<ArrayAttr> dependKinds,
OperandRange dependVars,
2482 if (dependVars.empty())
2484 for (
auto dep : llvm::zip(dependVars, dependKinds->getValue())) {
2486 cast<mlir::omp::ClauseTaskDependAttr>(std::get<1>(dep)).getValue();
2488 llvm::Value *depVal = moduleTranslation.
lookupValue(std::get<0>(dep));
2489 llvm::OpenMPIRBuilder::DependData dd(type, depVal->getType(), depVal);
2490 dds.emplace_back(dd);
2502 llvm::IRBuilderBase &llvmBuilder, llvm::OpenMPIRBuilder &ompBuilder,
2504 auto finiCB = [&](llvm::OpenMPIRBuilder::InsertPointTy ip) -> llvm::Error {
2505 llvm::IRBuilderBase::InsertPointGuard guard(llvmBuilder);
2509 llvmBuilder.restoreIP(ip);
2515 cancelTerminators.push_back(llvmBuilder.CreateBr(ip.getBlock()));
2516 return llvm::Error::success();
2521 ompBuilder.pushFinalizationCB(
2531 llvm::OpenMPIRBuilder &ompBuilder,
2532 const llvm::OpenMPIRBuilder::InsertPointTy &afterIP) {
2533 ompBuilder.popFinalizationCB();
2534 llvm::BasicBlock *constructFini = afterIP.getBlock()->getSinglePredecessor();
2535 for (llvm::UncondBrInst *cancelBranch : cancelTerminators)
2536 cancelBranch->setSuccessor(constructFini);
2542class TaskContextStructManager {
2544 TaskContextStructManager(llvm::IRBuilderBase &builder,
2545 LLVM::ModuleTranslation &moduleTranslation,
2546 MutableArrayRef<omp::PrivateClauseOp> privateDecls)
2547 : builder{builder}, moduleTranslation{moduleTranslation},
2548 privateDecls{privateDecls} {}
2554 void generateTaskContextStruct();
2560 void createGEPsToPrivateVars();
2566 SmallVector<llvm::Value *>
2567 createGEPsToPrivateVars(llvm::Value *altStructPtr)
const;
2570 void freeStructPtr();
2572 MutableArrayRef<llvm::Value *> getLLVMPrivateVarGEPs() {
2573 return llvmPrivateVarGEPs;
2576 llvm::Value *getStructPtr() {
return structPtr; }
2579 llvm::IRBuilderBase &builder;
2580 LLVM::ModuleTranslation &moduleTranslation;
2581 MutableArrayRef<omp::PrivateClauseOp> privateDecls;
2584 SmallVector<llvm::Type *> privateVarTypes;
2588 SmallVector<llvm::Value *> llvmPrivateVarGEPs;
2591 llvm::Value *structPtr =
nullptr;
2593 llvm::Type *structTy =
nullptr;
2604 llvm::SmallVector<llvm::Value *> lowerBounds;
2605 llvm::SmallVector<llvm::Value *> upperBounds;
2606 llvm::SmallVector<llvm::Value *> steps;
2607 llvm::SmallVector<llvm::Value *> trips;
2609 llvm::Value *totalTrips;
2611 llvm::Value *lookUpAsI64(mlir::Value val,
const LLVM::ModuleTranslation &mt,
2612 llvm::IRBuilderBase &builder) {
2616 if (v->getType()->isIntegerTy(64))
2618 if (v->getType()->isIntegerTy())
2619 return builder.CreateSExtOrTrunc(v, builder.getInt64Ty());
2624 IteratorInfo(mlir::omp::IteratorOp itersOp,
2625 mlir::LLVM::ModuleTranslation &moduleTranslation,
2626 llvm::IRBuilderBase &builder) {
2627 dims = itersOp.getLoopLowerBounds().size();
2628 lowerBounds.resize(dims);
2629 upperBounds.resize(dims);
2633 for (
unsigned d = 0; d < dims; ++d) {
2634 llvm::Value *lb = lookUpAsI64(itersOp.getLoopLowerBounds()[d],
2635 moduleTranslation, builder);
2636 llvm::Value *ub = lookUpAsI64(itersOp.getLoopUpperBounds()[d],
2637 moduleTranslation, builder);
2639 lookUpAsI64(itersOp.getLoopSteps()[d], moduleTranslation, builder);
2640 assert(lb && ub && st &&
2641 "Expect lowerBounds, upperBounds, and steps in IteratorOp");
2642 assert((!llvm::isa<llvm::ConstantInt>(st) ||
2643 !llvm::cast<llvm::ConstantInt>(st)->isZero()) &&
2644 "Expect non-zero step in IteratorOp");
2646 lowerBounds[d] = lb;
2647 upperBounds[d] = ub;
2651 llvm::Value *diff = builder.CreateSub(ub, lb);
2652 llvm::Value *
div = builder.CreateSDiv(diff, st);
2653 trips[d] = builder.CreateAdd(
2654 div, llvm::ConstantInt::get(builder.getInt64Ty(), 1));
2657 totalTrips = llvm::ConstantInt::get(builder.getInt64Ty(), 1);
2658 for (
unsigned d = 0; d < dims; ++d)
2659 totalTrips = builder.CreateMul(totalTrips, trips[d]);
2662 unsigned getDims()
const {
return dims; }
2663 llvm::ArrayRef<llvm::Value *> getLowerBounds()
const {
return lowerBounds; }
2664 llvm::ArrayRef<llvm::Value *> getUpperBounds()
const {
return upperBounds; }
2665 llvm::ArrayRef<llvm::Value *> getSteps()
const {
return steps; }
2666 llvm::ArrayRef<llvm::Value *> getTrips()
const {
return trips; }
2667 llvm::Value *getTotalTrips()
const {
return totalTrips; }
2672void TaskContextStructManager::generateTaskContextStruct() {
2673 if (privateDecls.empty())
2675 privateVarTypes.reserve(privateDecls.size());
2677 for (omp::PrivateClauseOp &privOp : privateDecls) {
2680 if (!privOp.readsFromMold())
2682 Type mlirType = privOp.getType();
2683 privateVarTypes.push_back(moduleTranslation.
convertType(mlirType));
2686 if (privateVarTypes.empty())
2689 structTy = llvm::StructType::get(moduleTranslation.
getLLVMContext(),
2692 llvm::DataLayout dataLayout =
2693 builder.GetInsertBlock()->getModule()->getDataLayout();
2694 llvm::Type *intPtrTy = builder.getIntPtrTy(dataLayout);
2695 llvm::Constant *allocSize = llvm::ConstantExpr::getSizeOf(structTy);
2698 structPtr = builder.CreateMalloc(intPtrTy, structTy, allocSize,
2700 "omp.task.context_ptr");
2703SmallVector<llvm::Value *> TaskContextStructManager::createGEPsToPrivateVars(
2704 llvm::Value *altStructPtr)
const {
2705 SmallVector<llvm::Value *> ret;
2708 ret.reserve(privateDecls.size());
2709 llvm::Value *zero = builder.getInt32(0);
2711 for (
auto privDecl : privateDecls) {
2712 if (!privDecl.readsFromMold()) {
2714 ret.push_back(
nullptr);
2717 llvm::Value *iVal = builder.getInt32(i);
2718 llvm::Value *gep = builder.CreateGEP(structTy, altStructPtr, {zero, iVal});
2725void TaskContextStructManager::createGEPsToPrivateVars() {
2727 assert(privateVarTypes.empty());
2731 llvmPrivateVarGEPs = createGEPsToPrivateVars(structPtr);
2734void TaskContextStructManager::freeStructPtr() {
2738 llvm::IRBuilderBase::InsertPointGuard guard{builder};
2740 builder.SetInsertPoint(builder.GetInsertBlock()->getTerminator());
2741 builder.CreateFree(structPtr);
2745 llvm::OpenMPIRBuilder &ompBuilder,
2746 llvm::Value *affinityList, llvm::Value *
index,
2747 llvm::Value *addr, llvm::Value *len) {
2748 llvm::StructType *kmpTaskAffinityInfoTy =
2749 ompBuilder.getKmpTaskAffinityInfoTy();
2750 llvm::Value *entry = builder.CreateInBoundsGEP(
2751 kmpTaskAffinityInfoTy, affinityList,
index,
"omp.affinity.entry");
2753 addr = builder.CreatePtrToInt(addr, kmpTaskAffinityInfoTy->getElementType(0));
2754 len = builder.CreateIntCast(len, kmpTaskAffinityInfoTy->getElementType(1),
2756 llvm::Value *flags = builder.getInt32(0);
2758 builder.CreateStore(addr,
2759 builder.CreateStructGEP(kmpTaskAffinityInfoTy, entry, 0));
2760 builder.CreateStore(len,
2761 builder.CreateStructGEP(kmpTaskAffinityInfoTy, entry, 1));
2762 builder.CreateStore(flags,
2763 builder.CreateStructGEP(kmpTaskAffinityInfoTy, entry, 2));
2767 llvm::IRBuilderBase &builder,
2769 llvm::Value *affinityList) {
2770 for (
auto [i, affinityVar] : llvm::enumerate(affinityVars)) {
2771 auto entryOp = affinityVar.getDefiningOp<mlir::omp::AffinityEntryOp>();
2772 assert(entryOp &&
"affinity item must be omp.affinity_entry");
2774 llvm::Value *addr = moduleTranslation.
lookupValue(entryOp.getAddr());
2775 llvm::Value *len = moduleTranslation.
lookupValue(entryOp.getLen());
2776 assert(addr && len &&
"expect affinity addr and len to be non-null");
2778 affinityList, builder.getInt64(i), addr, len);
2782static mlir::LogicalResult
2785 llvm::IRBuilderBase &builder,
2787 llvm::Value *tmp = linearIV;
2788 for (
int d = (
int)iterInfo.getDims() - 1; d >= 0; --d) {
2789 llvm::Value *trip = iterInfo.getTrips()[d];
2791 llvm::Value *idx = builder.CreateURem(tmp, trip);
2793 tmp = builder.CreateUDiv(tmp, trip);
2796 llvm::Value *physIV = builder.CreateAdd(
2797 iterInfo.getLowerBounds()[d],
2798 builder.CreateMul(idx, iterInfo.getSteps()[d]),
"omp.it.phys_iv");
2804 moduleTranslation.
mapBlock(&iteratorRegionBlock, builder.GetInsertBlock());
2805 if (mlir::failed(moduleTranslation.
convertBlock(iteratorRegionBlock,
2808 return mlir::failure();
2810 return mlir::success();
2816static mlir::LogicalResult
2819 IteratorInfo &iterInfo, llvm::StringRef loopName,
2824 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
2826 auto bodyGen = [&](llvm::OpenMPIRBuilder::InsertPointTy bodyIP,
2827 llvm::Value *linearIV) -> llvm::Error {
2828 llvm::IRBuilderBase::InsertPointGuard guard(builder);
2829 builder.restoreIP(bodyIP);
2832 builder, moduleTranslation))) {
2833 return llvm::make_error<llvm::StringError>(
2834 "failed to convert iterator region", llvm::inconvertibleErrorCode());
2838 mlir::dyn_cast<mlir::omp::YieldOp>(iteratorRegionBlock.
getTerminator());
2839 assert(yield && yield.getResults().size() == 1 &&
2840 "expect omp.yield in iterator region to have one result");
2842 genStoreEntry(linearIV, yield);
2848 return llvm::Error::success();
2851 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2853 loc, iterInfo.getTotalTrips(), bodyGen, loopName);
2857 builder.restoreIP(*afterIP);
2859 return mlir::success();
2862static mlir::LogicalResult
2865 llvm::OpenMPIRBuilder::AffinityData &ad) {
2867 if (taskOp.getAffinityVars().empty() && taskOp.getIterated().empty()) {
2870 return mlir::success();
2874 llvm::StructType *kmpTaskAffinityInfoTy =
2877 auto allocateAffinityList = [&](llvm::Value *count) -> llvm::Value * {
2878 llvm::IRBuilderBase::InsertPointGuard guard(builder);
2879 if (llvm::isa<llvm::Constant>(count) || llvm::isa<llvm::Argument>(count))
2881 return builder.CreateAlloca(kmpTaskAffinityInfoTy, count,
2882 "omp.affinity_list");
2885 auto createAffinity =
2886 [&](llvm::Value *count,
2887 llvm::Value *info) -> llvm::OpenMPIRBuilder::AffinityData {
2888 llvm::OpenMPIRBuilder::AffinityData ad{};
2889 ad.Count = builder.CreateTrunc(count, builder.getInt32Ty());
2891 builder.CreatePointerBitCastOrAddrSpaceCast(info, builder.getPtrTy(0));
2895 if (!taskOp.getAffinityVars().empty()) {
2896 llvm::Value *count = llvm::ConstantInt::get(
2897 builder.getInt64Ty(), taskOp.getAffinityVars().size());
2898 llvm::Value *list = allocateAffinityList(count);
2901 ads.emplace_back(createAffinity(count, list));
2904 if (!taskOp.getIterated().empty()) {
2905 for (
auto [i, iter] : llvm::enumerate(taskOp.getIterated())) {
2906 auto itersOp = iter.getDefiningOp<omp::IteratorOp>();
2907 assert(itersOp &&
"iterated value must be defined by omp.iterator");
2908 IteratorInfo iterInfo(itersOp, moduleTranslation, builder);
2909 llvm::Value *affList = allocateAffinityList(iterInfo.getTotalTrips());
2911 itersOp, builder, moduleTranslation, iterInfo,
"iterator",
2912 [&](llvm::Value *linearIV, mlir::omp::YieldOp yield) {
2913 auto entryOp = yield.getResults()[0]
2914 .getDefiningOp<mlir::omp::AffinityEntryOp>();
2915 assert(entryOp &&
"expect yield produce an affinity entry");
2922 affList, linearIV, addr, len);
2924 return llvm::failure();
2925 ads.emplace_back(createAffinity(iterInfo.getTotalTrips(), affList));
2929 llvm::Value *totalAffinityCount = builder.getInt32(0);
2930 for (
const auto &affinity : ads)
2931 totalAffinityCount = builder.CreateAdd(
2933 builder.CreateIntCast(affinity.Count, builder.getInt32Ty(),
2936 llvm::Value *affinityInfo = ads.front().Info;
2937 if (ads.size() > 1) {
2938 llvm::StructType *kmpTaskAffinityInfoTy =
2940 llvm::Value *affinityInfoElemSize = builder.getInt64(
2941 moduleTranslation.
getLLVMModule()->getDataLayout().getTypeAllocSize(
2942 kmpTaskAffinityInfoTy));
2944 llvm::Value *packedAffinityInfo = allocateAffinityList(totalAffinityCount);
2945 llvm::Value *packedAffinityInfoOffset = builder.getInt32(0);
2946 for (
const auto &affinity : ads) {
2947 llvm::Value *affinityCount = builder.CreateIntCast(
2948 affinity.Count, builder.getInt32Ty(),
false);
2949 llvm::Value *affinityCountInt64 = builder.CreateIntCast(
2950 affinityCount, builder.getInt64Ty(),
false);
2951 llvm::Value *affinityInfoSize =
2952 builder.CreateMul(affinityCountInt64, affinityInfoElemSize);
2954 llvm::Value *packedAffinityInfoIndex = builder.CreateIntCast(
2955 packedAffinityInfoOffset, kmpTaskAffinityInfoTy->getElementType(0),
2957 packedAffinityInfoIndex = builder.CreateInBoundsGEP(
2958 kmpTaskAffinityInfoTy, packedAffinityInfo, packedAffinityInfoIndex);
2960 builder.CreateMemCpy(
2961 packedAffinityInfoIndex, llvm::Align(1),
2962 builder.CreatePointerBitCastOrAddrSpaceCast(
2963 affinity.Info, builder.getPtrTy(packedAffinityInfoIndex->getType()
2964 ->getPointerAddressSpace())),
2965 llvm::Align(1), affinityInfoSize);
2967 packedAffinityInfoOffset =
2968 builder.CreateAdd(packedAffinityInfoOffset, affinityCount);
2971 affinityInfo = packedAffinityInfo;
2974 ad.Count = totalAffinityCount;
2975 ad.Info = affinityInfo;
2977 return mlir::success();
2983static mlir::LogicalResult
2986 std::optional<ArrayAttr> dependIteratedKinds,
2987 llvm::IRBuilderBase &builder,
2989 llvm::OpenMPIRBuilder::DependenciesInfo &taskDeps) {
2990 if (dependIterated.empty()) {
2993 return mlir::success();
2997 llvm::Type *dependInfoTy = ompBuilder.DependInfo;
2998 unsigned numLocator = dependVars.size();
3001 llvm::Value *totalCount =
3002 llvm::ConstantInt::get(builder.getInt64Ty(), numLocator);
3005 for (
auto iter : dependIterated) {
3006 auto itersOp = iter.getDefiningOp<mlir::omp::IteratorOp>();
3007 assert(itersOp &&
"depend_iterated value must be defined by omp.iterator");
3008 iterInfos.emplace_back(itersOp, moduleTranslation, builder);
3010 builder.CreateAdd(totalCount, iterInfos.back().getTotalTrips());
3015 llvm::Constant *allocSize = llvm::ConstantExpr::getSizeOf(dependInfoTy);
3016 llvm::Value *depArray =
3017 builder.CreateMalloc(ompBuilder.SizeTy, dependInfoTy, allocSize,
3018 totalCount,
nullptr,
".dep.arr.addr");
3021 if (numLocator > 0) {
3024 for (
auto [i, dd] : llvm::enumerate(dds)) {
3025 llvm::Value *idx = llvm::ConstantInt::get(builder.getInt64Ty(), i);
3026 llvm::Value *entry =
3027 builder.CreateInBoundsGEP(dependInfoTy, depArray, idx);
3028 ompBuilder.emitTaskDependency(builder, entry, dd);
3033 llvm::Value *offset =
3034 llvm::ConstantInt::get(builder.getInt64Ty(), numLocator);
3035 for (
auto [i, iterInfo] : llvm::enumerate(iterInfos)) {
3036 auto kindAttr = cast<mlir::omp::ClauseTaskDependAttr>(
3037 dependIteratedKinds->getValue()[i]);
3038 llvm::omp::RTLDependenceKindTy rtlKind =
3041 auto itersOp = dependIterated[i].getDefiningOp<mlir::omp::IteratorOp>();
3043 itersOp, builder, moduleTranslation, iterInfo,
"dep_iterator",
3044 [&](llvm::Value *linearIV, mlir::omp::YieldOp yield) {
3046 moduleTranslation.
lookupValue(yield.getResults()[0]);
3047 llvm::Value *idx = builder.CreateAdd(offset, linearIV);
3048 llvm::Value *entry =
3049 builder.CreateInBoundsGEP(dependInfoTy, depArray, idx);
3050 ompBuilder.emitTaskDependency(
3052 llvm::OpenMPIRBuilder::DependData{rtlKind, addr->getType(),
3055 return mlir::failure();
3058 offset = builder.CreateAdd(offset, iterInfo.getTotalTrips());
3061 taskDeps.DepArray = depArray;
3062 taskDeps.NumDeps = builder.CreateTrunc(totalCount, builder.getInt32Ty());
3063 return mlir::success();
3070 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
3075 TaskContextStructManager taskStructMgr{builder, moduleTranslation,
3087 InsertPointTy allocaIP =
3092 assert(builder.GetInsertPoint() == builder.GetInsertBlock()->end());
3093 llvm::BasicBlock *taskStartBlock = llvm::BasicBlock::Create(
3094 builder.getContext(),
"omp.task.start",
3095 builder.GetInsertBlock()->getParent());
3096 llvm::Instruction *branchToTaskStartBlock = builder.CreateBr(taskStartBlock);
3097 builder.SetInsertPoint(branchToTaskStartBlock);
3100 llvm::BasicBlock *copyBlock =
3101 splitBB(builder,
true,
"omp.private.copy");
3102 llvm::BasicBlock *initBlock =
3103 splitBB(builder,
true,
"omp.private.init");
3119 moduleTranslation, allocaIP, deallocBlocks);
3122 builder.SetInsertPoint(initBlock->getTerminator());
3125 taskStructMgr.generateTaskContextStruct();
3132 taskStructMgr.createGEPsToPrivateVars();
3134 for (
auto [privDecl, mlirPrivVar, blockArg, llvmPrivateVarAlloc] :
3137 taskStructMgr.getLLVMPrivateVarGEPs())) {
3139 if (!privDecl.readsFromMold())
3141 assert(llvmPrivateVarAlloc &&
3142 "reads from mold so shouldn't have been skipped");
3145 initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar,
3146 blockArg, llvmPrivateVarAlloc, initBlock);
3147 if (!privateVarOrErr)
3148 return handleError(privateVarOrErr, *taskOp.getOperation());
3157 [[maybe_unused]] llvm::Value *llvmPrivateVar = llvmPrivateVarAlloc;
3158 if ((privateVarOrErr.get() != llvmPrivateVarAlloc) &&
3159 !mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
3160 builder.CreateStore(privateVarOrErr.get(), llvmPrivateVarAlloc);
3162 llvmPrivateVar = builder.CreateLoad(privateVarOrErr.get()->getType(),
3163 llvmPrivateVarAlloc);
3165 assert(llvmPrivateVar->getType() ==
3166 moduleTranslation.
convertType(blockArg.getType()));
3176 taskOp, builder, moduleTranslation, privateVarsInfo.
mlirVars,
3177 taskStructMgr.getLLVMPrivateVarGEPs(), privateVarsInfo.
privatizers,
3178 taskOp.getPrivateNeedsBarrier())))
3179 return llvm::failure();
3181 llvm::OpenMPIRBuilder::AffinityData ad;
3183 return llvm::failure();
3193 taskOp.getOperation(), taskOp.getInReductionSyms(),
"omp.task",
3194 "in_reduction", inRedDecls)))
3197 inRedOrigPtrs.reserve(inRedDecls.size());
3198 for (
Value v : taskOp.getInReductionVars())
3199 inRedOrigPtrs.push_back(moduleTranslation.
lookupValue(v));
3202 builder.SetInsertPoint(taskStartBlock);
3205 [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
3210 moduleTranslation, allocaIP, deallocBlocks);
3213 builder.restoreIP(codegenIP);
3215 llvm::BasicBlock *privInitBlock =
nullptr;
3217 for (
auto [i, zip] : llvm::enumerate(llvm::zip_equal(
3220 auto [blockArg, privDecl, mlirPrivVar] = zip;
3222 if (privDecl.readsFromMold())
3225 llvm::IRBuilderBase::InsertPointGuard guard(builder);
3226 llvm::Type *llvmAllocType =
3227 moduleTranslation.
convertType(privDecl.getType());
3228 builder.SetInsertPoint(allocaIP.getBlock()->getTerminator());
3229 llvm::Value *llvmPrivateVar = builder.CreateAlloca(
3230 llvmAllocType,
nullptr,
"omp.private.alloc");
3233 initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar,
3234 blockArg, llvmPrivateVar, privInitBlock);
3235 if (!privateVarOrError)
3236 return privateVarOrError.takeError();
3237 moduleTranslation.
mapValue(blockArg, privateVarOrError.get());
3238 privateVarsInfo.
llvmVars[i] = privateVarOrError.get();
3241 taskStructMgr.createGEPsToPrivateVars();
3242 for (
auto [i, llvmPrivVar] :
3243 llvm::enumerate(taskStructMgr.getLLVMPrivateVarGEPs())) {
3245 assert(privateVarsInfo.
llvmVars[i] &&
3246 "This is added in the loop above");
3249 privateVarsInfo.
llvmVars[i] = llvmPrivVar;
3254 for (
auto [blockArg, llvmPrivateVar, privateDecl] :
3258 if (!privateDecl.readsFromMold())
3261 if (!mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
3262 llvmPrivateVar = builder.CreateLoad(
3263 moduleTranslation.
convertType(blockArg.getType()), llvmPrivateVar);
3265 assert(llvmPrivateVar->getType() ==
3266 moduleTranslation.
convertType(blockArg.getType()));
3267 moduleTranslation.
mapValue(blockArg, llvmPrivateVar);
3278 if (!inRedDecls.empty()) {
3279 auto iface = cast<omp::BlockArgOpenMPOpInterface>(taskOp.getOperation());
3282 llvm::LLVMContext &llvmCtx = m->getContext();
3283 llvm::OpenMPIRBuilder::LocationDescription bodyLoc(builder);
3284 uint32_t srcLocSize;
3285 llvm::Constant *srcLocStr =
3286 ompB.getOrCreateSrcLocStr(bodyLoc, srcLocSize);
3287 llvm::Value *bodyIdent = ompB.getOrCreateIdent(srcLocStr, srcLocSize);
3290 ompB.updateToLocation(bodyLoc);
3291 llvm::Value *bodyGtid = ompB.getOrCreateThreadID(bodyIdent);
3292 llvm::FunctionCallee getThData = ompB.getOrCreateRuntimeFunction(
3293 *m, llvm::omp::OMPRTL___kmpc_task_reduction_get_th_data);
3294 llvm::Type *ptrTy = llvm::PointerType::getUnqual(llvmCtx);
3295 llvm::Value *nullDesc = llvm::ConstantPointerNull::get(ptrTy);
3297 for (
auto [blockArg, origPtr] :
3298 llvm::zip_equal(inRedBlockArgs, inRedOrigPtrs)) {
3305 llvm::Value *lookupPtr = origPtr;
3306 if (
auto *origPtrTy =
3307 llvm::dyn_cast<llvm::PointerType>(lookupPtr->getType());
3308 origPtrTy && origPtrTy->getAddressSpace() != 0)
3309 lookupPtr = builder.CreateAddrSpaceCast(lookupPtr, ptrTy);
3310 llvm::Value *priv = builder.CreateCall(
3311 getThData, {bodyGtid, nullDesc, lookupPtr},
"omp.inred.priv");
3312 if (
auto *argPtrTy = llvm::dyn_cast<llvm::PointerType>(
3313 moduleTranslation.
convertType(blockArg.getType()));
3314 argPtrTy && argPtrTy->getAddressSpace() != 0)
3315 priv = builder.CreateAddrSpaceCast(priv, argPtrTy);
3316 moduleTranslation.
mapValue(blockArg, priv);
3321 taskOp.getRegion(),
"omp.task.region", builder, moduleTranslation);
3322 if (failed(
handleError(continuationBlockOrError, *taskOp)))
3323 return llvm::make_error<PreviouslyReportedError>();
3325 builder.SetInsertPoint(continuationBlockOrError.get()->getTerminator());
3328 taskOp.getLoc(), privateVarsInfo)))
3329 return llvm::make_error<PreviouslyReportedError>();
3332 taskStructMgr.freeStructPtr();
3334 return llvm::Error::success();
3343 llvm::omp::Directive::OMPD_taskgroup);
3345 llvm::OpenMPIRBuilder::DependenciesInfo dependencies;
3346 if (failed(
buildDependData(taskOp.getDependVars(), taskOp.getDependKinds(),
3347 taskOp.getDependIterated(),
3348 taskOp.getDependIteratedKinds(), builder,
3349 moduleTranslation, dependencies)))
3352 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
3353 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
3355 ompLoc, allocaIP, deallocBlocks, bodyCB, !taskOp.getUntied(),
3357 moduleTranslation.
lookupValue(taskOp.getIfExpr()), dependencies, ad,
3358 taskOp.getMergeable(),
3359 moduleTranslation.
lookupValue(taskOp.getEventHandle()),
3360 moduleTranslation.
lookupValue(taskOp.getPriority()));
3368 builder.restoreIP(*afterIP);
3370 if (dependencies.DepArray)
3371 builder.CreateFree(dependencies.DepArray);
3380 llvm::IRBuilderBase &builder,
3388 loopWrapperOp.getRegion(),
"omp.taskloop.wrapper.region", builder,
3391 if (failed(
handleError(continuationBlockOrError, opInst)))
3394 builder.SetInsertPoint(continuationBlockOrError.get());
3402static llvm::Expected<llvm::Value *>
3405 llvm::IRBuilderBase &builder) {
3406 if (llvm::Value *mapped = moduleTranslation.
lookupValue(value))
3411 return llvm::make_error<llvm::StringError>(
3412 "value is a block argument and is not mapped",
3413 llvm::inconvertibleErrorCode());
3415 return llvm::make_error<llvm::StringError>(
3416 "unsupported op defining taskloop loop bound",
3417 llvm::inconvertibleErrorCode());
3427 if (!operandOrError)
3428 return operandOrError.takeError();
3429 moduleTranslation.
mapValue(operand, *operandOrError);
3430 mappingsToRemove.push_back(operand);
3434 return llvm::make_error<llvm::StringError>(
3435 "failed to convert op defining taskloop loop bound",
3436 llvm::inconvertibleErrorCode());
3439 assert(
result &&
"expected conversion of loop bound op to produce a value");
3443 mappingsToRemove.push_back(resultValue);
3445 for (
Value mappedValue : mappingsToRemove)
3454 llvm::Value *&lbVal, llvm::Value *&ubVal,
3455 llvm::Value *&stepVal) {
3463 return firstLbOrErr.takeError();
3465 llvm::Type *boundType = (*firstLbOrErr)->getType();
3466 ubVal = builder.getIntN(boundType->getIntegerBitWidth(), 1);
3467 if (loopOp.getCollapseNumLoops() > 1) {
3485 for (uint64_t i = 0; i < loopOp.getCollapseNumLoops(); i++) {
3487 i == 0 ? std::move(firstLbOrErr)
3491 return lbOrErr.takeError();
3493 upperBounds[i], moduleTranslation, builder);
3495 return ubOrErr.takeError();
3499 return stepOrErr.takeError();
3501 llvm::Value *loopLb = *lbOrErr;
3502 llvm::Value *loopUb = *ubOrErr;
3503 llvm::Value *loopStep = *stepOrErr;
3509 llvm::Value *loopLbMinusOne = builder.CreateSub(
3510 loopLb, builder.getIntN(boundType->getIntegerBitWidth(), 1));
3511 llvm::Value *loopUbMinusOne = builder.CreateSub(
3512 loopUb, builder.getIntN(boundType->getIntegerBitWidth(), 1));
3513 llvm::Value *boundsCmp = builder.CreateICmpSLT(loopLb, loopUb);
3514 llvm::Value *ubMinusLb = builder.CreateSub(loopUb, loopLbMinusOne);
3515 llvm::Value *lbMinusUb = builder.CreateSub(loopLb, loopUbMinusOne);
3516 llvm::Value *loopTripCount =
3517 builder.CreateSelect(boundsCmp, ubMinusLb, lbMinusUb);
3518 loopTripCount = builder.CreateBinaryIntrinsic(
3519 llvm::Intrinsic::abs, loopTripCount, builder.getFalse());
3523 llvm::Value *loopTripCountDivStep =
3524 builder.CreateSDiv(loopTripCount, loopStep);
3525 loopTripCountDivStep = builder.CreateBinaryIntrinsic(
3526 llvm::Intrinsic::abs, loopTripCountDivStep, builder.getFalse());
3527 llvm::Value *loopTripCountRem =
3528 builder.CreateSRem(loopTripCount, loopStep);
3529 loopTripCountRem = builder.CreateBinaryIntrinsic(
3530 llvm::Intrinsic::abs, loopTripCountRem, builder.getFalse());
3531 llvm::Value *needsRoundUp = builder.CreateICmpNE(
3533 builder.getIntN(loopTripCountRem->getType()->getIntegerBitWidth(),
3536 builder.CreateAdd(loopTripCountDivStep,
3537 builder.CreateZExtOrTrunc(
3538 needsRoundUp, loopTripCountDivStep->getType()));
3539 ubVal = builder.CreateMul(ubVal, loopTripCount);
3541 lbVal = builder.getIntN(boundType->getIntegerBitWidth(), 1);
3542 stepVal = builder.getIntN(boundType->getIntegerBitWidth(), 1);
3547 return ubOrErr.takeError();
3551 return stepOrErr.takeError();
3552 lbVal = *firstLbOrErr;
3554 stepVal = *stepOrErr;
3557 assert(lbVal !=
nullptr &&
"Expected value for lbVal");
3558 assert(ubVal !=
nullptr &&
"Expected value for ubVal");
3559 assert(stepVal !=
nullptr &&
"Expected value for stepVal");
3560 return llvm::Error::success();
3566 llvm::IRBuilderBase &builder,
3568 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
3570 omp::TaskloopWrapperOp loopWrapperOp = contextOp.getLoopOp();
3578 TaskContextStructManager taskStructMgr{builder, moduleTranslation,
3582 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
3585 assert(builder.GetInsertPoint() == builder.GetInsertBlock()->end());
3586 llvm::BasicBlock *taskloopStartBlock = llvm::BasicBlock::Create(
3587 builder.getContext(),
"omp.taskloop.wrapper.start",
3588 builder.GetInsertBlock()->getParent());
3589 llvm::Instruction *branchToTaskloopStartBlock =
3590 builder.CreateBr(taskloopStartBlock);
3591 builder.SetInsertPoint(branchToTaskloopStartBlock);
3593 llvm::BasicBlock *copyBlock =
3594 splitBB(builder,
true,
"omp.private.copy");
3595 llvm::BasicBlock *initBlock =
3596 splitBB(builder,
true,
"omp.private.init");
3599 moduleTranslation, allocaIP, deallocBlocks);
3602 builder.SetInsertPoint(initBlock->getTerminator());
3605 taskStructMgr.generateTaskContextStruct();
3606 taskStructMgr.createGEPsToPrivateVars();
3608 llvmFirstPrivateVars.resize(privateVarsInfo.
blockArgs.size());
3610 for (
auto [i, zip] : llvm::enumerate(llvm::zip_equal(
3612 privateVarsInfo.
blockArgs, taskStructMgr.getLLVMPrivateVarGEPs()))) {
3613 auto [privDecl, mlirPrivVar, blockArg, llvmPrivateVarAlloc] = zip;
3615 if (!privDecl.readsFromMold())
3617 assert(llvmPrivateVarAlloc &&
3618 "reads from mold so shouldn't have been skipped");
3621 initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar,
3622 blockArg, llvmPrivateVarAlloc, initBlock);
3623 if (!privateVarOrErr)
3624 return handleError(privateVarOrErr, *contextOp.getOperation());
3626 llvmFirstPrivateVars[i] = privateVarOrErr.get();
3628 llvm::IRBuilderBase::InsertPointGuard guard(builder);
3629 builder.SetInsertPoint(builder.GetInsertBlock()->getTerminator());
3631 [[maybe_unused]] llvm::Value *llvmPrivateVar = llvmPrivateVarAlloc;
3632 if ((privateVarOrErr.get() != llvmPrivateVarAlloc) &&
3633 !mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
3634 builder.CreateStore(privateVarOrErr.get(), llvmPrivateVarAlloc);
3636 llvmPrivateVar = builder.CreateLoad(privateVarOrErr.get()->getType(),
3637 llvmPrivateVarAlloc);
3639 assert(llvmPrivateVar->getType() ==
3640 moduleTranslation.
convertType(blockArg.getType()));
3646 contextOp, builder, moduleTranslation, privateVarsInfo.
mlirVars,
3647 taskStructMgr.getLLVMPrivateVarGEPs(), privateVarsInfo.
privatizers,
3648 contextOp.getPrivateNeedsBarrier())))
3649 return llvm::failure();
3659 contextOp.getOperation(), contextOp.getReductionSyms(),
3660 "omp.taskloop.context",
"reduction", redDecls)))
3664 contextOp.getOperation(), contextOp.getInReductionSyms(),
3665 "omp.taskloop.context",
"in_reduction", inRedDecls)))
3671 redOrigPtrs.reserve(redDecls.size());
3672 for (
Value v : contextOp.getReductionVars())
3673 redOrigPtrs.push_back(moduleTranslation.
lookupValue(v));
3675 inRedOrigPtrs.reserve(inRedDecls.size());
3676 for (
Value v : contextOp.getInReductionVars())
3677 inRedOrigPtrs.push_back(moduleTranslation.
lookupValue(v));
3681 builder.SetInsertPoint(taskloopStartBlock);
3683 llvm::OpenMPIRBuilder &ompBuilderRef = *moduleTranslation.
getOpenMPBuilder();
3690 bool implicitTaskgroup = !redDecls.empty();
3691 llvm::Value *redDesc =
nullptr;
3692 if (implicitTaskgroup) {
3693 llvm::OpenMPIRBuilder::LocationDescription redLoc(builder);
3694 uint32_t srcLocSize;
3695 llvm::Constant *srcLocStr =
3696 ompBuilderRef.getOrCreateSrcLocStr(redLoc, srcLocSize);
3697 llvm::Value *ident = ompBuilderRef.getOrCreateIdent(srcLocStr, srcLocSize);
3700 ompBuilderRef.updateToLocation(redLoc);
3701 llvm::Value *outerGtid = ompBuilderRef.getOrCreateThreadID(ident);
3702 llvm::FunctionCallee taskgroupFn = ompBuilderRef.getOrCreateRuntimeFunction(
3703 *module, llvm::omp::OMPRTL___kmpc_taskgroup);
3704 builder.CreateCall(taskgroupFn, {ident, outerGtid});
3707 "__omp_taskloop_taskred_", builder,
3708 allocaIP, moduleTranslation);
3713 auto loopOp = cast<omp::LoopNestOp>(loopWrapperOp.getWrappedLoop());
3714 llvm::Value *lbVal =
nullptr;
3715 llvm::Value *ubVal =
nullptr;
3716 llvm::Value *stepVal =
nullptr;
3718 loopOp, builder, moduleTranslation, lbVal, ubVal, stepVal))
3722 [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
3727 moduleTranslation, allocaIP, deallocBlocks);
3730 builder.restoreIP(codegenIP);
3732 llvm::BasicBlock *privInitBlock =
nullptr;
3734 for (
auto [i, zip] : llvm::enumerate(llvm::zip_equal(
3737 auto [blockArg, privDecl, mlirPrivVar] = zip;
3739 if (privDecl.readsFromMold())
3742 llvm::IRBuilderBase::InsertPointGuard guard(builder);
3743 llvm::Type *llvmAllocType =
3744 moduleTranslation.
convertType(privDecl.getType());
3745 builder.SetInsertPoint(allocaIP.getBlock()->getTerminator());
3746 llvm::Value *llvmPrivateVar = builder.CreateAlloca(
3747 llvmAllocType,
nullptr,
"omp.private.alloc");
3750 initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar,
3751 blockArg, llvmPrivateVar, privInitBlock);
3752 if (!privateVarOrError)
3753 return privateVarOrError.takeError();
3754 moduleTranslation.
mapValue(blockArg, privateVarOrError.get());
3755 privateVarsInfo.
llvmVars[i] = privateVarOrError.get();
3758 taskStructMgr.createGEPsToPrivateVars();
3759 for (
auto [i, llvmPrivVar] :
3760 llvm::enumerate(taskStructMgr.getLLVMPrivateVarGEPs())) {
3762 assert(privateVarsInfo.
llvmVars[i] &&
3763 "This is added in the loop above");
3766 privateVarsInfo.
llvmVars[i] = llvmPrivVar;
3771 for (
auto [blockArg, llvmPrivateVar, privateDecl] :
3775 if (!privateDecl.readsFromMold())
3778 if (!mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
3779 llvmPrivateVar = builder.CreateLoad(
3780 moduleTranslation.
convertType(blockArg.getType()), llvmPrivateVar);
3782 assert(llvmPrivateVar->getType() ==
3783 moduleTranslation.
convertType(blockArg.getType()));
3784 moduleTranslation.
mapValue(blockArg, llvmPrivateVar);
3796 if (!redDecls.empty() || !inRedDecls.empty()) {
3798 cast<omp::BlockArgOpenMPOpInterface>(contextOp.getOperation());
3801 llvm::LLVMContext &llvmCtx = m->getContext();
3802 llvm::OpenMPIRBuilder::LocationDescription bodyLoc(builder);
3803 uint32_t srcLocSize;
3804 llvm::Constant *srcLocStr =
3805 ompB.getOrCreateSrcLocStr(bodyLoc, srcLocSize);
3806 llvm::Value *bodyIdent = ompB.getOrCreateIdent(srcLocStr, srcLocSize);
3809 ompB.updateToLocation(bodyLoc);
3810 llvm::Value *bodyGtid = ompB.getOrCreateThreadID(bodyIdent);
3811 llvm::FunctionCallee getThData = ompB.getOrCreateRuntimeFunction(
3812 *m, llvm::omp::OMPRTL___kmpc_task_reduction_get_th_data);
3813 llvm::Type *ptrTy = llvm::PointerType::getUnqual(llvmCtx);
3823 auto remapReductionArg = [&](
BlockArgument blockArg, llvm::Value *desc,
3824 llvm::Value *origPtr,
3825 const llvm::Twine &name) {
3826 if (
auto *origPtrTy =
3827 llvm::dyn_cast<llvm::PointerType>(origPtr->getType());
3828 origPtrTy && origPtrTy->getAddressSpace() != 0)
3829 origPtr = builder.CreateAddrSpaceCast(origPtr, ptrTy);
3831 builder.CreateCall(getThData, {bodyGtid, desc, origPtr}, name);
3832 if (
auto *argPtrTy = llvm::dyn_cast<llvm::PointerType>(
3834 argPtrTy && argPtrTy->getAddressSpace() != 0)
3835 priv = builder.CreateAddrSpaceCast(priv, argPtrTy);
3836 moduleTranslation.
mapValue(blockArg, priv);
3840 for (
auto [blockArg, origPtr] :
3841 llvm::zip_equal(redBlockArgs, redOrigPtrs))
3842 remapReductionArg(blockArg, redDesc, origPtr,
"omp.taskred.priv");
3844 llvm::Value *nullDesc = llvm::ConstantPointerNull::get(ptrTy);
3845 for (
auto [blockArg, origPtr] :
3846 llvm::zip_equal(inRedBlockArgs, inRedOrigPtrs))
3847 remapReductionArg(blockArg, nullDesc, origPtr,
"omp.inred.priv");
3853 contextOp.getRegion(),
"omp.taskloop.context.region", builder,
3856 if (failed(
handleError(continuationBlockOrError, opInst)))
3857 return llvm::make_error<PreviouslyReportedError>();
3859 builder.SetInsertPoint(continuationBlockOrError.get()->getTerminator());
3867 contextOp.getLoc(), privateVarsInfo)))
3868 return llvm::make_error<PreviouslyReportedError>();
3871 taskStructMgr.freeStructPtr();
3873 return llvm::Error::success();
3879 auto taskDupCB = [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
3880 llvm::Value *destPtr, llvm::Value *srcPtr)
3882 llvm::IRBuilderBase::InsertPointGuard guard(builder);
3883 builder.restoreIP(codegenIP);
3886 builder.getPtrTy(srcPtr->getType()->getPointerAddressSpace());
3888 builder.CreateLoad(ptrTy, srcPtr,
"omp.taskloop.context.src");
3890 TaskContextStructManager &srcStructMgr = taskStructMgr;
3891 TaskContextStructManager destStructMgr(builder, moduleTranslation,
3893 destStructMgr.generateTaskContextStruct();
3894 llvm::Value *dest = destStructMgr.getStructPtr();
3895 dest->setName(
"omp.taskloop.context.dest");
3896 builder.CreateStore(dest, destPtr);
3899 srcStructMgr.createGEPsToPrivateVars(src);
3901 destStructMgr.createGEPsToPrivateVars(dest);
3904 for (
auto [privDecl, mold, blockArg, llvmPrivateVarAlloc] :
3905 llvm::zip_equal(privateVarsInfo.
privatizers, srcGEPs,
3908 if (!privDecl.readsFromMold())
3910 assert(llvmPrivateVarAlloc &&
3911 "reads from mold so shouldn't have been skipped");
3914 builder, moduleTranslation, privDecl.getInitMoldArg(), mold);
3916 builder, moduleTranslation, privDecl, moldArg, blockArg,
3917 llvmPrivateVarAlloc, builder.GetInsertBlock());
3918 if (!privateVarOrErr)
3919 return privateVarOrErr.takeError();
3928 [[maybe_unused]] llvm::Value *llvmPrivateVar = llvmPrivateVarAlloc;
3929 if ((privateVarOrErr.get() != llvmPrivateVarAlloc) &&
3930 !mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
3931 builder.CreateStore(privateVarOrErr.get(), llvmPrivateVarAlloc);
3933 llvmPrivateVar = builder.CreateLoad(privateVarOrErr.get()->getType(),
3934 llvmPrivateVarAlloc);
3936 assert(llvmPrivateVar->getType() ==
3937 moduleTranslation.
convertType(blockArg.getType()));
3945 moduleTranslation, srcGEPs, destGEPs,
3947 contextOp.getPrivateNeedsBarrier())))
3948 return llvm::make_error<PreviouslyReportedError>();
3950 return builder.saveIP();
3958 llvm::Value *ifCond =
nullptr;
3959 llvm::Value *grainsize =
nullptr;
3961 mlir::Value grainsizeVal = contextOp.getGrainsize();
3962 mlir::Value numTasksVal = contextOp.getNumTasks();
3963 if (
Value ifVar = contextOp.getIfExpr())
3966 grainsize = moduleTranslation.
lookupValue(grainsizeVal);
3968 }
else if (numTasksVal) {
3969 grainsize = moduleTranslation.
lookupValue(numTasksVal);
3973 llvm::OpenMPIRBuilder::TaskDupCallbackTy taskDupOrNull =
nullptr;
3974 if (taskStructMgr.getStructPtr())
3975 taskDupOrNull = taskDupCB;
3985 llvm::omp::Directive::OMPD_taskgroup);
3987 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
3988 bool effectiveNoGroup = contextOp.getNogroup() || implicitTaskgroup;
3989 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
3991 ompLoc, allocaIP, deallocBlocks, bodyCB, loopInfo, lbVal, ubVal,
3992 stepVal, contextOp.getUntied(), ifCond, grainsize, effectiveNoGroup,
3993 sched, moduleTranslation.
lookupValue(contextOp.getFinal()),
3994 contextOp.getMergeable(),
3995 moduleTranslation.
lookupValue(contextOp.getPriority()),
3996 loopOp.getCollapseNumLoops(), taskDupOrNull,
3997 taskStructMgr.getStructPtr());
4004 builder.restoreIP(*afterIP);
4008 if (implicitTaskgroup) {
4009 llvm::OpenMPIRBuilder::LocationDescription endLoc(builder);
4010 uint32_t srcLocSize;
4011 llvm::Constant *srcLocStr =
4012 ompBuilder.getOrCreateSrcLocStr(endLoc, srcLocSize);
4013 llvm::Value *ident = ompBuilder.getOrCreateIdent(srcLocStr, srcLocSize);
4016 ompBuilder.updateToLocation(endLoc);
4017 llvm::Value *outerGtid = ompBuilder.getOrCreateThreadID(ident);
4018 llvm::FunctionCallee endTgFn = ompBuilder.getOrCreateRuntimeFunction(
4020 llvm::omp::OMPRTL___kmpc_end_taskgroup);
4021 builder.CreateCall(endTgFn, {ident, outerGtid});
4032static llvm::Function *
4035 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
4036 llvm::LLVMContext &ctx = llvmModule->getContext();
4037 llvm::Type *voidTy = llvm::Type::getVoidTy(ctx);
4038 llvm::Type *ptrTy = llvm::PointerType::getUnqual(ctx);
4039 llvm::FunctionType *fty =
4040 llvm::FunctionType::get(voidTy, {ptrTy, ptrTy},
false);
4041 llvm::Function *fn =
4042 llvm::Function::Create(fty, llvm::GlobalValue::InternalLinkage,
4043 baseName +
".red.init", llvmModule);
4044 fn->setDoesNotRecurse();
4045 fn->getArg(0)->setName(
"priv");
4046 fn->getArg(1)->setName(
"orig");
4048 llvm::BasicBlock *entry = llvm::BasicBlock::Create(ctx,
"entry", fn);
4049 llvm::IRBuilder<>
b(entry);
4056 Value moldArg = decl.getInitializerMoldArg();
4057 llvm::Value *origVal = fn->getArg(1);
4058 if (!isa<LLVM::LLVMPointerType>(moldArg.
getType()))
4060 fn->getArg(1),
"omp.orig");
4061 moduleTranslation.
mapValue(moldArg, origVal);
4064 "omp.taskred.init",
b, moduleTranslation,
4066 fn->eraseFromParent();
4069 assert(phis.size() == 1 &&
4070 "expected one value yielded from reduction initializer");
4071 b.CreateStore(phis[0], fn->getArg(0));
4074 moduleTranslation.
forgetMapping(decl.getInitializerRegion());
4082static llvm::Function *
4085 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
4086 llvm::LLVMContext &ctx = llvmModule->getContext();
4087 llvm::Type *voidTy = llvm::Type::getVoidTy(ctx);
4088 llvm::Type *ptrTy = llvm::PointerType::getUnqual(ctx);
4089 llvm::FunctionType *fty =
4090 llvm::FunctionType::get(voidTy, {ptrTy, ptrTy},
false);
4091 llvm::Function *fn =
4092 llvm::Function::Create(fty, llvm::GlobalValue::InternalLinkage,
4093 baseName +
".red.comb", llvmModule);
4094 fn->setDoesNotRecurse();
4095 fn->getArg(0)->setName(
"lhs");
4096 fn->getArg(1)->setName(
"rhs");
4098 llvm::BasicBlock *entry = llvm::BasicBlock::Create(ctx,
"entry", fn);
4099 llvm::IRBuilder<>
b(entry);
4101 llvm::Type *elemTy = moduleTranslation.
convertType(decl.getType());
4102 Block &combBlock = decl.getReductionRegion().
front();
4104 "expected two arguments in declare_reduction combiner");
4105 llvm::Value *lhsVal =
b.CreateLoad(elemTy, fn->getArg(0),
"omp.lhs");
4106 llvm::Value *rhsVal =
b.CreateLoad(elemTy, fn->getArg(1),
"omp.rhs");
4112 "omp.taskred.comb",
b, moduleTranslation,
4114 fn->eraseFromParent();
4117 assert(phis.size() == 1 &&
4118 "expected one value yielded from reduction combiner");
4119 b.CreateStore(phis[0], fn->getArg(0));
4145 llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder::InsertPointTy allocaIP,
4147 bool isWorksharing) {
4148 assert(redDecls.size() == origPtrs.size() &&
4149 "expected one orig pointer per reduction decl");
4151 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
4152 llvm::LLVMContext &ctx = llvmModule->getContext();
4153 const llvm::DataLayout &dl = llvmModule->getDataLayout();
4155 llvm::Type *ptrTy = llvm::PointerType::getUnqual(ctx);
4156 llvm::Type *i32Ty = llvm::Type::getInt32Ty(ctx);
4157 llvm::Type *sizeTy =
4158 llvm::Type::getIntNTy(ctx, dl.getPointerSizeInBits(0));
4162 llvm::StructType *redInputTy =
4163 llvm::StructType::getTypeByName(ctx,
"kmp_taskred_input_t");
4165 redInputTy = llvm::StructType::create(
4166 ctx, {ptrTy, ptrTy, sizeTy, ptrTy, ptrTy, ptrTy, i32Ty},
4167 "kmp_taskred_input_t");
4169 unsigned n = redDecls.size();
4170 llvm::ArrayType *arrTy = llvm::ArrayType::get(redInputTy, n);
4173 llvm::AllocaInst *arrAlloca;
4175 llvm::IRBuilderBase::InsertPointGuard guard(builder);
4176 builder.restoreIP(allocaIP);
4178 builder.CreateAlloca(arrTy,
nullptr,
".taskred.input");
4182 llvm::Value *zero = builder.getInt32(0);
4183 for (
unsigned i = 0; i < n; ++i) {
4184 omp::DeclareReductionOp decl = redDecls[i];
4185 llvm::Value *orig = origPtrs[i];
4186 if (
auto *origPtrTy = llvm::dyn_cast<llvm::PointerType>(orig->getType());
4187 origPtrTy && origPtrTy->getAddressSpace() != 0)
4188 orig = builder.CreateAddrSpaceCast(orig, ptrTy);
4189 llvm::Type *elemTy = moduleTranslation.
convertType(decl.getType());
4190 uint64_t size = dl.getTypeAllocSize(elemTy).getFixedValue();
4192 std::string baseName =
4193 (llvm::Twine(helperNamePrefix) + decl.getSymName()).str();
4194 llvm::Function *initFn =
4196 llvm::Function *combFn =
4198 if (!initFn || !combFn)
4200 llvm::Value *elemPtr = builder.CreateInBoundsGEP(
4201 arrTy, arrAlloca, {zero, builder.getInt32(i)},
".taskred.elem");
4202 auto storeField = [&](
unsigned fieldIdx, llvm::Value *val) {
4203 llvm::Value *fieldPtr =
4204 builder.CreateStructGEP(redInputTy, elemPtr, fieldIdx);
4205 builder.CreateStore(val, fieldPtr);
4207 storeField(0, orig);
4208 storeField(1, orig);
4209 storeField(2, llvm::ConstantInt::get(sizeTy, size));
4210 storeField(3, initFn);
4211 storeField(4, llvm::ConstantPointerNull::get(ptrTy));
4212 storeField(5, combFn);
4213 storeField(6, llvm::ConstantInt::get(i32Ty, 0));
4217 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4218 uint32_t srcLocSize;
4219 llvm::Constant *srcLocStr =
4220 ompBuilder->getOrCreateSrcLocStr(ompLoc, srcLocSize);
4221 llvm::Value *ident = ompBuilder->getOrCreateIdent(srcLocStr, srcLocSize);
4222 ompBuilder->updateToLocation(ompLoc);
4223 llvm::Value *gtid = ompBuilder->getOrCreateThreadID(ident);
4227 llvm::FunctionCallee modInit = ompBuilder->getOrCreateRuntimeFunction(
4228 *llvmModule, llvm::omp::OMPRTL___kmpc_taskred_modifier_init);
4229 return builder.CreateCall(modInit,
4231 builder.getInt32(isWorksharing ? 1 : 0),
4232 builder.getInt32(n), arrAlloca},
4236 llvm::FunctionCallee taskredInit = ompBuilder->getOrCreateRuntimeFunction(
4237 *llvmModule, llvm::omp::OMPRTL___kmpc_taskred_init);
4238 return builder.CreateCall(taskredInit, {gtid, builder.getInt32(n), arrAlloca},
4249 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
4250 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4251 uint32_t srcLocSize;
4252 llvm::Constant *srcLocStr =
4253 ompBuilder->getOrCreateSrcLocStr(ompLoc, srcLocSize);
4254 llvm::Value *ident = ompBuilder->getOrCreateIdent(srcLocStr, srcLocSize);
4255 ompBuilder->updateToLocation(ompLoc);
4256 llvm::Value *gtid = ompBuilder->getOrCreateThreadID(ident);
4257 llvm::FunctionCallee fini = ompBuilder->getOrCreateRuntimeFunction(
4258 *llvmModule, llvm::omp::OMPRTL___kmpc_task_reduction_modifier_fini);
4259 builder.CreateCall(fini,
4260 {ident, gtid, builder.getInt32(isWorksharing ? 1 : 0)});
4267 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4276 if (
auto syms = tgOp.getTaskReductionSyms()) {
4277 redDecls.reserve(syms->size());
4278 for (
auto sym : syms->getAsRange<SymbolRefAttr>()) {
4282 return tgOp.emitError()
4283 <<
"failed to resolve task_reduction declare_reduction symbol "
4284 << sym.getRootReference() <<
" in omp.taskgroup";
4285 if (decl.getInitializerRegion().front().getNumArguments() != 1)
4286 return tgOp.emitError(
"not yet implemented: task_reduction with "
4287 "two-argument initializer in omp.taskgroup");
4288 if (!decl.getCleanupRegion().empty())
4289 return tgOp.emitError(
"not yet implemented: task_reduction with "
4290 "cleanup region in omp.taskgroup");
4291 if (decl.getReductionRegion().empty())
4292 return tgOp.emitError(
"task_reduction declare_reduction is missing a "
4294 redDecls.push_back(decl);
4299 [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
4301 builder.restoreIP(codegenIP);
4303 if (!redDecls.empty()) {
4305 origPtrs.reserve(redDecls.size());
4306 for (
Value v : tgOp.getTaskReductionVars())
4307 origPtrs.push_back(moduleTranslation.
lookupValue(v));
4309 builder, allocaIP, moduleTranslation))
4310 return llvm::createStringError(
4311 llvm::inconvertibleErrorCode(),
4312 "failed to emit task_reduction initialization for omp.taskgroup");
4320 for (
auto [i, blockArg] :
4321 llvm::enumerate(tgOp.getRegion().getArguments())) {
4323 moduleTranslation.
lookupValue(tgOp.getTaskReductionVars()[i]);
4324 moduleTranslation.
mapValue(blockArg, orig);
4328 builder, moduleTranslation)
4333 InsertPointTy allocaIP =
4335 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4336 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
4338 ompLoc, allocaIP, deallocBlocks, bodyCB);
4343 builder.restoreIP(*afterIP);
4362 auto wsloopOp = cast<omp::WsloopOp>(opInst);
4366 auto loopOp = cast<omp::LoopNestOp>(wsloopOp.getWrappedLoop());
4368 assert(isByRef.size() == wsloopOp.getNumReductionVars());
4372 wsloopOp.getScheduleKind().value_or(omp::ClauseScheduleKind::Static);
4375 llvm::Value *step = moduleTranslation.
lookupValue(loopOp.getLoopSteps()[0]);
4376 llvm::Type *ivType = step->getType();
4377 llvm::Value *chunk =
nullptr;
4378 if (wsloopOp.getScheduleChunk()) {
4379 llvm::Value *chunkVar =
4380 moduleTranslation.
lookupValue(wsloopOp.getScheduleChunk());
4381 chunk = builder.CreateSExtOrTrunc(chunkVar, ivType);
4384 omp::DistributeOp distributeOp =
nullptr;
4385 llvm::Value *distScheduleChunk =
nullptr;
4386 bool hasDistSchedule =
false;
4387 if (llvm::isa_and_present<omp::DistributeOp>(opInst.
getParentOp())) {
4388 distributeOp = cast<omp::DistributeOp>(opInst.
getParentOp());
4389 hasDistSchedule = distributeOp.getDistScheduleStatic();
4390 if (distributeOp.getDistScheduleChunkSize()) {
4391 llvm::Value *chunkVar = moduleTranslation.
lookupValue(
4392 distributeOp.getDistScheduleChunkSize());
4393 distScheduleChunk = builder.CreateSExtOrTrunc(chunkVar, ivType);
4402 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
4406 wsloopOp.getNumReductionVars());
4409 wsloopOp, builder, moduleTranslation, privateVarsInfo, allocaIP);
4416 cast<omp::BlockArgOpenMPOpInterface>(opInst).getReductionBlockArgs();
4421 moduleTranslation, allocaIP, reductionDecls,
4422 privateReductionVariables, reductionVariableMap,
4423 deferredStores, isByRef)))
4432 wsloopOp, builder, moduleTranslation, privateVarsInfo.
mlirVars,
4434 wsloopOp.getPrivateNeedsBarrier())))
4437 assert(afterAllocas.get()->getSinglePredecessor());
4438 if (failed(initReductionVars(wsloopOp, reductionArgs, builder,
4440 afterAllocas.get()->getSinglePredecessor(),
4441 reductionDecls, privateReductionVariables,
4442 reductionVariableMap, isByRef, deferredStores)))
4448 bool isTaskReductionMod =
4449 wsloopOp.getReductionMod() == omp::ReductionModifier::task &&
4450 wsloopOp.getNumReductionVars() > 0;
4451 if (isTaskReductionMod &&
4453 "__omp_taskred_mod_", builder, allocaIP,
4454 moduleTranslation,
true,
4456 return wsloopOp.emitError(
4457 "failed to emit task reduction modifier initialization");
4460 bool isOrdered = wsloopOp.getOrdered().has_value();
4461 std::optional<omp::ScheduleModifier> scheduleMod = wsloopOp.getScheduleMod();
4462 bool isSimd = wsloopOp.getScheduleSimd();
4463 bool loopNeedsBarrier = !wsloopOp.getNowait();
4468 llvm::omp::WorksharingLoopType workshareLoopType =
4469 llvm::isa_and_present<omp::DistributeOp>(opInst.
getParentOp())
4470 ? llvm::omp::WorksharingLoopType::DistributeForStaticLoop
4471 : llvm::omp::WorksharingLoopType::ForStaticLoop;
4475 llvm::omp::Directive::OMPD_for);
4477 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4480 LinearClauseProcessor linearClauseProcessor;
4482 if (!wsloopOp.getLinearVars().empty()) {
4483 auto linearVarTypes = wsloopOp.getLinearVarTypes().value();
4485 linearClauseProcessor.registerType(moduleTranslation, linearVarType);
4487 for (
auto [idx, linearVar] : llvm::enumerate(wsloopOp.getLinearVars()))
4488 linearClauseProcessor.createLinearVar(
4489 builder, moduleTranslation, moduleTranslation.
lookupValue(linearVar),
4491 for (
mlir::Value linearStep : wsloopOp.getLinearStepVars())
4492 linearClauseProcessor.initLinearStep(moduleTranslation, linearStep);
4496 wsloopOp.getRegion(),
"omp.wsloop.region", builder, moduleTranslation);
4504 if (!wsloopOp.getLinearVars().empty()) {
4505 linearClauseProcessor.initLinearVar(builder, moduleTranslation,
4506 loopInfo->getPreheader());
4507 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterBarrierIP =
4509 builder.saveIP(), llvm::omp::OMPD_barrier);
4512 builder.restoreIP(*afterBarrierIP);
4513 linearClauseProcessor.updateLinearVar(builder, loopInfo->getBody(),
4514 loopInfo->getIndVar());
4515 linearClauseProcessor.splitLinearFiniBB(builder, loopInfo->getExit());
4518 builder.SetInsertPoint(*regionBlock, (*regionBlock)->begin());
4521 bool noLoopMode =
false;
4522 omp::TargetOp targetOp = wsloopOp->getParentOfType<mlir::omp::TargetOp>();
4524 targetOp.getKernelType() == omp::TargetExecMode::spmd_no_loop) {
4526 cast<omp::ComposableOpInterface>(*targetOp).findCapturedOp();
4530 if (loopOp == targetCapturedOp)
4534 for (
size_t index = 0;
index < wsloopOp.getLinearVars().size();
index++)
4535 linearClauseProcessor.rewriteInPlace(builder, loopInfo->getBody(),
4536 loopInfo->getLatch(),
index);
4538 llvm::OpenMPIRBuilder::InsertPointOrErrorTy wsloopIP =
4539 ompBuilder->applyWorkshareLoop(
4540 ompLoc.DL, loopInfo, allocaIP, loopNeedsBarrier,
4541 convertToScheduleKind(schedule), chunk, isSimd,
4542 scheduleMod == omp::ScheduleModifier::monotonic,
4543 scheduleMod == omp::ScheduleModifier::nonmonotonic, isOrdered,
4544 workshareLoopType, noLoopMode, hasDistSchedule, distScheduleChunk);
4550 if (!wsloopOp.getLinearVars().empty()) {
4551 llvm::OpenMPIRBuilder::InsertPointTy oldIP = builder.saveIP();
4552 assert(loopInfo->getLastIter() &&
4553 "`lastiter` in CanonicalLoopInfo is nullptr");
4554 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterBarrierIP =
4555 linearClauseProcessor.finalizeLinearVar(builder, moduleTranslation,
4556 loopInfo->getLastIter());
4560 builder.restoreIP(oldIP);
4567 if (isTaskReductionMod)
4573 wsloopOp, builder, moduleTranslation, allocaIP, reductionDecls,
4574 privateReductionVariables, isByRef, wsloopOp.getNowait(),
4579 wsloopOp.getLoc(), privateVarsInfo);
4586 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4588 assert(isByRef.size() == opInst.getNumReductionVars());
4601 opInst.getNumReductionVars());
4607 bool isTaskReductionMod =
4608 opInst.getReductionMod() == omp::ReductionModifier::task &&
4609 opInst.getNumReductionVars() > 0;
4612 [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
4615 opInst, builder, moduleTranslation, privateVarsInfo, allocaIP);
4617 return llvm::make_error<PreviouslyReportedError>();
4623 cast<omp::BlockArgOpenMPOpInterface>(*opInst).getReductionBlockArgs();
4626 InsertPointTy(allocaIP.getBlock(),
4627 allocaIP.getBlock()->getTerminator()->getIterator());
4630 opInst, reductionArgs, builder, moduleTranslation, allocaIP,
4631 reductionDecls, privateReductionVariables, reductionVariableMap,
4632 deferredStores, isByRef)))
4633 return llvm::make_error<PreviouslyReportedError>();
4635 assert(afterAllocas.get()->getSinglePredecessor());
4636 builder.restoreIP(codeGenIP);
4642 return llvm::make_error<PreviouslyReportedError>();
4645 opInst, builder, moduleTranslation, privateVarsInfo.
mlirVars,
4647 opInst.getPrivateNeedsBarrier())))
4648 return llvm::make_error<PreviouslyReportedError>();
4651 initReductionVars(opInst, reductionArgs, builder, moduleTranslation,
4652 afterAllocas.get()->getSinglePredecessor(),
4653 reductionDecls, privateReductionVariables,
4654 reductionVariableMap, isByRef, deferredStores)))
4655 return llvm::make_error<PreviouslyReportedError>();
4660 if (isTaskReductionMod &&
4662 "__omp_taskred_mod_", builder, allocaIP,
4663 moduleTranslation,
true,
4665 return llvm::createStringError(
4666 "failed to emit task reduction modifier initialization");
4671 moduleTranslation, allocaIP, deallocBlocks);
4675 opInst.getRegion(),
"omp.par.region", builder, moduleTranslation);
4677 return regionBlock.takeError();
4680 if (opInst.getNumReductionVars() > 0) {
4685 owningReductionGenRefDataPtrGens;
4687 collectReductionInfo(opInst, builder, moduleTranslation, reductionDecls,
4689 owningReductionGenRefDataPtrGens,
4690 privateReductionVariables, reductionInfos, isByRef);
4693 builder.SetInsertPoint((*regionBlock)->getTerminator());
4697 if (isTaskReductionMod)
4702 llvm::UnreachableInst *tempTerminator = builder.CreateUnreachable();
4703 builder.SetInsertPoint(tempTerminator);
4705 llvm::OpenMPIRBuilder::InsertPointOrErrorTy contInsertPoint =
4706 ompBuilder->createReductions(
4707 builder.saveIP(), allocaIP, reductionInfos, isByRef,
4709 if (!contInsertPoint)
4710 return contInsertPoint.takeError();
4712 if (!contInsertPoint->getBlock())
4713 return llvm::make_error<PreviouslyReportedError>();
4715 tempTerminator->eraseFromParent();
4716 builder.restoreIP(*contInsertPoint);
4719 return llvm::Error::success();
4722 auto privCB = [](InsertPointTy allocaIP, InsertPointTy codeGenIP,
4723 llvm::Value &, llvm::Value &val, llvm::Value *&replVal) {
4732 auto finiCB = [&](InsertPointTy codeGenIP) -> llvm::Error {
4733 InsertPointTy oldIP = builder.saveIP();
4734 builder.restoreIP(codeGenIP);
4739 llvm::transform(reductionDecls, std::back_inserter(reductionCleanupRegions),
4740 [](omp::DeclareReductionOp reductionDecl) {
4741 return &reductionDecl.getCleanupRegion();
4744 reductionCleanupRegions, privateReductionVariables,
4745 moduleTranslation, builder,
"omp.reduction.cleanup")))
4746 return llvm::createStringError(
4747 "failed to inline `cleanup` region of `omp.declare_reduction`");
4750 opInst.getLoc(), privateVarsInfo)))
4751 return llvm::make_error<PreviouslyReportedError>();
4755 if (isCancellable) {
4756 auto IPOrErr = ompBuilder->createBarrier(
4757 llvm::OpenMPIRBuilder::LocationDescription(builder),
4758 llvm::omp::Directive::OMPD_unknown,
4762 return IPOrErr.takeError();
4765 builder.restoreIP(oldIP);
4766 return llvm::Error::success();
4769 llvm::Value *ifCond =
nullptr;
4770 if (
auto ifVar = opInst.getIfExpr())
4772 llvm::Value *numThreads =
nullptr;
4773 if (!opInst.getNumThreadsVars().empty())
4774 numThreads = moduleTranslation.
lookupValue(opInst.getNumThreads(0));
4775 auto pbKind = llvm::omp::OMP_PROC_BIND_default;
4776 if (
auto bind = opInst.getProcBindKind())
4780 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
4782 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4784 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
4785 ompBuilder->createParallel(ompLoc, allocaIP, deallocBlocks, bodyGenCB,
4786 privCB, finiCB, ifCond, numThreads, pbKind,
4792 builder.restoreIP(*afterIP);
4797static llvm::omp::OrderKind
4800 return llvm::omp::OrderKind::OMP_ORDER_unknown;
4802 case omp::ClauseOrderKind::Concurrent:
4803 return llvm::omp::OrderKind::OMP_ORDER_concurrent;
4805 llvm_unreachable(
"Unknown ClauseOrderKind kind");
4813 auto simdOp = cast<omp::SimdOp>(opInst);
4821 cast<omp::BlockArgOpenMPOpInterface>(opInst).getReductionBlockArgs();
4824 simdOp.getNumReductionVars());
4829 assert(isByRef.size() == simdOp.getNumReductionVars());
4831 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
4835 simdOp, builder, moduleTranslation, privateVarsInfo, allocaIP);
4840 LinearClauseProcessor linearClauseProcessor;
4842 if (!simdOp.getLinearVars().empty()) {
4843 auto linearVarTypes = simdOp.getLinearVarTypes().value();
4845 linearClauseProcessor.registerType(moduleTranslation, linearVarType);
4846 for (
auto [idx, linearVar] : llvm::enumerate(simdOp.getLinearVars())) {
4847 bool isImplicit =
false;
4848 for (
auto [mlirPrivVar, llvmPrivateVar] : llvm::zip_equal(
4852 if (linearVar == mlirPrivVar) {
4854 linearClauseProcessor.createLinearVar(builder, moduleTranslation,
4855 llvmPrivateVar, idx);
4861 linearClauseProcessor.createLinearVar(
4862 builder, moduleTranslation,
4865 for (
mlir::Value linearStep : simdOp.getLinearStepVars())
4866 linearClauseProcessor.initLinearStep(moduleTranslation, linearStep);
4870 moduleTranslation, allocaIP, reductionDecls,
4871 privateReductionVariables, reductionVariableMap,
4872 deferredStores, isByRef)))
4883 assert(afterAllocas.get()->getSinglePredecessor());
4884 if (failed(initReductionVars(simdOp, reductionArgs, builder,
4886 afterAllocas.get()->getSinglePredecessor(),
4887 reductionDecls, privateReductionVariables,
4888 reductionVariableMap, isByRef, deferredStores)))
4891 llvm::ConstantInt *simdlen =
nullptr;
4892 if (std::optional<uint64_t> simdlenVar = simdOp.getSimdlen())
4893 simdlen = builder.getInt64(simdlenVar.value());
4895 llvm::ConstantInt *safelen =
nullptr;
4896 if (std::optional<uint64_t> safelenVar = simdOp.getSafelen())
4897 safelen = builder.getInt64(safelenVar.value());
4899 llvm::MapVector<llvm::Value *, llvm::Value *> alignedVars;
4902 llvm::BasicBlock *sourceBlock = builder.GetInsertBlock();
4903 std::optional<ArrayAttr> alignmentValues = simdOp.getAlignments();
4905 for (
size_t i = 0; i < operands.size(); ++i) {
4906 llvm::Value *alignment =
nullptr;
4907 llvm::Value *llvmVal = moduleTranslation.
lookupValue(operands[i]);
4908 llvm::Type *ty = llvmVal->getType();
4910 auto intAttr = cast<IntegerAttr>((*alignmentValues)[i]);
4911 alignment = builder.getInt64(intAttr.getInt());
4912 assert(ty->isPointerTy() &&
"Invalid type for aligned variable");
4913 assert(alignment &&
"Invalid alignment value");
4917 if (!intAttr.getValue().isPowerOf2())
4920 auto curInsert = builder.saveIP();
4921 builder.SetInsertPoint(sourceBlock);
4922 llvmVal = builder.CreateLoad(ty, llvmVal);
4923 builder.restoreIP(curInsert);
4924 alignedVars[llvmVal] = alignment;
4928 simdOp.getRegion(),
"omp.simd.region", builder, moduleTranslation);
4935 if (simdOp.getLinearVars().size()) {
4936 linearClauseProcessor.initLinearVar(builder, moduleTranslation,
4937 loopInfo->getPreheader());
4939 linearClauseProcessor.updateLinearVar(builder, loopInfo->getBody(),
4940 loopInfo->getIndVar());
4942 builder.SetInsertPoint(*regionBlock, (*regionBlock)->begin());
4944 for (
size_t index = 0;
index < simdOp.getLinearVars().size();
index++)
4945 linearClauseProcessor.rewriteInPlace(builder, loopInfo->getBody(),
4946 loopInfo->getLatch(),
index);
4948 ompBuilder->applySimd(loopInfo, alignedVars,
4950 ? moduleTranslation.
lookupValue(simdOp.getIfExpr())
4952 order, simdlen, safelen);
4954 linearClauseProcessor.emitStoresForLinearVar(builder);
4960 for (
auto [i, tuple] : llvm::enumerate(
4961 llvm::zip(reductionDecls, isByRef, simdOp.getReductionVars(),
4962 privateReductionVariables))) {
4963 auto [decl, byRef, reductionVar, privateReductionVar] = tuple;
4965 OwningReductionGen gen =
makeReductionGen(decl, builder, moduleTranslation);
4966 llvm::Value *originalVariable = moduleTranslation.
lookupValue(reductionVar);
4967 llvm::Type *reductionType = moduleTranslation.
convertType(decl.getType());
4971 llvm::Value *redValue = originalVariable;
4974 builder.CreateLoad(reductionType, redValue,
"red.value." + Twine(i));
4975 llvm::Value *privateRedValue = builder.CreateLoad(
4976 reductionType, privateReductionVar,
"red.private.value." + Twine(i));
4977 llvm::Value *reduced;
4979 auto res = gen(builder.saveIP(), redValue, privateRedValue, reduced);
4982 builder.restoreIP(res.get());
4986 builder.CreateStore(reduced, originalVariable);
4991 llvm::transform(reductionDecls, std::back_inserter(reductionRegions),
4992 [](omp::DeclareReductionOp reductionDecl) {
4993 return &reductionDecl.getCleanupRegion();
4996 moduleTranslation, builder,
4997 "omp.reduction.cleanup")))
5009 auto loopOp = cast<omp::LoopNestOp>(opInst);
5015 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5020 auto bodyGen = [&](llvm::OpenMPIRBuilder::InsertPointTy ip,
5021 llvm::Value *iv) -> llvm::Error {
5024 loopOp.getRegion().front().getArgument(loopInfos.size()), iv);
5029 bodyInsertPoints.push_back(ip);
5031 if (loopInfos.size() != loopOp.getNumLoops() - 1)
5032 return llvm::Error::success();
5035 builder.restoreIP(ip);
5037 loopOp.getRegion(),
"omp.loop_nest.region", builder, moduleTranslation);
5039 return regionBlock.takeError();
5041 builder.SetInsertPoint(*regionBlock, (*regionBlock)->begin());
5042 return llvm::Error::success();
5050 for (
unsigned i = 0, e = loopOp.getNumLoops(); i < e; ++i) {
5051 llvm::Value *lowerBound =
5052 moduleTranslation.
lookupValue(loopOp.getLoopLowerBounds()[i]);
5053 llvm::Value *upperBound =
5054 moduleTranslation.
lookupValue(loopOp.getLoopUpperBounds()[i]);
5055 llvm::Value *step = moduleTranslation.
lookupValue(loopOp.getLoopSteps()[i]);
5060 llvm::OpenMPIRBuilder::LocationDescription loc = ompLoc;
5061 llvm::OpenMPIRBuilder::InsertPointTy computeIP = ompLoc.IP;
5063 loc = llvm::OpenMPIRBuilder::LocationDescription(bodyInsertPoints.back(),
5065 computeIP = loopInfos.front()->getPreheaderIP();
5069 ompBuilder->createCanonicalLoop(
5070 loc, bodyGen, lowerBound, upperBound, step,
5071 true, loopOp.getLoopInclusive(), computeIP);
5076 loopInfos.push_back(*loopResult);
5079 llvm::OpenMPIRBuilder::InsertPointTy afterIP =
5080 loopInfos.front()->getAfterIP();
5083 if (
const auto &tiles = loopOp.getTileSizes()) {
5084 llvm::Type *ivType = loopInfos.front()->getIndVarType();
5087 for (
auto tile : tiles.value()) {
5088 llvm::Value *tileVal = llvm::ConstantInt::get(ivType,
tile);
5089 tileSizes.push_back(tileVal);
5092 std::vector<llvm::CanonicalLoopInfo *> newLoops =
5093 ompBuilder->tileLoops(ompLoc.DL, loopInfos, tileSizes);
5097 llvm::BasicBlock *afterBB = newLoops.front()->getAfter();
5098 llvm::BasicBlock *afterAfterBB = afterBB->getSingleSuccessor();
5099 afterIP = {afterAfterBB, afterAfterBB->begin()};
5103 for (
const auto &newLoop : newLoops)
5104 loopInfos.push_back(newLoop);
5108 const auto &numCollapse = loopOp.getCollapseNumLoops();
5110 loopInfos.begin(), loopInfos.begin() + (numCollapse));
5112 auto newTopLoopInfo =
5113 ompBuilder->collapseLoops(ompLoc.DL, collapseLoopInfos, {});
5115 assert(newTopLoopInfo &&
"New top loop information is missing");
5116 moduleTranslation.
stackWalk<OpenMPLoopInfoStackFrame>(
5117 [&](OpenMPLoopInfoStackFrame &frame) {
5118 frame.loopInfo = newTopLoopInfo;
5126 builder.restoreIP(afterIP);
5136 llvm::OpenMPIRBuilder::LocationDescription loopLoc(builder);
5137 Value loopIV = op.getInductionVar();
5138 Value loopTC = op.getTripCount();
5140 llvm::Value *llvmTC = moduleTranslation.
lookupValue(loopTC);
5143 ompBuilder->createCanonicalLoop(
5145 [&](llvm::OpenMPIRBuilder::InsertPointTy ip, llvm::Value *llvmIV) {
5148 moduleTranslation.
mapValue(loopIV, llvmIV);
5150 builder.restoreIP(ip);
5155 return bodyGenStatus.takeError();
5157 llvmTC,
"omp.loop");
5159 return op.emitError(llvm::toString(llvmOrError.takeError()));
5161 llvm::CanonicalLoopInfo *llvmCLI = *llvmOrError;
5162 llvm::IRBuilderBase::InsertPoint afterIP = llvmCLI->getAfterIP();
5163 builder.restoreIP(afterIP);
5166 if (
Value cli = op.getCli())
5179 Value applyee = op.getApplyee();
5180 assert(applyee &&
"Loop to apply unrolling on required");
5182 llvm::CanonicalLoopInfo *consBuilderCLI =
5184 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
5185 ompBuilder->unrollLoopHeuristic(loc.DL, consBuilderCLI);
5193static LogicalResult
applyTile(omp::TileOp op, llvm::IRBuilderBase &builder,
5196 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
5201 for (
Value size : op.getSizes()) {
5202 llvm::Value *translatedSize = moduleTranslation.
lookupValue(size);
5203 assert(translatedSize &&
5204 "sizes clause arguments must already be translated");
5205 translatedSizes.push_back(translatedSize);
5208 for (
Value applyee : op.getApplyees()) {
5209 llvm::CanonicalLoopInfo *consBuilderCLI =
5211 assert(applyee &&
"Canonical loop must already been translated");
5212 translatedLoops.push_back(consBuilderCLI);
5215 auto generatedLoops =
5216 ompBuilder->tileLoops(loc.DL, translatedLoops, translatedSizes);
5217 if (!op.getGeneratees().empty()) {
5218 for (
auto [mlirLoop,
genLoop] :
5219 zip_equal(op.getGeneratees(), generatedLoops))
5224 for (
Value applyee : op.getApplyees())
5232static LogicalResult
applyFuse(omp::FuseOp op, llvm::IRBuilderBase &builder,
5235 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
5239 for (
size_t i = 0; i < op.getApplyees().size(); i++) {
5240 Value applyee = op.getApplyees()[i];
5241 llvm::CanonicalLoopInfo *consBuilderCLI =
5243 assert(applyee &&
"Canonical loop must already been translated");
5244 if (op.getFirst().has_value() && i < op.getFirst().value() - 1)
5245 beforeFuse.push_back(consBuilderCLI);
5246 else if (op.getCount().has_value() &&
5247 i >= op.getFirst().value() + op.getCount().value() - 1)
5248 afterFuse.push_back(consBuilderCLI);
5250 toFuse.push_back(consBuilderCLI);
5253 (op.getGeneratees().empty() ||
5254 beforeFuse.size() + afterFuse.size() + 1 == op.getGeneratees().size()) &&
5255 "Wrong number of generatees");
5258 auto generatedLoop = ompBuilder->fuseLoops(loc.DL, toFuse);
5259 if (!op.getGeneratees().empty()) {
5261 for (; i < beforeFuse.size(); i++)
5262 moduleTranslation.
mapOmpLoop(op.getGeneratees()[i], beforeFuse[i]);
5263 moduleTranslation.
mapOmpLoop(op.getGeneratees()[i++], generatedLoop);
5264 for (; i < afterFuse.size(); i++)
5265 moduleTranslation.
mapOmpLoop(op.getGeneratees()[i], afterFuse[i]);
5269 for (
Value applyee : op.getApplyees())
5276static llvm::AtomicOrdering
5279 return llvm::AtomicOrdering::Monotonic;
5282 case omp::ClauseMemoryOrderKind::Seq_cst:
5283 return llvm::AtomicOrdering::SequentiallyConsistent;
5284 case omp::ClauseMemoryOrderKind::Acq_rel:
5285 return llvm::AtomicOrdering::AcquireRelease;
5286 case omp::ClauseMemoryOrderKind::Acquire:
5287 return llvm::AtomicOrdering::Acquire;
5288 case omp::ClauseMemoryOrderKind::Release:
5289 return llvm::AtomicOrdering::Release;
5290 case omp::ClauseMemoryOrderKind::Relaxed:
5291 return llvm::AtomicOrdering::Monotonic;
5293 llvm_unreachable(
"Unknown ClauseMemoryOrderKind kind");
5300 auto readOp = cast<omp::AtomicReadOp>(opInst);
5305 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
5308 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5311 llvm::Value *x = moduleTranslation.
lookupValue(readOp.getX());
5312 llvm::Value *v = moduleTranslation.
lookupValue(readOp.getV());
5314 llvm::Type *elementType =
5315 moduleTranslation.
convertType(readOp.getElementType());
5317 llvm::OpenMPIRBuilder::AtomicOpValue V = {v, elementType,
false,
false};
5318 llvm::OpenMPIRBuilder::AtomicOpValue X = {x, elementType,
false,
false};
5319 builder.restoreIP(ompBuilder->createAtomicRead(ompLoc, X, V, AO, allocaIP));
5327 auto writeOp = cast<omp::AtomicWriteOp>(opInst);
5332 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
5335 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5337 llvm::Value *expr = moduleTranslation.
lookupValue(writeOp.getExpr());
5338 llvm::Value *dest = moduleTranslation.
lookupValue(writeOp.getX());
5339 llvm::Type *ty = moduleTranslation.
convertType(writeOp.getExpr().getType());
5340 llvm::OpenMPIRBuilder::AtomicOpValue x = {dest, ty,
false,
5343 ompBuilder->createAtomicWrite(ompLoc, x, expr, ao, allocaIP));
5351 .Case([&](LLVM::AddOp) {
return llvm::AtomicRMWInst::BinOp::Add; })
5352 .Case([&](LLVM::SubOp) {
return llvm::AtomicRMWInst::BinOp::Sub; })
5353 .Case([&](LLVM::AndOp) {
return llvm::AtomicRMWInst::BinOp::And; })
5354 .Case([&](LLVM::OrOp) {
return llvm::AtomicRMWInst::BinOp::Or; })
5355 .Case([&](LLVM::XOrOp) {
return llvm::AtomicRMWInst::BinOp::Xor; })
5356 .Case([&](LLVM::UMaxOp) {
return llvm::AtomicRMWInst::BinOp::UMax; })
5357 .Case([&](LLVM::UMinOp) {
return llvm::AtomicRMWInst::BinOp::UMin; })
5358 .Case([&](LLVM::FAddOp) {
return llvm::AtomicRMWInst::BinOp::FAdd; })
5359 .Case([&](LLVM::FSubOp) {
return llvm::AtomicRMWInst::BinOp::FSub; })
5360 .Default(llvm::AtomicRMWInst::BinOp::BAD_BINOP);
5364 bool &isIgnoreDenormalMode,
5365 bool &isFineGrainedMemory,
5366 bool &isRemoteMemory) {
5367 isIgnoreDenormalMode =
false;
5368 isFineGrainedMemory =
false;
5369 isRemoteMemory =
false;
5370 if (atomicUpdateOp &&
5371 atomicUpdateOp->hasAttr(atomicUpdateOp.getAtomicControlAttrName())) {
5372 mlir::omp::AtomicControlAttr atomicControlAttr =
5373 atomicUpdateOp.getAtomicControlAttr();
5374 isIgnoreDenormalMode = atomicControlAttr.getIgnoreDenormalMode();
5375 isFineGrainedMemory = atomicControlAttr.getFineGrainedMemory();
5376 isRemoteMemory = atomicControlAttr.getRemoteMemory();
5383 llvm::IRBuilderBase &builder,
5390 auto &innerOpList = opInst.getRegion().front().getOperations();
5391 bool isXBinopExpr{
false};
5392 llvm::AtomicRMWInst::BinOp binop;
5394 llvm::Value *llvmExpr =
nullptr;
5395 llvm::Value *llvmX =
nullptr;
5396 llvm::Type *llvmXElementType =
nullptr;
5397 if (innerOpList.size() == 2) {
5403 opInst.getRegion().getArgument(0))) {
5404 return opInst.emitError(
"no atomic update operation with region argument"
5405 " as operand found inside atomic.update region");
5408 isXBinopExpr = innerOp.
getOperand(0) == opInst.getRegion().getArgument(0);
5410 llvmExpr = moduleTranslation.
lookupValue(mlirExpr);
5414 binop = llvm::AtomicRMWInst::BinOp::BAD_BINOP;
5416 llvmX = moduleTranslation.
lookupValue(opInst.getX());
5418 opInst.getRegion().getArgument(0).getType());
5419 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {llvmX, llvmXElementType,
5423 llvm::AtomicOrdering atomicOrdering =
5428 [&opInst, &moduleTranslation](
5429 llvm::Value *atomicx,
5432 moduleTranslation.
mapValue(*opInst.getRegion().args_begin(), atomicx);
5433 moduleTranslation.
mapBlock(&bb, builder.GetInsertBlock());
5434 if (failed(moduleTranslation.
convertBlock(bb,
true, builder)))
5435 return llvm::make_error<PreviouslyReportedError>();
5437 omp::YieldOp yieldop = dyn_cast<omp::YieldOp>(bb.
getTerminator());
5438 assert(yieldop && yieldop.getResults().size() == 1 &&
5439 "terminator must be omp.yield op and it must have exactly one "
5441 return moduleTranslation.
lookupValue(yieldop.getResults()[0]);
5444 bool isIgnoreDenormalMode;
5445 bool isFineGrainedMemory;
5446 bool isRemoteMemory;
5451 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5452 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
5453 ompBuilder->createAtomicUpdate(ompLoc, allocaIP, llvmAtomicX, llvmExpr,
5454 atomicOrdering, binop, updateFn,
5455 isXBinopExpr, isIgnoreDenormalMode,
5456 isFineGrainedMemory, isRemoteMemory);
5461 builder.restoreIP(*afterIP);
5467 llvm::IRBuilderBase &builder,
5474 bool isXBinopExpr =
false, isPostfixUpdate =
false;
5475 llvm::AtomicRMWInst::BinOp binop = llvm::AtomicRMWInst::BinOp::BAD_BINOP;
5477 omp::AtomicUpdateOp atomicUpdateOp = atomicCaptureOp.getAtomicUpdateOp();
5478 omp::AtomicWriteOp atomicWriteOp = atomicCaptureOp.getAtomicWriteOp();
5480 assert((atomicUpdateOp || atomicWriteOp) &&
5481 "internal op must be an atomic.update or atomic.write op");
5483 if (atomicWriteOp) {
5484 isPostfixUpdate =
true;
5485 mlirExpr = atomicWriteOp.getExpr();
5487 isPostfixUpdate = atomicCaptureOp.getSecondOp() ==
5488 atomicCaptureOp.getAtomicUpdateOp().getOperation();
5489 auto &innerOpList = atomicUpdateOp.getRegion().front().getOperations();
5492 if (innerOpList.size() == 2) {
5495 atomicUpdateOp.getRegion().getArgument(0))) {
5496 return atomicUpdateOp.emitError(
5497 "no atomic update operation with region argument"
5498 " as operand found inside atomic.update region");
5502 innerOp.
getOperand(0) == atomicUpdateOp.getRegion().getArgument(0);
5505 binop = llvm::AtomicRMWInst::BinOp::BAD_BINOP;
5509 llvm::Value *llvmExpr = moduleTranslation.
lookupValue(mlirExpr);
5510 llvm::Value *llvmX =
5511 moduleTranslation.
lookupValue(atomicCaptureOp.getAtomicReadOp().getX());
5512 llvm::Value *llvmV =
5513 moduleTranslation.
lookupValue(atomicCaptureOp.getAtomicReadOp().getV());
5514 llvm::Type *llvmXElementType = moduleTranslation.
convertType(
5515 atomicCaptureOp.getAtomicReadOp().getElementType());
5516 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {llvmX, llvmXElementType,
5519 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicV = {llvmV, llvmXElementType,
5523 llvm::AtomicOrdering atomicOrdering =
5527 [&](llvm::Value *atomicx,
5530 return moduleTranslation.
lookupValue(atomicWriteOp.getExpr());
5531 Block &bb = *atomicUpdateOp.getRegion().
begin();
5532 moduleTranslation.
mapValue(*atomicUpdateOp.getRegion().args_begin(),
5534 moduleTranslation.
mapBlock(&bb, builder.GetInsertBlock());
5535 if (failed(moduleTranslation.
convertBlock(bb,
true, builder)))
5536 return llvm::make_error<PreviouslyReportedError>();
5538 omp::YieldOp yieldop = dyn_cast<omp::YieldOp>(bb.
getTerminator());
5539 assert(yieldop && yieldop.getResults().size() == 1 &&
5540 "terminator must be omp.yield op and it must have exactly one "
5542 return moduleTranslation.
lookupValue(yieldop.getResults()[0]);
5545 bool isIgnoreDenormalMode;
5546 bool isFineGrainedMemory;
5547 bool isRemoteMemory;
5549 isFineGrainedMemory, isRemoteMemory);
5552 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5553 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
5554 ompBuilder->createAtomicCapture(
5555 ompLoc, allocaIP, llvmAtomicX, llvmAtomicV, llvmExpr, atomicOrdering,
5556 binop, updateFn, atomicUpdateOp, isPostfixUpdate, isXBinopExpr,
5557 isIgnoreDenormalMode, isFineGrainedMemory, isRemoteMemory);
5559 if (failed(
handleError(afterIP, *atomicCaptureOp)))
5562 builder.restoreIP(*afterIP);
5568static std::optional<llvm::omp::OMPAtomicCompareOp>
5570 switch (predicate) {
5571 case LLVM::ICmpPredicate::eq:
5572 return llvm::omp::OMPAtomicCompareOp::EQ;
5573 case LLVM::ICmpPredicate::slt:
5574 case LLVM::ICmpPredicate::ult:
5575 return llvm::omp::OMPAtomicCompareOp::MIN;
5576 case LLVM::ICmpPredicate::sgt:
5577 case LLVM::ICmpPredicate::ugt:
5578 return llvm::omp::OMPAtomicCompareOp::MAX;
5580 return std::nullopt;
5586static std::optional<llvm::omp::OMPAtomicCompareOp>
5588 switch (predicate) {
5589 case LLVM::FCmpPredicate::oeq:
5590 case LLVM::FCmpPredicate::ueq:
5591 return llvm::omp::OMPAtomicCompareOp::EQ;
5592 case LLVM::FCmpPredicate::olt:
5593 case LLVM::FCmpPredicate::ult:
5594 return llvm::omp::OMPAtomicCompareOp::MIN;
5595 case LLVM::FCmpPredicate::ogt:
5596 case LLVM::FCmpPredicate::ugt:
5597 return llvm::omp::OMPAtomicCompareOp::MAX;
5599 return std::nullopt;
5621 llvm::IRBuilderBase &builder,
5627 Region ®ion = atomicCompareOp.getRegion();
5631 llvm::Type *llvmXElementType =
5633 if (!llvmXElementType)
5634 return atomicCompareOp.emitError(
5635 "unable to determine element type for atomic compare");
5637 llvm::Value *llvmX = moduleTranslation.
lookupValue(atomicCompareOp.getX());
5642 bool isSigned =
false;
5643 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {llvmX, llvmXElementType,
5647 llvm::AtomicOrdering atomicOrdering =
5650 auto isAtomicComparePatternOp = [](
Operation &op) {
5651 return llvm::isa<LLVM::ICmpOp, LLVM::FCmpOp, LLVM::SelectOp, LLVM::AndOp,
5672 if (isAtomicComparePatternOp(op))
5677 return moduleTranslation.lookupValue(v) != nullptr;
5679 if (!allOperandsMapped)
5683 return atomicCompareOp.emitError(
5684 "failed to translate operation inside atomic compare region");
5689 auto materializeValue = [&](
mlir::Value val) -> llvm::Value * {
5691 if (llvm::Value *existing = moduleTranslation.
lookupValue(val))
5696 if (loadOp->getParentRegion() == ®ion) {
5697 llvm::Value *loadAddr = moduleTranslation.
lookupValue(loadOp.getAddr());
5700 llvm::Type *loadType =
5701 moduleTranslation.
convertType(loadOp.getResult().getType());
5702 return builder.CreateLoad(loadType, loadAddr);
5710 llvm::omp::OMPAtomicCompareOp compareOp = llvm::omp::OMPAtomicCompareOp::EQ;
5711 llvm::Value *eVal =
nullptr;
5712 llvm::Value *dVal =
nullptr;
5713 bool isXBinopExpr =
false;
5716 if (
auto extractOp = v.getDefiningOp<LLVM::ExtractValueOp>())
5717 return extractOp.getContainer();
5731 bool isComplexPattern =
false;
5733 if (!isa<LLVM::AndOp, LLVM::OrOp>(op))
5739 if (!lhsFcmp || !rhsFcmp)
5744 mlir::Value lhsAgg0 = traceToAggregate(lhsFcmp.getOperand(0));
5745 mlir::Value lhsAgg1 = traceToAggregate(lhsFcmp.getOperand(1));
5746 bool lhsXIsOp0 = (lhsAgg0 == block.
getArgument(0));
5747 bool lhsXIsOp1 = (lhsAgg1 == block.
getArgument(0));
5748 if (!lhsXIsOp0 && !lhsXIsOp1)
5750 mlir::Value eAggregate = lhsXIsOp0 ? lhsAgg1 : lhsAgg0;
5754 if (isa<LLVM::AndOp>(op))
5755 compareOp = llvm::omp::OMPAtomicCompareOp::EQ;
5758 return atomicCompareOp.emitError(
5759 "unsupported comparison predicate (NE) for complex atomic compare");
5761 isXBinopExpr = lhsXIsOp0;
5762 eVal = materializeValue(eAggregate);
5763 isComplexPattern =
true;
5767 if (isComplexPattern) {
5770 if (
auto selectOp = dyn_cast<LLVM::SelectOp>(op)) {
5771 dVal = materializeValue(selectOp.getTrueValue());
5777 if (yieldOp.getResults().empty())
5778 return atomicCompareOp.emitError(
5779 "failed to extract desired value (d) from atomic compare region");
5780 dVal = materializeValue(yieldOp.getResults()[0]);
5783 const llvm::DataLayout &DL =
5784 builder.GetInsertBlock()->getModule()->getDataLayout();
5785 unsigned totalBits =
5786 DL.getTypeStoreSizeInBits(llvmXElementType).getFixedValue();
5788 llvm::IntegerType *intTy =
5789 llvm::IntegerType::get(builder.getContext(), totalBits);
5791 llvm::Align complexAlign = DL.getABITypeAlign(llvmXElementType);
5792 llvm::Align intAlign = DL.getABITypeAlign(intTy);
5793 llvm::Align maxAlign = std::max(complexAlign, intAlign);
5795 llvm::AllocaInst *eAlloca =
5796 builder.CreateAlloca(llvmXElementType,
nullptr,
"cmplx.e");
5797 eAlloca->setAlignment(maxAlign);
5798 llvm::AllocaInst *dAlloca =
5799 builder.CreateAlloca(llvmXElementType,
nullptr,
"cmplx.d");
5800 dAlloca->setAlignment(maxAlign);
5802 builder.CreateAlignedStore(eVal, eAlloca, maxAlign);
5804 builder.CreateAlignedLoad(intTy, eAlloca, maxAlign,
"cmplx.e.int");
5805 builder.CreateAlignedStore(dVal, dAlloca, maxAlign);
5807 builder.CreateAlignedLoad(intTy, dAlloca, maxAlign,
"cmplx.d.int");
5809 llvm::AtomicOrdering failOrdering =
5810 llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(atomicOrdering);
5811 auto *cmpXchg = builder.CreateAtomicCmpXchg(llvmX, eInt, dInt, maxAlign,
5812 atomicOrdering, failOrdering);
5813 cmpXchg->setWeak(atomicCompareOp.getWeak());
5817 if (atomicOrdering == llvm::AtomicOrdering::Release ||
5818 atomicOrdering == llvm::AtomicOrdering::AcquireRelease ||
5819 atomicOrdering == llvm::AtomicOrdering::SequentiallyConsistent) {
5820 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5821 ompBuilder->createFlush(ompLoc);
5827 if (
auto icmpOp = dyn_cast<LLVM::ICmpOp>(op)) {
5831 return atomicCompareOp.emitError(
5832 "unsupported comparison predicate in atomic compare");
5833 compareOp = *maybeOp;
5835 LLVM::ICmpPredicate pred = icmpOp.getPredicate();
5836 isSigned = (pred == LLVM::ICmpPredicate::slt ||
5837 pred == LLVM::ICmpPredicate::sgt ||
5838 pred == LLVM::ICmpPredicate::sle ||
5839 pred == LLVM::ICmpPredicate::sge);
5842 isXBinopExpr = (icmpOp.getOperand(0) == block.
getArgument(0));
5844 isXBinopExpr ? icmpOp.getOperand(1) : icmpOp.getOperand(0);
5845 eVal = materializeValue(eOperand);
5846 }
else if (
auto fcmpOp = dyn_cast<LLVM::FCmpOp>(op)) {
5850 return atomicCompareOp.emitError(
5851 "unsupported comparison predicate in atomic compare");
5852 compareOp = *maybeOp;
5854 isXBinopExpr = (fcmpOp.getOperand(0) == block.
getArgument(0));
5856 isXBinopExpr ? fcmpOp.getOperand(1) : fcmpOp.getOperand(0);
5857 eVal = materializeValue(eOperand);
5858 }
else if (
auto selectOp = dyn_cast<LLVM::SelectOp>(op)) {
5860 dVal = materializeValue(selectOp.getTrueValue());
5868 if (
auto selectOp = dyn_cast<LLVM::SelectOp>(op)) {
5869 dVal = materializeValue(selectOp.getTrueValue());
5876 return atomicCompareOp.emitError(
5877 "failed to extract expected value (e) from atomic compare region");
5881 if (yieldOp.getResults().empty())
5882 return atomicCompareOp.emitError(
5883 "failed to extract desired value (d) from atomic compare region");
5884 dVal = materializeValue(yieldOp.getResults()[0]);
5887 llvmAtomicX.IsSigned = isSigned;
5889 llvm::OpenMPIRBuilder::AtomicOpValue vOpVal = {
nullptr,
nullptr,
false,
5891 llvm::OpenMPIRBuilder::AtomicOpValue rOpVal = {
nullptr,
nullptr,
false,
5893 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5895 bool isWeak = atomicCompareOp.getWeak();
5897 bool savedHandleFPNegZero = ompBuilder->setHandleFPNegZero(
true);
5898 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
5899 ompBuilder->createAtomicCompare(ompLoc, llvmAtomicX, vOpVal, rOpVal, eVal,
5900 dVal, atomicOrdering, compareOp,
5901 isXBinopExpr,
false,
false, isWeak);
5902 ompBuilder->setHandleFPNegZero(savedHandleFPNegZero);
5904 if (failed(
handleError(afterIP, *atomicCompareOp)))
5907 builder.restoreIP(*afterIP);
5912 omp::ClauseCancellationConstructType directive) {
5913 switch (directive) {
5914 case omp::ClauseCancellationConstructType::Loop:
5915 return llvm::omp::Directive::OMPD_for;
5916 case omp::ClauseCancellationConstructType::Parallel:
5917 return llvm::omp::Directive::OMPD_parallel;
5918 case omp::ClauseCancellationConstructType::Sections:
5919 return llvm::omp::Directive::OMPD_sections;
5920 case omp::ClauseCancellationConstructType::Taskgroup:
5921 return llvm::omp::Directive::OMPD_taskgroup;
5923 llvm_unreachable(
"Unhandled cancellation construct type");
5932 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5935 llvm::Value *ifCond =
nullptr;
5936 if (
Value ifVar = op.getIfExpr())
5939 llvm::omp::Directive cancelledDirective =
5942 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
5943 ompBuilder->createCancel(ompLoc, ifCond, cancelledDirective);
5945 if (failed(
handleError(afterIP, *op.getOperation())))
5948 builder.restoreIP(afterIP.get());
5955 llvm::IRBuilderBase &builder,
5960 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5963 llvm::omp::Directive cancelledDirective =
5966 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
5967 ompBuilder->createCancellationPoint(ompLoc, cancelledDirective);
5969 if (failed(
handleError(afterIP, *op.getOperation())))
5972 builder.restoreIP(afterIP.get());
5982 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5984 auto threadprivateOp = cast<omp::ThreadprivateOp>(opInst);
5989 Value symAddr = threadprivateOp.getSymAddr();
5992 if (
auto asCast = dyn_cast<LLVM::AddrSpaceCastOp>(symOp))
5995 if (!isa<LLVM::AddressOfOp>(symOp))
5996 return opInst.
emitError(
"Addressing symbol not found");
5997 LLVM::AddressOfOp addressOfOp = dyn_cast<LLVM::AddressOfOp>(symOp);
5999 LLVM::GlobalOp global =
6000 addressOfOp.getGlobal(moduleTranslation.
symbolTable());
6001 llvm::GlobalValue *globalValue = moduleTranslation.
lookupGlobal(global);
6002 llvm::Type *type = globalValue->getValueType();
6003 llvm::TypeSize typeSize =
6004 builder.GetInsertBlock()->getModule()->getDataLayout().getTypeStoreSize(
6006 llvm::ConstantInt *size = builder.getInt64(typeSize.getFixedValue());
6007 llvm::Value *callInst = ompBuilder->createCachedThreadPrivate(
6008 ompLoc, globalValue, size, global.getSymName() +
".cache");
6014static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind
6016 switch (deviceClause) {
6017 case mlir::omp::DeclareTargetDeviceType::host:
6018 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseHost;
6020 case mlir::omp::DeclareTargetDeviceType::nohost:
6021 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNoHost;
6023 case mlir::omp::DeclareTargetDeviceType::any:
6024 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny;
6027 llvm_unreachable(
"unhandled device clause");
6030static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind
6032 mlir::omp::DeclareTargetCaptureClause captureClause) {
6033 switch (captureClause) {
6034 case mlir::omp::DeclareTargetCaptureClause::to:
6035 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo;
6036 case mlir::omp::DeclareTargetCaptureClause::link:
6037 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink;
6038 case mlir::omp::DeclareTargetCaptureClause::enter:
6039 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter;
6040 case mlir::omp::DeclareTargetCaptureClause::none:
6041 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
6043 llvm_unreachable(
"unhandled capture clause");
6048 if (
auto addrCast = dyn_cast_if_present<LLVM::AddrSpaceCastOp>(op))
6050 if (
auto addressOfOp = dyn_cast_if_present<LLVM::AddressOfOp>(op)) {
6051 auto modOp = addressOfOp->getParentOfType<mlir::ModuleOp>();
6052 return modOp.lookupSymbol(addressOfOp.getGlobalName());
6059 if (
auto addrCast = dyn_cast_if_present<LLVM::AddrSpaceCastOp>(op))
6060 value = addrCast.getOperand();
6077static llvm::SmallString<64>
6079 llvm::OpenMPIRBuilder &ompBuilder,
6080 llvm::vfs::FileSystem &vfs) {
6082 llvm::raw_svector_ostream os(suffix);
6085 auto fileInfoCallBack = [&loc]() {
6086 return std::pair<std::string, uint64_t>(
6087 llvm::StringRef(loc.getFilename()), loc.getLine());
6092 ompBuilder.getTargetEntryUniqueInfo(fileInfoCallBack, vfs).FileID);
6094 os <<
"_decl_tgt_ref_ptr";
6100 if (
auto declareTargetGlobal =
6101 dyn_cast_if_present<omp::DeclareTargetInterface>(
6103 if (declareTargetGlobal.getDeclareTargetCaptureClause() ==
6104 omp::DeclareTargetCaptureClause::link)
6110 if (
auto declareTargetGlobal =
6111 dyn_cast_if_present<omp::DeclareTargetInterface>(
6113 if (declareTargetGlobal.getDeclareTargetCaptureClause() ==
6114 omp::DeclareTargetCaptureClause::to ||
6115 declareTargetGlobal.getDeclareTargetCaptureClause() ==
6116 omp::DeclareTargetCaptureClause::enter)
6134 ompBuilder->Config.hasRequiresUnifiedSharedMemory())) {
6138 if (gOp.getSymName().contains(suffix))
6143 (gOp.getSymName().str() + suffix.str()).str());
6151struct MapInfosTy : llvm::OpenMPIRBuilder::MapInfosTy {
6152 SmallVector<Operation *, 4> Mappers;
6155 void append(MapInfosTy &curInfo) {
6156 Mappers.append(curInfo.Mappers.begin(), curInfo.Mappers.end());
6157 llvm::OpenMPIRBuilder::MapInfosTy::append(curInfo);
6166struct MapInfoData : MapInfosTy {
6167 llvm::SmallVector<bool, 4> IsDeclareTarget;
6168 llvm::SmallVector<bool, 4> IsAMember;
6170 llvm::SmallVector<bool, 4> IsAMapping;
6171 llvm::SmallVector<mlir::Operation *, 4> MapClause;
6172 llvm::SmallVector<llvm::Value *, 4> OriginalValue;
6175 llvm::SmallVector<llvm::Type *, 4> BaseType;
6178 void append(MapInfoData &CurInfo) {
6179 IsDeclareTarget.append(CurInfo.IsDeclareTarget.begin(),
6180 CurInfo.IsDeclareTarget.end());
6181 MapClause.append(CurInfo.MapClause.begin(), CurInfo.MapClause.end());
6182 OriginalValue.append(CurInfo.OriginalValue.begin(),
6183 CurInfo.OriginalValue.end());
6184 BaseType.append(CurInfo.BaseType.begin(), CurInfo.BaseType.end());
6185 MapInfosTy::append(CurInfo);
6189enum class TargetDirectiveEnumTy : uint32_t {
6193 TargetEnterData = 3,
6198static TargetDirectiveEnumTy getTargetDirectiveEnumTyFromOp(Operation *op) {
6199 return llvm::TypeSwitch<Operation *, TargetDirectiveEnumTy>(op)
6200 .Case([](omp::TargetDataOp) {
return TargetDirectiveEnumTy::TargetData; })
6201 .Case([](omp::TargetEnterDataOp) {
6202 return TargetDirectiveEnumTy::TargetEnterData;
6204 .Case([&](omp::TargetExitDataOp) {
6205 return TargetDirectiveEnumTy::TargetExitData;
6207 .Case([&](omp::TargetUpdateOp) {
6208 return TargetDirectiveEnumTy::TargetUpdate;
6210 .Case([&](omp::TargetOp) {
return TargetDirectiveEnumTy::Target; })
6211 .Default([&](Operation *op) {
return TargetDirectiveEnumTy::None; });
6218 if (
auto nestedArrTy = llvm::dyn_cast_if_present<LLVM::LLVMArrayType>(
6219 arrTy.getElementType()))
6233 if (mapOp.getVarPtrPtr())
6257 llvm::Value *basePointer,
6258 llvm::Type *baseType,
6259 llvm::IRBuilderBase &builder,
6261 if (
auto memberClause =
6262 mlir::dyn_cast_if_present<mlir::omp::MapInfoOp>(clauseOp)) {
6267 if (!memberClause.getBounds().empty()) {
6268 llvm::Value *elementCount = builder.getInt64(1);
6269 for (
auto bounds : memberClause.getBounds()) {
6270 if (
auto boundOp = mlir::dyn_cast_if_present<mlir::omp::MapBoundsOp>(
6271 bounds.getDefiningOp())) {
6276 elementCount = builder.CreateMul(
6280 moduleTranslation.
lookupValue(boundOp.getUpperBound()),
6281 moduleTranslation.
lookupValue(boundOp.getLowerBound())),
6282 builder.getInt64(1)));
6289 if (
auto arrTy = llvm::dyn_cast_if_present<LLVM::LLVMArrayType>(type))
6297 llvm::Value *sizeCalc = builder.CreateMul(
6298 elementCount, builder.getInt64(underlyingTypeSzInBits / 8),
6336 return builder.CreateSelect(
6337 builder.CreateICmpEQ(sizeCalc, builder.getInt64(0)),
6338 builder.getInt64(1), sizeCalc);
6352static llvm::omp::OpenMPOffloadMappingFlags
6354 const bool hasExplicitMap =
6355 (mlirFlags &
~omp::ClauseMapFlags::is_device_ptr) !=
6356 omp::ClauseMapFlags::none;
6358 llvm::omp::OpenMPOffloadMappingFlags mapType =
6359 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE;
6361 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::to))
6362 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
6364 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::from))
6365 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
6367 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::always))
6368 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
6370 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::del))
6371 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
6373 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::return_param))
6374 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
6376 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::priv))
6377 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRIVATE;
6379 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::literal))
6380 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL;
6382 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::implicit))
6383 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
6385 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::close))
6386 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
6388 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::present))
6389 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
6391 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::ompx_hold))
6392 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
6394 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::attach))
6395 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH;
6397 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::is_device_ptr)) {
6398 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
6399 if (!hasExplicitMap)
6400 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL;
6410 ArrayRef<Value> useDevAddrOperands = {},
6411 ArrayRef<Value> hasDevAddrOperands = {}) {
6413 auto checkRefPtrOrPteeMapWithAttach = [](omp::ClauseMapFlags mapType) {
6415 bitEnumContainsAll(mapType, omp::ClauseMapFlags::ref_ptr) ||
6416 bitEnumContainsAll(mapType, omp::ClauseMapFlags::ref_ptee);
6417 return hasRefType &&
6418 bitEnumContainsAll(mapType, omp::ClauseMapFlags::attach);
6421 auto checkIsAMember = [](
const auto &mapVars,
auto mapOp) {
6429 for (Value mapValue : mapVars) {
6430 auto map = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
6431 for (
auto member : map.getMembers())
6432 if (member == mapOp)
6439 for (Value mapValue : mapVars) {
6440 auto mapOp = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
6441 bool isRefPtrOrPteeMapWithAttach =
6442 checkRefPtrOrPteeMapWithAttach(mapOp.getMapType());
6443 Value offloadPtr = (mapOp.getVarPtrPtr() && !isRefPtrOrPteeMapWithAttach)
6444 ? mapOp.getVarPtrPtr()
6445 : mapOp.getVarPtr();
6446 mapData.OriginalValue.push_back(moduleTranslation.
lookupValue(offloadPtr));
6447 mapData.Pointers.push_back(
6448 isRefPtrOrPteeMapWithAttach
6449 ? moduleTranslation.
lookupValue(mapOp.getVarPtrPtr())
6450 : mapData.OriginalValue.back());
6452 if (llvm::Value *refPtr =
6454 mapData.IsDeclareTarget.push_back(
true);
6455 mapData.BasePointers.push_back(refPtr);
6457 mapData.IsDeclareTarget.push_back(
true);
6458 mapData.BasePointers.push_back(mapData.OriginalValue.back());
6460 mapData.IsDeclareTarget.push_back(
false);
6461 mapData.BasePointers.push_back(mapData.OriginalValue.back());
6467 mapData.BaseType.push_back(moduleTranslation.
convertType(
6468 mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtrType().value()
6469 : mapOp.getVarPtrType()));
6476 mlir::Type sizeType = (isRefPtrOrPteeMapWithAttach || !mapOp.getVarPtrPtr())
6477 ? mapOp.getVarPtrType()
6478 : mapOp.getVarPtrPtrType().value();
6480 dl, sizeType, isRefPtrOrPteeMapWithAttach ?
nullptr : mapOp,
6481 mapData.Pointers.back(), moduleTranslation.
convertType(sizeType),
6482 builder, moduleTranslation));
6483 mapData.MapClause.push_back(mapOp.getOperation());
6487 mapData.DevicePointers.push_back(llvm::OpenMPIRBuilder::DeviceInfoTy::None);
6488 if (mapOp.getMapperId())
6489 mapData.Mappers.push_back(
6491 mapOp, mapOp.getMapperIdAttr()));
6493 mapData.Mappers.push_back(
nullptr);
6494 mapData.IsAMapping.push_back(
true);
6495 mapData.IsAMember.push_back(checkIsAMember(mapVars, mapOp));
6498 auto findMapInfo = [&mapData](llvm::Value *val,
6499 llvm::OpenMPIRBuilder::DeviceInfoTy devInfoTy,
6500 size_t memberCount) {
6503 for (llvm::Value *basePtr : mapData.OriginalValue) {
6504 auto mapOp = cast<omp::MapInfoOp>(mapData.MapClause[index]);
6515 (mapData.Types[index] &
6516 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH) ==
6517 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH;
6518 if (!isAttachMap && basePtr == val && mapData.IsAMapping[index] &&
6519 memberCount == mapOp.getMembers().size()) {
6521 mapData.Types[index] |=
6522 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
6523 mapData.DevicePointers[index] = devInfoTy;
6531 auto addDevInfos = [&](
const llvm::ArrayRef<Value> &useDevOperands,
6532 llvm::OpenMPIRBuilder::DeviceInfoTy devInfoTy) {
6533 for (Value mapValue : useDevOperands) {
6534 auto mapOp = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
6536 mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtr() : mapOp.getVarPtr();
6537 llvm::Value *origValue = moduleTranslation.
lookupValue(offloadPtr);
6540 if (!findMapInfo(origValue, devInfoTy, mapOp.getMembers().size())) {
6541 mapData.OriginalValue.push_back(origValue);
6542 mapData.Pointers.push_back(mapData.OriginalValue.back());
6543 mapData.IsDeclareTarget.push_back(
false);
6544 mapData.BasePointers.push_back(mapData.OriginalValue.back());
6545 mlir::Type baseTy = mapOp.getVarPtrPtr()
6546 ? mapOp.getVarPtrPtrType().value()
6547 : mapOp.getVarPtrType();
6548 mapData.BaseType.push_back(moduleTranslation.
convertType(baseTy));
6549 mapData.Sizes.push_back(builder.getInt64(0));
6550 mapData.MapClause.push_back(mapOp.getOperation());
6551 mapData.Types.push_back(
6552 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM);
6555 mapData.DevicePointers.push_back(devInfoTy);
6556 mapData.Mappers.push_back(
nullptr);
6557 mapData.IsAMapping.push_back(
false);
6558 mapData.IsAMember.push_back(checkIsAMember(useDevOperands, mapOp));
6563 addDevInfos(useDevAddrOperands, llvm::OpenMPIRBuilder::DeviceInfoTy::Address);
6564 addDevInfos(useDevPtrOperands, llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer);
6566 for (Value mapValue : hasDevAddrOperands) {
6567 auto mapOp = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
6569 mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtr() : mapOp.getVarPtr();
6570 llvm::Value *origValue = moduleTranslation.
lookupValue(offloadPtr);
6572 auto mapTypeAlways = llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
6574 (mapOp.getMapType() & omp::ClauseMapFlags::is_device_ptr) !=
6575 omp::ClauseMapFlags::none;
6577 mapData.OriginalValue.push_back(origValue);
6578 mapData.BasePointers.push_back(origValue);
6579 mapData.Pointers.push_back(origValue);
6580 mapData.IsDeclareTarget.push_back(
false);
6582 mlir::Type baseTy = mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtrType().value()
6583 : mapOp.getVarPtrType();
6584 mapData.BaseType.push_back(moduleTranslation.
convertType(baseTy));
6585 mapData.Sizes.push_back(builder.getInt64(dl.
getTypeSize(baseTy)));
6587 mapData.MapClause.push_back(mapOp.getOperation());
6588 if (llvm::to_underlying(mapType & mapTypeAlways)) {
6592 mapData.Types.push_back(mapType);
6596 if (mapOp.getMapperId()) {
6597 mapData.Mappers.push_back(
6599 mapOp, mapOp.getMapperIdAttr()));
6601 mapData.Mappers.push_back(
nullptr);
6606 mapData.Types.push_back(
6607 isDevicePtr ? mapType
6608 : llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
6609 mapData.Mappers.push_back(
nullptr);
6613 mapData.DevicePointers.push_back(
6614 isDevicePtr ? llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer
6615 : llvm::OpenMPIRBuilder::DeviceInfoTy::Address);
6616 mapData.IsAMapping.push_back(
false);
6617 mapData.IsAMember.push_back(checkIsAMember(hasDevAddrOperands, mapOp));
6622 auto *res = llvm::find(mapData.MapClause, memberOp);
6623 assert(res != mapData.MapClause.end() &&
6624 "MapInfoOp for member not found in MapData, cannot return index");
6625 return std::distance(mapData.MapClause.begin(), res);
6629 omp::MapInfoOp mapInfo,
bool first =
true) {
6630 ArrayAttr indexAttr = mapInfo.getMembersIndexAttr();
6640 auto memberIndicesA = cast<ArrayAttr>(indexAttr[a]);
6641 auto memberIndicesB = cast<ArrayAttr>(indexAttr[b]);
6643 for (auto it : llvm::zip(memberIndicesA, memberIndicesB)) {
6644 int64_t aIndex = mlir::cast<IntegerAttr>(std::get<0>(it)).getInt();
6645 int64_t bIndex = mlir::cast<IntegerAttr>(std::get<1>(it)).getInt();
6647 if (aIndex == bIndex)
6650 if (aIndex < bIndex)
6653 if (aIndex > bIndex)
6660 bool memberAParent = memberIndicesA.size() < memberIndicesB.size();
6662 occludedChildren.push_back(
b);
6664 occludedChildren.push_back(a);
6665 return memberAParent;
6668 for (
auto v : occludedChildren)
6675 ArrayAttr indexAttr = mapInfo.getMembersIndexAttr();
6677 if (indexAttr.size() == 1)
6678 return cast<omp::MapInfoOp>(mapInfo.getMembers()[0].getDefiningOp());
6682 return llvm::cast<omp::MapInfoOp>(
6683 mapInfo.getMembers()[
indices.front()].getDefiningOp());
6706static std::vector<llvm::Value *>
6708 llvm::IRBuilderBase &builder,
bool isArrayTy,
6710 std::vector<llvm::Value *> idx;
6721 idx.push_back(builder.getInt64(0));
6722 for (
int i = bounds.size() - 1; i >= 0; --i) {
6723 if (
auto boundOp = dyn_cast_if_present<omp::MapBoundsOp>(
6724 bounds[i].getDefiningOp())) {
6725 idx.push_back(moduleTranslation.
lookupValue(boundOp.getLowerBound()));
6743 for (
int i = bounds.size() - 1; i >= 0; --i) {
6744 if (
auto boundOp = dyn_cast_if_present<omp::MapBoundsOp>(
6745 bounds[i].getDefiningOp())) {
6746 if (i == ((
int)bounds.size() - 1))
6748 moduleTranslation.
lookupValue(boundOp.getLowerBound()));
6750 idx.back() = builder.CreateAdd(
6751 builder.CreateMul(idx.back(), moduleTranslation.
lookupValue(
6752 boundOp.getExtent())),
6753 moduleTranslation.
lookupValue(boundOp.getLowerBound()));
6762 llvm::transform(values, std::back_inserter(ints), [](
Attribute value) {
6763 return cast<IntegerAttr>(value).getInt();
6771 omp::MapInfoOp parentOp) {
6773 if (parentOp.getMembers().empty())
6777 if (parentOp.getMembers().size() == 1) {
6778 overlapMapDataIdxs.push_back(0);
6782 ArrayAttr indexAttr = parentOp.getMembersIndexAttr();
6783 size_t numMembers = indexAttr.size();
6787 for (
auto [i, indicesAttr] : llvm::enumerate(indexAttr))
6788 getAsIntegers(cast<ArrayAttr>(indicesAttr), memberIndices[i]);
6794 llvm::SmallDenseSet<size_t> skipIndices;
6795 for (
size_t i = 0; i < numMembers; ++i) {
6796 const auto &iIndices = memberIndices[i];
6797 for (
size_t j = 0;
j < numMembers; ++
j) {
6800 const auto &jIndices = memberIndices[
j];
6802 if (jIndices.size() < iIndices.size() &&
6803 std::equal(jIndices.begin(), jIndices.end(), iIndices.begin())) {
6804 skipIndices.insert(i);
6811 for (
size_t i = 0; i < numMembers; ++i)
6812 if (!skipIndices.contains(i))
6813 overlapMapDataIdxs.push_back(i);
6827 llvm::OpenMPIRBuilder &ompBuilder, MapInfoData &mapData,
6828 size_t mapDataIdx, MapInfosTy &combinedInfo,
6829 TargetDirectiveEnumTy targetDirective,
6830 llvm::omp::OpenMPOffloadMappingFlags memberOfFlag =
6831 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE,
6832 bool isTargetParam =
true,
int mapDataParentIdx = -1) {
6833 auto mapFlag = mapData.Types[mapDataIdx];
6834 auto mapInfoOp = llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIdx]);
6838 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH) ==
6839 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
6845 if (isTargetParam &&
6846 (targetDirective == TargetDirectiveEnumTy::Target &&
6847 !mapData.IsDeclareTarget[mapDataIdx]) &&
6849 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
6851 if (mapInfoOp.getMapCaptureType() == omp::VariableCaptureKind::ByCopy &&
6853 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL;
6862 if (memberOfFlag != llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE) {
6863 if (!isPtrTy && !isAttachMap)
6864 ompBuilder.setCorrectMemberOfFlag(mapFlag, memberOfFlag);
6871 mapFlag &=
~llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
6881 if (isPtrTy && !isAttachMap && mapData.IsDeclareTarget[mapDataIdx])
6882 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
6891 !bitEnumContainsAll(mapInfoOp.getMapType(),
6892 omp::ClauseMapFlags::ref_ptr) &&
6893 bitEnumContainsAll(mapInfoOp.getMapType(), omp::ClauseMapFlags::ref_ptee);
6894 bool isRefPtrPtee = bitEnumContainsAll(mapInfoOp.getMapType(),
6895 omp::ClauseMapFlags::ref_ptr |
6896 omp::ClauseMapFlags::ref_ptee);
6898 if (!mapInfoOp->getParentOfType<omp::DeclareMapperOp>() &&
6899 mapDataParentIdx >= 0 && !(isRefPtee || (isRefPtrPtee && isPtrTy))) {
6900 combinedInfo.BasePointers.emplace_back(
6901 mapData.BasePointers[mapDataParentIdx]);
6903 combinedInfo.BasePointers.emplace_back(mapData.BasePointers[mapDataIdx]);
6906 combinedInfo.Pointers.emplace_back(mapData.Pointers[mapDataIdx]);
6907 combinedInfo.DevicePointers.emplace_back(
6908 memberOfFlag != llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE
6909 ? llvm::OpenMPIRBuilder::DeviceInfoTy::None
6910 : mapData.DevicePointers[mapDataIdx]);
6911 combinedInfo.Mappers.emplace_back(mapData.Mappers[mapDataIdx]);
6912 combinedInfo.Names.emplace_back(mapData.Names[mapDataIdx]);
6913 combinedInfo.Types.emplace_back(mapFlag);
6914 combinedInfo.Sizes.emplace_back(
6915 isPtrTy ? builder.CreateSelect(
6916 builder.CreateIsNull(mapData.Pointers[mapDataIdx]),
6917 builder.getInt64(0), mapData.Sizes[mapDataIdx])
6918 : mapData.Sizes[mapDataIdx]);
6938 llvm::OpenMPIRBuilder &ompBuilder,
DataLayout &dl, MapInfosTy &combinedInfo,
6939 MapInfoData &mapData, uint64_t mapDataIndex,
6940 llvm::omp::OpenMPOffloadMappingFlags memberOfFlag,
6941 TargetDirectiveEnumTy targetDirective) {
6942 using MapFlags = llvm::omp::OpenMPOffloadMappingFlags;
6943 assert(!ompBuilder.Config.isTargetDevice() &&
6944 "function only supported for host device codegen");
6946 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
6947 auto *parentMapper = mapData.Mappers[mapDataIndex];
6953 MapFlags baseFlag = (targetDirective == TargetDirectiveEnumTy::Target &&
6954 !mapData.IsDeclareTarget[mapDataIndex])
6955 ? MapFlags::OMP_MAP_TARGET_PARAM
6956 : MapFlags::OMP_MAP_NONE;
6962 MapFlags parentFlags = mapData.Types[mapDataIndex];
6963 MapFlags preserve = MapFlags::OMP_MAP_TO | MapFlags::OMP_MAP_FROM |
6964 MapFlags::OMP_MAP_ALWAYS | MapFlags::OMP_MAP_CLOSE |
6965 MapFlags::OMP_MAP_PRESENT |
6966 MapFlags::OMP_MAP_OMPX_HOLD |
6967 MapFlags::OMP_MAP_IMPLICIT;
6968 baseFlag |= (parentFlags & preserve);
6970 MapFlags parentFlags = mapData.Types[mapDataIndex];
6972 MapFlags::OMP_MAP_PRESENT | MapFlags::OMP_MAP_RETURN_PARAM;
6973 baseFlag |= (parentFlags & preserve);
6976 combinedInfo.Types.emplace_back(baseFlag);
6977 combinedInfo.DevicePointers.emplace_back(
6978 mapData.DevicePointers[mapDataIndex]);
6982 combinedInfo.Mappers.emplace_back(
6983 parentMapper && !parentClause.getPartialMap() ? parentMapper :
nullptr);
6985 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder));
6986 combinedInfo.BasePointers.emplace_back(mapData.BasePointers[mapDataIndex]);
6995 llvm::Value *lowAddr, *highAddr;
6996 if (!parentClause.getPartialMap()) {
6997 lowAddr = builder.CreatePointerCast(mapData.Pointers[mapDataIndex],
6998 builder.getPtrTy());
6999 highAddr = builder.CreatePointerCast(
7000 builder.CreateConstGEP1_32(mapData.BaseType[mapDataIndex],
7001 mapData.Pointers[mapDataIndex], 1),
7002 builder.getPtrTy());
7003 combinedInfo.Pointers.emplace_back(mapData.Pointers[mapDataIndex]);
7005 auto mapOp = dyn_cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
7008 lowAddr = builder.CreatePointerCast(mapData.BasePointers[firstMemberIdx],
7009 builder.getPtrTy());
7013 auto lastMemberMapInfo =
7014 cast<omp::MapInfoOp>(mapData.MapClause[lastMemberIdx]);
7023 bool isRefPteeMap = bitEnumContainsAll(lastMemberMapInfo.getMapType(),
7024 omp::ClauseMapFlags::ref_ptee) &&
7025 !bitEnumContainsAll(lastMemberMapInfo.getMapType(),
7026 omp::ClauseMapFlags::ref_ptr);
7027 llvm::Type *castType = mapData.BaseType[lastMemberIdx];
7030 moduleTranslation.
convertType(lastMemberMapInfo.getVarPtrType());
7031 highAddr = builder.CreatePointerCast(
7032 builder.CreateGEP(castType, mapData.BasePointers[lastMemberIdx],
7033 builder.getInt64(1)),
7034 builder.getPtrTy());
7035 combinedInfo.Pointers.emplace_back(mapData.BasePointers[firstMemberIdx]);
7038 llvm::Value *size = builder.CreateIntCast(
7039 builder.CreatePtrDiff(builder.getInt8Ty(), highAddr, lowAddr),
7040 builder.getInt64Ty(),
7042 combinedInfo.Sizes.push_back(size);
7050 if (!parentClause.getPartialMap()) {
7055 MapFlags mapFlag = mapData.Types[mapDataIndex];
7056 bool hasMapClose = (MapFlags(mapFlag) & MapFlags::OMP_MAP_CLOSE) ==
7057 MapFlags::OMP_MAP_CLOSE;
7058 ompBuilder.setCorrectMemberOfFlag(mapFlag, memberOfFlag);
7074 if (targetDirective == TargetDirectiveEnumTy::TargetUpdate || hasMapClose ||
7075 overlapIdxs.size() == 1) {
7076 combinedInfo.Types.emplace_back(mapFlag);
7077 combinedInfo.DevicePointers.emplace_back(
7078 mapData.DevicePointers[mapDataIndex]);
7080 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder));
7081 combinedInfo.BasePointers.emplace_back(
7082 mapData.BasePointers[mapDataIndex]);
7083 combinedInfo.Pointers.emplace_back(mapData.Pointers[mapDataIndex]);
7084 combinedInfo.Sizes.emplace_back(mapData.Sizes[mapDataIndex]);
7085 combinedInfo.Mappers.emplace_back(
nullptr);
7091 lowAddr = builder.CreatePointerCast(mapData.Pointers[mapDataIndex],
7092 builder.getPtrTy());
7093 highAddr = builder.CreatePointerCast(
7094 builder.CreateConstGEP1_32(mapData.BaseType[mapDataIndex],
7095 mapData.Pointers[mapDataIndex], 1),
7096 builder.getPtrTy());
7103 mapFlag &=
~llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
7110 for (
auto v : overlapIdxs) {
7113 cast<omp::MapInfoOp>(parentClause.getMembers()[v].getDefiningOp()));
7115 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataOverlapIdx]));
7116 combinedInfo.Types.emplace_back(mapFlag);
7117 combinedInfo.DevicePointers.emplace_back(
7118 llvm::OpenMPIRBuilder::DeviceInfoTy::None);
7120 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder));
7121 combinedInfo.BasePointers.emplace_back(
7122 mapData.BasePointers[mapDataIndex]);
7123 combinedInfo.Mappers.emplace_back(
nullptr);
7124 combinedInfo.Pointers.emplace_back(lowAddr);
7125 auto sizeCalc = builder.CreateIntCast(
7126 builder.CreatePtrDiff(builder.getInt8Ty(),
7127 mapData.OriginalValue[mapDataOverlapIdx],
7129 builder.getInt64Ty(),
true);
7134 auto sizeSel = builder.CreateSelect(
7135 builder.CreateICmpNE(builder.getInt64(0), sizeCalc), sizeCalc,
7136 isPtrMap ? llvm::ConstantExpr::getSizeOf(builder.getPtrTy())
7137 : mapData.Sizes[mapDataOverlapIdx]);
7138 combinedInfo.Sizes.emplace_back(sizeSel);
7139 lowAddr = builder.CreateConstGEP1_32(
7140 isPtrMap ? builder.getPtrTy() : mapData.BaseType[mapDataOverlapIdx],
7141 mapData.BasePointers[mapDataOverlapIdx], 1);
7144 combinedInfo.Types.emplace_back(mapFlag);
7145 combinedInfo.DevicePointers.emplace_back(
7146 llvm::OpenMPIRBuilder::DeviceInfoTy::None);
7148 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder));
7149 combinedInfo.BasePointers.emplace_back(
7150 mapData.BasePointers[mapDataIndex]);
7151 combinedInfo.Mappers.emplace_back(
nullptr);
7152 combinedInfo.Pointers.emplace_back(lowAddr);
7153 combinedInfo.Sizes.emplace_back(builder.CreateIntCast(
7154 builder.CreatePtrDiff(builder.getInt8Ty(), highAddr, lowAddr),
7155 builder.getInt64Ty(),
true));
7161 llvm::IRBuilderBase &builder,
7162 llvm::OpenMPIRBuilder &ompBuilder,
7164 MapInfoData &mapData, uint64_t mapDataIndex,
7165 TargetDirectiveEnumTy targetDirective) {
7166 assert(!ompBuilder.Config.isTargetDevice() &&
7167 "function only supported for host device codegen");
7170 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
7175 if (parentClause.getMembers().size() == 1 && parentClause.getPartialMap()) {
7176 auto memberClause = llvm::cast<omp::MapInfoOp>(
7177 parentClause.getMembers()[0].getDefiningOp());
7190 builder, ompBuilder, mapData, memberDataIdx, combinedInfo,
7192 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE,
7193 true, mapDataIndex);
7197 auto collectMapInfoIdxs =
7200 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
7202 for (
auto member : parentClause.getMembers())
7204 mapData, llvm::cast<omp::MapInfoOp>(member.getDefiningOp())));
7208 collectMapInfoIdxs(mapInfoIdx);
7210 llvm::omp::OpenMPOffloadMappingFlags memberOfFlag =
7211 ompBuilder.getMemberOfFlag(combinedInfo.Types.size());
7212 for (
size_t i = 0; i < mapInfoIdx.size(); i++) {
7217 combinedInfo, mapData, mapInfoIdx[i], memberOfFlag,
7221 combinedInfo, targetDirective, memberOfFlag,
7222 false, mapDataIndex);
7234 llvm::IRBuilderBase &builder) {
7236 "function only supported for host device codegen");
7237 for (
size_t i = 0; i < mapData.MapClause.size(); ++i) {
7238 auto mapOp = cast<omp::MapInfoOp>(mapData.MapClause[i]);
7241 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH) ==
7242 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
7247 if (!mapData.IsDeclareTarget[i] ||
7248 (mapData.IsDeclareTarget[i] && isAttachMap)) {
7249 omp::VariableCaptureKind captureKind = mapOp.getMapCaptureType();
7259 switch (captureKind) {
7260 case omp::VariableCaptureKind::ByRef: {
7261 llvm::Value *newV = mapData.Pointers[i];
7263 moduleTranslation, builder, mapData.BaseType[i]->isArrayTy(),
7266 newV = builder.CreateLoad(builder.getPtrTy(), newV);
7268 if (!offsetIdx.empty())
7269 newV = builder.CreateInBoundsGEP(mapData.BaseType[i], newV, offsetIdx,
7271 mapData.Pointers[i] = newV;
7273 case omp::VariableCaptureKind::ByCopy: {
7274 llvm::Type *type = mapData.BaseType[i];
7276 if (mapData.Pointers[i]->getType()->isPointerTy())
7277 newV = builder.CreateLoad(type, mapData.Pointers[i]);
7279 newV = mapData.Pointers[i];
7282 auto curInsert = builder.saveIP();
7283 llvm::DebugLoc DbgLoc = builder.getCurrentDebugLocation();
7285 auto *memTempAlloc =
7286 builder.CreateAlloca(builder.getPtrTy(),
nullptr,
".casted");
7287 builder.SetCurrentDebugLocation(DbgLoc);
7288 builder.restoreIP(curInsert);
7290 builder.CreateStore(newV, memTempAlloc);
7291 newV = builder.CreateLoad(builder.getPtrTy(), memTempAlloc);
7294 mapData.Pointers[i] = newV;
7295 mapData.BasePointers[i] = newV;
7297 case omp::VariableCaptureKind::This:
7298 case omp::VariableCaptureKind::VLAType:
7299 mapData.MapClause[i]->emitOpError(
"Unhandled capture kind");
7310 MapInfoData &mapData,
7311 TargetDirectiveEnumTy targetDirective) {
7313 "function only supported for host device codegen");
7334 for (
size_t i = 0; i < mapData.MapClause.size(); ++i) {
7335 if (mapData.IsAMember[i])
7338 auto mapInfoOp = dyn_cast<omp::MapInfoOp>(mapData.MapClause[i]);
7339 if (!mapInfoOp.getMembers().empty()) {
7341 combinedInfo, mapData, i, targetDirective);
7350static llvm::Expected<llvm::Function *>
7352 LLVM::ModuleTranslation &moduleTranslation,
7353 llvm::StringRef mapperFuncName,
7354 TargetDirectiveEnumTy targetDirective);
7356static llvm::Expected<llvm::Function *>
7359 TargetDirectiveEnumTy targetDirective) {
7361 "function only supported for host device codegen");
7362 auto declMapperOp = cast<omp::DeclareMapperOp>(op);
7363 std::string mapperFuncName =
7365 {
"omp_mapper", declMapperOp.getSymName()});
7367 if (
auto *lookupFunc = moduleTranslation.
lookupFunction(mapperFuncName))
7375 if (llvm::Function *existingFunc =
7376 moduleTranslation.
getLLVMModule()->getFunction(mapperFuncName)) {
7377 moduleTranslation.
mapFunction(mapperFuncName, existingFunc);
7378 return existingFunc;
7382 mapperFuncName, targetDirective);
7385static llvm::Expected<llvm::Function *>
7388 llvm::StringRef mapperFuncName,
7389 TargetDirectiveEnumTy targetDirective) {
7391 "function only supported for host device codegen");
7392 auto declMapperOp = cast<omp::DeclareMapperOp>(op);
7393 auto declMapperInfoOp = declMapperOp.getDeclareMapperInfo();
7395 return llvm::make_error<PreviouslyReportedError>();
7399 llvm::Type *varType = moduleTranslation.
convertType(declMapperOp.getType());
7402 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
7405 MapInfosTy combinedInfo;
7407 [&](InsertPointTy codeGenIP, llvm::Value *ptrPHI,
7408 llvm::Value *unused2) -> llvm::OpenMPIRBuilder::MapInfosOrErrorTy {
7409 builder.restoreIP(codeGenIP);
7410 moduleTranslation.
mapValue(declMapperOp.getSymVal(), ptrPHI);
7411 moduleTranslation.
mapBlock(&declMapperOp.getRegion().front(),
7412 builder.GetInsertBlock());
7413 if (failed(moduleTranslation.
convertBlock(declMapperOp.getRegion().front(),
7416 return llvm::make_error<PreviouslyReportedError>();
7417 MapInfoData mapData;
7420 genMapInfos(builder, moduleTranslation, dl, combinedInfo, mapData,
7426 return combinedInfo;
7430 if (!combinedInfo.Mappers[i])
7433 moduleTranslation, targetDirective);
7437 genMapInfoCB, varType, mapperFuncName, customMapperCB,
7440 return newFn.takeError();
7441 if ([[maybe_unused]] llvm::Function *mappedFunc =
7443 assert(mappedFunc == *newFn &&
7444 "mapper function mapping disagrees with emitted function");
7446 moduleTranslation.
mapFunction(mapperFuncName, *newFn);
7454 llvm::Value *ifCond =
nullptr;
7455 llvm::Value *deviceID = builder.getInt64(llvm::omp::OMP_DEVICEID_UNDEF);
7459 llvm::omp::RuntimeFunction RTLFn;
7461 TargetDirectiveEnumTy targetDirective = getTargetDirectiveEnumTyFromOp(op);
7464 llvm::OpenMPIRBuilder::TargetDataInfo info(
7467 assert(!ompBuilder->Config.isTargetDevice() &&
7468 "target data/enter/exit/update are host ops");
7469 bool isOffloadEntry = !ompBuilder->Config.TargetTriples.empty();
7471 auto getDeviceID = [&](
mlir::Value dev) -> llvm::Value * {
7472 llvm::Value *v = moduleTranslation.
lookupValue(dev);
7473 return builder.CreateIntCast(v, builder.getInt64Ty(),
true);
7478 .Case([&](omp::TargetDataOp dataOp) {
7482 if (
auto ifVar = dataOp.getIfExpr())
7486 deviceID = getDeviceID(devId);
7488 mapVars = dataOp.getMapVars();
7489 useDevicePtrVars = dataOp.getUseDevicePtrVars();
7490 useDeviceAddrVars = dataOp.getUseDeviceAddrVars();
7493 .Case([&](omp::TargetEnterDataOp enterDataOp) -> LogicalResult {
7497 if (
auto ifVar = enterDataOp.getIfExpr())
7501 deviceID = getDeviceID(devId);
7504 enterDataOp.getNowait()
7505 ? llvm::omp::OMPRTL___tgt_target_data_begin_nowait_mapper
7506 : llvm::omp::OMPRTL___tgt_target_data_begin_mapper;
7507 mapVars = enterDataOp.getMapVars();
7508 info.HasNoWait = enterDataOp.getNowait();
7511 .Case([&](omp::TargetExitDataOp exitDataOp) -> LogicalResult {
7515 if (
auto ifVar = exitDataOp.getIfExpr())
7519 deviceID = getDeviceID(devId);
7521 RTLFn = exitDataOp.getNowait()
7522 ? llvm::omp::OMPRTL___tgt_target_data_end_nowait_mapper
7523 : llvm::omp::OMPRTL___tgt_target_data_end_mapper;
7524 mapVars = exitDataOp.getMapVars();
7525 info.HasNoWait = exitDataOp.getNowait();
7528 .Case([&](omp::TargetUpdateOp updateDataOp) -> LogicalResult {
7532 if (
auto ifVar = updateDataOp.getIfExpr())
7536 deviceID = getDeviceID(devId);
7539 updateDataOp.getNowait()
7540 ? llvm::omp::OMPRTL___tgt_target_data_update_nowait_mapper
7541 : llvm::omp::OMPRTL___tgt_target_data_update_mapper;
7542 mapVars = updateDataOp.getMapVars();
7543 info.HasNoWait = updateDataOp.getNowait();
7546 .DefaultUnreachable(
"unexpected operation");
7551 if (!isOffloadEntry)
7552 ifCond = builder.getFalse();
7554 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
7555 MapInfoData mapData;
7557 builder, useDevicePtrVars, useDeviceAddrVars);
7560 MapInfosTy combinedInfo;
7561 auto genMapInfoCB = [&](InsertPointTy codeGenIP) -> MapInfosTy & {
7562 builder.restoreIP(codeGenIP);
7563 genMapInfos(builder, moduleTranslation, DL, combinedInfo, mapData,
7565 return combinedInfo;
7571 [&moduleTranslation](
7572 llvm::OpenMPIRBuilder::DeviceInfoTy type,
7576 for (
auto [arg, useDevVar] :
7577 llvm::zip_equal(blockArgs, useDeviceVars)) {
7579 auto getMapBasePtr = [](omp::MapInfoOp mapInfoOp) {
7580 return mapInfoOp.getVarPtrPtr() ? mapInfoOp.getVarPtrPtr()
7581 : mapInfoOp.getVarPtr();
7584 auto useDevMap = cast<omp::MapInfoOp>(useDevVar.getDefiningOp());
7585 for (
auto [mapClause, devicePointer, basePointer] : llvm::zip_equal(
7586 mapInfoData.MapClause, mapInfoData.DevicePointers,
7587 mapInfoData.BasePointers)) {
7588 auto mapOp = cast<omp::MapInfoOp>(mapClause);
7589 if (getMapBasePtr(mapOp) != getMapBasePtr(useDevMap) ||
7590 devicePointer != type)
7593 if (llvm::Value *devPtrInfoMap =
7594 mapper ? mapper(basePointer) : basePointer) {
7595 moduleTranslation.
mapValue(arg, devPtrInfoMap);
7602 using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy;
7603 auto bodyGenCB = [&](InsertPointTy codeGenIP, BodyGenTy bodyGenType)
7604 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
7607 builder.restoreIP(codeGenIP);
7608 assert(isa<omp::TargetDataOp>(op) &&
7609 "BodyGen requested for non TargetDataOp");
7610 auto blockArgIface = cast<omp::BlockArgOpenMPOpInterface>(op);
7611 Region ®ion = cast<omp::TargetDataOp>(op).getRegion();
7612 switch (bodyGenType) {
7613 case BodyGenTy::Priv:
7615 if (!info.DevicePtrInfoMap.empty()) {
7616 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Address,
7617 blockArgIface.getUseDeviceAddrBlockArgs(),
7618 useDeviceAddrVars, mapData,
7619 [&](llvm::Value *basePointer) -> llvm::Value * {
7620 if (!info.DevicePtrInfoMap[basePointer].second)
7622 return builder.CreateLoad(
7624 info.DevicePtrInfoMap[basePointer].second);
7626 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer,
7627 blockArgIface.getUseDevicePtrBlockArgs(), useDevicePtrVars,
7628 mapData, [&](llvm::Value *basePointer) {
7629 return info.DevicePtrInfoMap[basePointer].second;
7633 moduleTranslation)))
7634 return llvm::make_error<PreviouslyReportedError>();
7637 case BodyGenTy::DupNoPriv:
7638 if (info.DevicePtrInfoMap.empty()) {
7641 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Address,
7642 blockArgIface.getUseDeviceAddrBlockArgs(),
7643 useDeviceAddrVars, mapData);
7644 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer,
7645 blockArgIface.getUseDevicePtrBlockArgs(), useDevicePtrVars,
7649 case BodyGenTy::NoPriv:
7651 if (info.DevicePtrInfoMap.empty()) {
7653 moduleTranslation)))
7654 return llvm::make_error<PreviouslyReportedError>();
7658 return builder.saveIP();
7661 auto customMapperCB =
7663 if (!combinedInfo.Mappers[i])
7665 info.HasMapper =
true;
7667 moduleTranslation, targetDirective);
7670 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
7672 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
7674 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP = [&]() {
7675 if (isa<omp::TargetDataOp>(op))
7676 return ompBuilder->createTargetData(ompLoc, allocaIP, builder.saveIP(),
7677 deallocBlocks, deviceID, ifCond, info,
7678 genMapInfoCB, customMapperCB,
7681 return ompBuilder->createTargetData(ompLoc, allocaIP, builder.saveIP(),
7682 deallocBlocks, deviceID, ifCond, info,
7683 genMapInfoCB, customMapperCB, &RTLFn);
7689 builder.restoreIP(*afterIP);
7697 auto distributeOp = cast<omp::DistributeOp>(opInst);
7704 bool doDistributeReduction =
7708 unsigned numReductionVars = teamsOp ? teamsOp.getNumReductionVars() : 0;
7713 if (doDistributeReduction) {
7714 isByRef =
getIsByRef(teamsOp.getReductionByref());
7715 assert(isByRef.size() == teamsOp.getNumReductionVars());
7718 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
7722 llvm::cast<omp::BlockArgOpenMPOpInterface>(*teamsOp)
7723 .getReductionBlockArgs();
7726 teamsOp, reductionArgs, builder, moduleTranslation, allocaIP,
7727 reductionDecls, privateReductionVariables, reductionVariableMap,
7732 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
7734 [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
7739 moduleTranslation, allocaIP, deallocBlocks);
7742 builder.restoreIP(codeGenIP);
7746 distributeOp, builder, moduleTranslation, privVarsInfo, allocaIP);
7748 return llvm::make_error<PreviouslyReportedError>();
7753 return llvm::make_error<PreviouslyReportedError>();
7756 distributeOp, builder, moduleTranslation, privVarsInfo.
mlirVars,
7758 distributeOp.getPrivateNeedsBarrier())))
7759 return llvm::make_error<PreviouslyReportedError>();
7762 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
7765 builder, moduleTranslation);
7767 return regionBlock.takeError();
7768 builder.SetInsertPoint(*regionBlock, (*regionBlock)->begin());
7773 if (!isa_and_present<omp::WsloopOp>(distributeOp.getNestedWrapper())) {
7776 bool hasDistSchedule = distributeOp.getDistScheduleStatic();
7777 auto schedule = hasDistSchedule ? omp::ClauseScheduleKind::Distribute
7778 : omp::ClauseScheduleKind::Static;
7780 bool isOrdered = hasDistSchedule;
7781 std::optional<omp::ScheduleModifier> scheduleMod;
7782 bool isSimd =
false;
7783 llvm::omp::WorksharingLoopType workshareLoopType =
7784 llvm::omp::WorksharingLoopType::DistributeStaticLoop;
7785 bool loopNeedsBarrier =
false;
7786 llvm::Value *chunk = moduleTranslation.
lookupValue(
7787 distributeOp.getDistScheduleChunkSize());
7788 llvm::CanonicalLoopInfo *loopInfo =
7790 llvm::OpenMPIRBuilder::InsertPointOrErrorTy wsloopIP =
7791 ompBuilder->applyWorkshareLoop(
7792 ompLoc.DL, loopInfo, allocaIP, loopNeedsBarrier,
7793 convertToScheduleKind(schedule), chunk, isSimd,
7794 scheduleMod == omp::ScheduleModifier::monotonic,
7795 scheduleMod == omp::ScheduleModifier::nonmonotonic, isOrdered,
7796 workshareLoopType,
false, hasDistSchedule, chunk);
7799 return wsloopIP.takeError();
7802 distributeOp.getLoc(), privVarsInfo)))
7803 return llvm::make_error<PreviouslyReportedError>();
7805 return llvm::Error::success();
7809 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
7811 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
7812 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
7813 ompBuilder->createDistribute(ompLoc, allocaIP, deallocBlocks, bodyGenCB);
7818 builder.restoreIP(*afterIP);
7820 if (doDistributeReduction) {
7823 teamsOp, builder, moduleTranslation, allocaIP, reductionDecls,
7824 privateReductionVariables, isByRef,
7836 auto offloadMod = dyn_cast<omp::OffloadModuleInterface>(op);
7838 return op->
emitOpError() <<
"omp flags attached to non offload module op";
7842 if (offloadMod.getIsTargetDevice())
7843 ompBuilder->M.addModuleFlag(llvm::Module::Max,
"openmp-device",
7844 attribute.getOpenmpDeviceVersion());
7847 if (!offloadMod.getIsGPU())
7850 if (attribute.getNoGpuLib())
7853 ompBuilder->createGlobalFlag(
7854 attribute.getDebugKind() ,
7855 "__omp_rtl_debug_kind");
7856 ompBuilder->createGlobalFlag(
7858 .getAssumeTeamsOversubscription()
7860 "__omp_rtl_assume_teams_oversubscription");
7861 ompBuilder->createGlobalFlag(
7863 .getAssumeThreadsOversubscription()
7865 "__omp_rtl_assume_threads_oversubscription");
7866 ompBuilder->createGlobalFlag(
7867 attribute.getAssumeNoThreadState() ,
7868 "__omp_rtl_assume_no_thread_state");
7869 ompBuilder->createGlobalFlag(
7871 .getAssumeNoNestedParallelism()
7873 "__omp_rtl_assume_no_nested_parallelism");
7878 omp::TargetOp targetOp,
7879 llvm::OpenMPIRBuilder &ompBuilder,
7880 llvm::vfs::FileSystem &vfs,
7881 llvm::StringRef parentName =
"") {
7882 auto fileLoc = targetOp.getLoc()->findInstanceOf<
FileLineColLoc>();
7883 assert(fileLoc &&
"No file found from location");
7885 auto fileInfoCallBack = [&fileLoc]() {
7886 return std::pair<std::string, uint64_t>(
7887 llvm::StringRef(fileLoc.getFilename()), fileLoc.getLine());
7891 ompBuilder.getTargetEntryUniqueInfo(fileInfoCallBack, vfs, parentName);
7897 llvm::IRBuilderBase &builder, llvm::Function *
func) {
7899 "function only supported for target device codegen");
7900 llvm::IRBuilderBase::InsertPointGuard guard(builder);
7901 for (
size_t i = 0; i < mapData.MapClause.size(); ++i) {
7914 if (!mapData.IsDeclareTarget[i])
7922 if (
auto *constant = dyn_cast<llvm::Constant>(mapData.OriginalValue[i]))
7923 convertUsersOfConstantsToInstructions(constant,
func,
false);
7930 for (llvm::User *user : mapData.OriginalValue[i]->users())
7931 userVec.push_back(user);
7933 for (llvm::User *user : userVec) {
7934 auto *insn = dyn_cast<llvm::Instruction>(user);
7935 if (!insn || insn->getFunction() !=
func)
7937 auto mapOp = cast<omp::MapInfoOp>(mapData.MapClause[i]);
7938 llvm::Value *substitute = mapData.BasePointers[i];
7940 mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtr() : mapOp.getVarPtr();
7944 ->Config.hasRequiresUnifiedSharedMemory())) {
7945 builder.SetCurrentDebugLocation(insn->getDebugLoc());
7946 substitute = builder.CreateLoad(mapData.BasePointers[i]->getType(),
7947 mapData.BasePointers[i]);
7948 cast<llvm::LoadInst>(substitute)->moveBefore(insn->getIterator());
7950 user->replaceUsesOfWith(mapData.OriginalValue[i], substitute);
7995 omp::TargetOp targetOp, MapInfoData &mapData, llvm::Argument &arg,
7996 llvm::Value *input, llvm::Value *&retVal, llvm::IRBuilderBase &builder,
7997 llvm::OpenMPIRBuilder &ompBuilder,
7999 llvm::IRBuilderBase::InsertPoint allocaIP,
8000 llvm::IRBuilderBase::InsertPoint codeGenIP,
8002 assert(ompBuilder.Config.isTargetDevice() &&
8003 "function only supported for target device codegen");
8004 builder.restoreIP(allocaIP);
8006 omp::VariableCaptureKind capture = omp::VariableCaptureKind::ByRef;
8008 ompBuilder.M.getContext());
8009 unsigned alignmentValue = 0;
8012 cast<omp::BlockArgOpenMPOpInterface>(*targetOp).getBlockArgsPairs(
8015 for (
size_t i = 0; i < mapData.MapClause.size(); ++i) {
8016 if (mapData.OriginalValue[i] == input) {
8017 auto mapOp = cast<omp::MapInfoOp>(mapData.MapClause[i]);
8018 capture = mapOp.getMapCaptureType();
8021 mapOp.getVarPtrType(), ompBuilder.M.getDataLayout());
8025 for (
auto &[val, arg] : blockArgsPairs) {
8026 if (mapOp.getResult() == val) {
8031 assert(mlirArg &&
"expected to find entry block argument for map clause");
8036 unsigned int allocaAS = ompBuilder.M.getDataLayout().getAllocaAddrSpace();
8037 unsigned int defaultAS =
8038 ompBuilder.M.getDataLayout().getProgramAddressSpace();
8041 llvm::Value *v =
nullptr;
8049 builder.SetInsertPoint(codeGenIP.getBlock()->getFirstInsertionPt());
8050 v = ompBuilder.createOMPAllocShared(builder, arg.getType());
8054 llvm::IRBuilderBase::InsertPointGuard guard(builder);
8055 for (
auto deallocIP : deallocIPs) {
8056 builder.SetInsertPoint(deallocIP.getBlock(), deallocIP.getPoint());
8057 ompBuilder.createOMPFreeShared(builder, v, arg.getType());
8061 v = builder.CreateAlloca(arg.getType(), allocaAS);
8063 if (allocaAS != defaultAS && arg.getType()->isPointerTy())
8064 v = builder.CreateAddrSpaceCast(v, builder.getPtrTy(defaultAS));
8067 builder.CreateStore(&arg, v);
8069 builder.restoreIP(codeGenIP);
8072 case omp::VariableCaptureKind::ByCopy: {
8076 case omp::VariableCaptureKind::ByRef: {
8077 llvm::LoadInst *loadInst = builder.CreateAlignedLoad(
8079 ompBuilder.M.getDataLayout().getPrefTypeAlign(v->getType()));
8094 if (v->getType()->isPointerTy() && alignmentValue) {
8095 llvm::MDBuilder MDB(builder.getContext());
8096 loadInst->setMetadata(
8097 llvm::LLVMContext::MD_align,
8098 llvm::MDNode::get(builder.getContext(),
8099 MDB.createConstant(llvm::ConstantInt::get(
8100 llvm::Type::getInt64Ty(builder.getContext()),
8107 case omp::VariableCaptureKind::This:
8108 case omp::VariableCaptureKind::VLAType:
8111 assert(
false &&
"Currently unsupported capture kind");
8115 return builder.saveIP();
8132 auto blockArgIface = llvm::cast<omp::BlockArgOpenMPOpInterface>(*targetOp);
8133 for (
auto item : llvm::zip_equal(targetOp.getHostEvalVars(),
8134 blockArgIface.getHostEvalBlockArgs())) {
8135 Value hostEvalVar = std::get<0>(item), blockArg = std::get<1>(item);
8139 .Case([&](omp::TeamsOp teamsOp) {
8140 if (teamsOp.getNumTeamsLower() == blockArg)
8141 numTeamsLower = hostEvalVar;
8142 else if (llvm::is_contained(teamsOp.getNumTeamsUpperVars(),
8144 numTeamsUpper = hostEvalVar;
8145 else if (!teamsOp.getThreadLimitVars().empty() &&
8146 teamsOp.getThreadLimit(0) == blockArg)
8147 threadLimit = hostEvalVar;
8149 llvm_unreachable(
"unsupported host_eval use");
8151 .Case([&](omp::ParallelOp parallelOp) {
8152 if (!parallelOp.getNumThreadsVars().empty() &&
8153 parallelOp.getNumThreads(0) == blockArg)
8154 numThreads = hostEvalVar;
8156 llvm_unreachable(
"unsupported host_eval use");
8158 .Case([&](omp::LoopNestOp loopOp) {
8159 auto processBounds =
8163 for (
auto [i, lb] : llvm::enumerate(opBounds)) {
8164 if (lb == blockArg) {
8167 (*outBounds)[i] = hostEvalVar;
8173 processBounds(loopOp.getLoopLowerBounds(), lowerBounds);
8174 found = processBounds(loopOp.getLoopUpperBounds(), upperBounds) ||
8176 found = processBounds(loopOp.getLoopSteps(), steps) || found;
8178 assert(found &&
"unsupported host_eval use");
8180 .DefaultUnreachable(
"unsupported host_eval use");
8192template <
typename OpTy>
8197 if (OpTy casted = dyn_cast<OpTy>(op))
8200 if (immediateParent)
8201 return dyn_cast_if_present<OpTy>(op->
getParentOp());
8210 return std::nullopt;
8213 if (
auto constAttr = dyn_cast<IntegerAttr>(constOp.getValue()))
8214 return constAttr.getInt();
8216 return std::nullopt;
8221 uint64_t sizeInBytes = sizeInBits / 8;
8225template <
typename OpTy>
8227 if (op.getNumReductionVars() > 0) {
8232 members.reserve(reductions.size());
8233 for (omp::DeclareReductionOp &red : reductions) {
8237 if (red.getByrefElementType())
8238 members.push_back(*red.getByrefElementType());
8240 members.push_back(red.getType());
8243 auto structType = mlir::LLVM::LLVMStructType::getLiteral(
8259 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &attrs,
8260 bool isTargetDevice,
bool isGPU) {
8263 Value numThreads, numTeamsLower, numTeamsUpper, threadLimit;
8264 if (!isTargetDevice) {
8272 numTeamsLower = teamsOp.getNumTeamsLower();
8274 if (!teamsOp.getNumTeamsUpperVars().empty())
8275 numTeamsUpper = teamsOp.getNumTeams(0);
8276 if (!teamsOp.getThreadLimitVars().empty())
8277 threadLimit = teamsOp.getThreadLimit(0);
8281 if (!parallelOp.getNumThreadsVars().empty())
8282 numThreads = parallelOp.getNumThreads(0);
8288 int32_t minTeamsVal = 1, maxTeamsVal = -1;
8292 if (numTeamsUpper) {
8294 minTeamsVal = maxTeamsVal = *val;
8296 minTeamsVal = maxTeamsVal = 0;
8302 minTeamsVal = maxTeamsVal = 1;
8304 minTeamsVal = maxTeamsVal = -1;
8309 auto setMaxValueFromClause = [](
Value clauseValue, int32_t &
result) {
8323 int32_t targetThreadLimitVal = -1, teamsThreadLimitVal = -1;
8324 if (!targetOp.getThreadLimitVars().empty())
8325 setMaxValueFromClause(targetOp.getThreadLimit(0), targetThreadLimitVal);
8326 setMaxValueFromClause(threadLimit, teamsThreadLimitVal);
8329 int32_t maxThreadsVal = -1;
8331 setMaxValueFromClause(numThreads, maxThreadsVal);
8339 int32_t combinedMaxThreadsVal = targetThreadLimitVal;
8340 if (combinedMaxThreadsVal < 0 ||
8341 (teamsThreadLimitVal >= 0 && teamsThreadLimitVal < combinedMaxThreadsVal))
8342 combinedMaxThreadsVal = teamsThreadLimitVal;
8344 if (combinedMaxThreadsVal < 0 ||
8345 (maxThreadsVal >= 0 && maxThreadsVal < combinedMaxThreadsVal))
8346 combinedMaxThreadsVal = maxThreadsVal;
8348 int32_t reductionDataSize = 0;
8349 if (isGPU && capturedOp) {
8356 omp::TargetExecMode execMode = targetOp.getKernelType();
8358 case omp::TargetExecMode::bare:
8359 attrs.ExecFlags = llvm::omp::OMP_TGT_EXEC_MODE_BARE;
8361 case omp::TargetExecMode::generic:
8362 attrs.ExecFlags = llvm::omp::OMP_TGT_EXEC_MODE_GENERIC;
8364 case omp::TargetExecMode::spmd:
8365 attrs.ExecFlags = llvm::omp::OMP_TGT_EXEC_MODE_SPMD;
8367 case omp::TargetExecMode::spmd_no_loop:
8368 attrs.ExecFlags = llvm::omp::OMP_TGT_EXEC_MODE_SPMD_NO_LOOP;
8371 attrs.MinTeams = minTeamsVal;
8372 attrs.MaxTeams.front() = maxTeamsVal;
8373 attrs.MinThreads = 1;
8374 attrs.MaxThreads.front() = combinedMaxThreadsVal;
8375 attrs.ReductionDataSize = reductionDataSize;
8387 omp::TargetOp targetOp,
Operation *capturedOp,
8388 llvm::OpenMPIRBuilder::TargetKernelRuntimeAttrs &attrs) {
8390 unsigned numLoops = loopOp ? loopOp.getNumLoops() : 0;
8392 Value numThreads, numTeamsLower, numTeamsUpper, teamsThreadLimit;
8396 teamsThreadLimit, &lowerBounds, &upperBounds, &steps);
8399 if (!targetOp.getThreadLimitVars().empty()) {
8400 Value targetThreadLimit = targetOp.getThreadLimit(0);
8401 attrs.TargetThreadLimit.front() =
8409 attrs.MinTeams = builder.CreateSExtOrTrunc(
8410 moduleTranslation.
lookupValue(numTeamsLower), builder.getInt32Ty());
8413 attrs.MaxTeams.front() = builder.CreateSExtOrTrunc(
8414 moduleTranslation.
lookupValue(numTeamsUpper), builder.getInt32Ty());
8416 if (teamsThreadLimit)
8417 attrs.TeamsThreadLimit.front() = builder.CreateSExtOrTrunc(
8418 moduleTranslation.
lookupValue(teamsThreadLimit), builder.getInt32Ty());
8421 attrs.MaxThreads = moduleTranslation.
lookupValue(numThreads);
8423 if (targetOp.hasHostEvalTripCount()) {
8425 attrs.LoopTripCount =
nullptr;
8430 for (
auto [loopLower, loopUpper, loopStep] :
8431 llvm::zip_equal(lowerBounds, upperBounds, steps)) {
8432 llvm::Value *lowerBound = moduleTranslation.
lookupValue(loopLower);
8433 llvm::Value *upperBound = moduleTranslation.
lookupValue(loopUpper);
8434 llvm::Value *step = moduleTranslation.
lookupValue(loopStep);
8436 if (!lowerBound || !upperBound || !step) {
8437 attrs.LoopTripCount =
nullptr;
8441 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
8442 llvm::Value *tripCount = ompBuilder->calculateCanonicalLoopTripCount(
8443 loc, lowerBound, upperBound, step,
true,
8444 loopOp.getLoopInclusive());
8446 if (!attrs.LoopTripCount) {
8447 attrs.LoopTripCount = tripCount;
8452 attrs.LoopTripCount = builder.CreateMul(attrs.LoopTripCount, tripCount,
8457 attrs.DeviceID = builder.getInt64(llvm::omp::OMP_DEVICEID_UNDEF);
8459 attrs.DeviceID = moduleTranslation.
lookupValue(devId);
8461 builder.CreateSExtOrTrunc(attrs.DeviceID, builder.getInt64Ty());
8465static llvm::omp::OMPDynGroupprivateFallbackType
8467 omp::FallbackModifier fb = fallbackAttr ? fallbackAttr.getValue()
8468 : omp::FallbackModifier::default_mem;
8470 case omp::FallbackModifier::abort:
8471 return llvm::omp::OMPDynGroupprivateFallbackType::Abort;
8472 case omp::FallbackModifier::null:
8473 return llvm::omp::OMPDynGroupprivateFallbackType::Null;
8474 case omp::FallbackModifier::default_mem:
8475 return llvm::omp::OMPDynGroupprivateFallbackType::DefaultMem;
8478 llvm_unreachable(
"unexpected dyn_groupprivate fallback type");
8484 auto targetOp = cast<omp::TargetOp>(opInst);
8489 llvm::DebugLoc outlinedFnLoc = builder.getCurrentDebugLocation();
8498 llvm::BasicBlock *parentBB = builder.GetInsertBlock();
8499 assert(parentBB &&
"No insert block is set for the builder");
8500 llvm::Function *parentLLVMFn = parentBB->getParent();
8501 assert(parentLLVMFn &&
"Parent Function must be valid");
8502 if (llvm::DISubprogram *SP = parentLLVMFn->getSubprogram())
8503 builder.SetCurrentDebugLocation(llvm::DILocation::get(
8504 parentLLVMFn->getContext(), outlinedFnLoc.getLine(),
8505 outlinedFnLoc.getCol(), SP, outlinedFnLoc.getInlinedAt()));
8508 bool isTargetDevice = ompBuilder->Config.isTargetDevice();
8509 bool isGPU = ompBuilder->Config.isGPU();
8512 auto argIface = cast<omp::BlockArgOpenMPOpInterface>(opInst);
8513 auto &targetRegion = targetOp.getRegion();
8530 llvm::Function *llvmOutlinedFn =
nullptr;
8531 TargetDirectiveEnumTy targetDirective =
8532 getTargetDirectiveEnumTyFromOp(&opInst);
8536 bool isOffloadEntry =
8537 isTargetDevice || !ompBuilder->Config.TargetTriples.empty();
8544 if (!targetOp.getPrivateVars().empty() && !targetOp.getMapVars().empty()) {
8546 std::optional<ArrayAttr> privateSyms = targetOp.getPrivateSyms();
8547 std::optional<DenseI64ArrayAttr> privateMapIndices =
8548 targetOp.getPrivateMapsAttr();
8550 for (
auto [privVarIdx, privVarSymPair] :
8551 llvm::enumerate(llvm::zip_equal(privateVars, *privateSyms))) {
8552 auto privVar = std::get<0>(privVarSymPair);
8553 auto privSym = std::get<1>(privVarSymPair);
8555 SymbolRefAttr privatizerName = llvm::cast<SymbolRefAttr>(privSym);
8556 omp::PrivateClauseOp privatizer =
8559 if (!privatizer.needsMap())
8563 targetOp.getMappedValueForPrivateVar(privVarIdx);
8564 assert(mappedValue &&
"Expected to find mapped value for a privatized "
8565 "variable that needs mapping");
8570 auto mapInfoOp = mappedValue.
getDefiningOp<omp::MapInfoOp>();
8571 [[maybe_unused]]
Type varType = mapInfoOp.getVarPtrType();
8575 if (!isa<LLVM::LLVMPointerType>(privVar.getType()))
8577 varType == privVar.getType() &&
8578 "Type of private var doesn't match the type of the mapped value");
8582 mappedPrivateVars.insert(
8584 targetRegion.getArgument(argIface.getMapBlockArgsStart() +
8585 (*privateMapIndices)[privVarIdx])});
8589 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
8590 auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
8592 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
8593 llvm::IRBuilderBase::InsertPointGuard guard(builder);
8594 builder.SetCurrentDebugLocation(llvm::DebugLoc());
8597 llvm::Function *llvmParentFn =
8599 llvmOutlinedFn = codeGenIP.getBlock()->getParent();
8600 assert(llvmParentFn && llvmOutlinedFn &&
8601 "Both parent and outlined functions must exist at this point");
8603 if (outlinedFnLoc && llvmParentFn->getSubprogram())
8604 llvmOutlinedFn->setSubprogram(outlinedFnLoc->getScope()->getSubprogram());
8606 if (
auto attr = llvmParentFn->getFnAttribute(
"target-cpu");
8607 attr.isStringAttribute())
8608 llvmOutlinedFn->addFnAttr(attr);
8610 if (
auto attr = llvmParentFn->getFnAttribute(
"target-features");
8611 attr.isStringAttribute())
8612 llvmOutlinedFn->addFnAttr(attr);
8614 for (
auto [arg, mapOp] : llvm::zip_equal(mapBlockArgs, mapVars)) {
8615 auto mapInfoOp = cast<omp::MapInfoOp>(mapOp.getDefiningOp());
8616 llvm::Value *mapOpValue =
8617 moduleTranslation.
lookupValue(mapInfoOp.getVarPtr());
8618 moduleTranslation.
mapValue(arg, mapOpValue);
8620 for (
auto [arg, mapOp] : llvm::zip_equal(hdaBlockArgs, hdaVars)) {
8621 auto mapInfoOp = cast<omp::MapInfoOp>(mapOp.getDefiningOp());
8622 llvm::Value *mapOpValue =
8623 moduleTranslation.
lookupValue(mapInfoOp.getVarPtr());
8624 moduleTranslation.
mapValue(arg, mapOpValue);
8633 privateVarsInfo, allocaIP, &mappedPrivateVars);
8636 return llvm::make_error<PreviouslyReportedError>();
8638 builder.restoreIP(codeGenIP);
8640 &mappedPrivateVars),
8643 return llvm::make_error<PreviouslyReportedError>();
8646 targetOp, builder, moduleTranslation, privateVarsInfo.
mlirVars,
8648 targetOp.getPrivateNeedsBarrier(), &mappedPrivateVars)))
8649 return llvm::make_error<PreviouslyReportedError>();
8652 moduleTranslation, allocaIP, deallocBlocks);
8654 targetRegion,
"omp.target", builder, moduleTranslation);
8657 return llvm::make_error<PreviouslyReportedError>();
8659 builder.SetInsertPoint(exitBlock.get()->getTerminator());
8662 targetOp.getLoc(), privateVarsInfo)))
8663 return llvm::make_error<PreviouslyReportedError>();
8665 return builder.saveIP();
8668 StringRef parentName = parentFn.getName();
8670 llvm::TargetRegionEntryInfo entryInfo;
8676 MapInfoData mapData;
8681 MapInfosTy combinedInfos;
8683 [&](llvm::OpenMPIRBuilder::InsertPointTy codeGenIP) -> MapInfosTy & {
8684 builder.restoreIP(codeGenIP);
8685 genMapInfos(builder, moduleTranslation, dl, combinedInfos, mapData,
8690 auto *nullPtr = llvm::Constant::getNullValue(builder.getPtrTy());
8691 combinedInfos.BasePointers.push_back(nullPtr);
8692 combinedInfos.Pointers.push_back(nullPtr);
8693 combinedInfos.DevicePointers.push_back(
8694 llvm::OpenMPIRBuilder::DeviceInfoTy::None);
8695 combinedInfos.Sizes.push_back(builder.getInt64(0));
8696 combinedInfos.Types.push_back(
8697 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
8698 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
8699 if (!combinedInfos.Names.empty())
8700 combinedInfos.Names.push_back(nullPtr);
8701 combinedInfos.Mappers.push_back(
nullptr);
8703 return combinedInfos;
8706 auto argAccessorCB = [&](llvm::Argument &arg, llvm::Value *input,
8707 llvm::Value *&retVal, InsertPointTy allocaIP,
8708 InsertPointTy codeGenIP,
8710 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
8711 llvm::IRBuilderBase::InsertPointGuard guard(builder);
8712 builder.SetCurrentDebugLocation(llvm::DebugLoc());
8718 if (!isTargetDevice) {
8719 retVal = cast<llvm::Value>(&arg);
8724 builder, *ompBuilder, moduleTranslation,
8725 allocaIP, codeGenIP, deallocIPs);
8728 llvm::OpenMPIRBuilder::TargetKernelRuntimeAttrs runtimeAttrs;
8729 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs defaultAttrs;
8731 cast<omp::ComposableOpInterface>(*targetOp).findCapturedOp();
8733 isTargetDevice, isGPU);
8737 if (!isTargetDevice)
8739 targetCapturedOp, runtimeAttrs);
8747 for (
auto [arg, var] : llvm::zip_equal(hostEvalBlockArgs, hostEvalVars)) {
8748 llvm::Value *value = moduleTranslation.
lookupValue(var);
8749 moduleTranslation.
mapValue(arg, value);
8751 if (!llvm::isa<llvm::Constant>(value))
8752 kernelInput.push_back(value);
8755 for (
size_t i = 0, e = mapData.OriginalValue.size(); i != e; ++i) {
8764 bool isAttachMap = (mapData.Types[i] &
8765 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH) ==
8766 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH;
8767 if (!mapData.IsDeclareTarget[i] && !mapData.IsAMember[i] && !isAttachMap)
8768 kernelInput.push_back(mapData.OriginalValue[i]);
8772 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
8775 llvm::OpenMPIRBuilder::DependenciesInfo dds;
8777 targetOp.getDependVars(), targetOp.getDependKinds(),
8778 targetOp.getDependIterated(), targetOp.getDependIteratedKinds(),
8779 builder, moduleTranslation, dds)))
8782 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
8784 llvm::OpenMPIRBuilder::TargetDataInfo info(
8788 auto customMapperCB =
8790 if (!combinedInfos.Mappers[i])
8792 info.HasMapper =
true;
8794 moduleTranslation, targetDirective);
8797 llvm::Value *ifCond =
nullptr;
8798 if (
Value targetIfCond = targetOp.getIfExpr())
8799 ifCond = moduleTranslation.
lookupValue(targetIfCond);
8801 Value dynGroupPrivateSize = targetOp.getDynGroupprivateSize();
8802 llvm::Value *dynSizeVal =
nullptr;
8803 if (dynGroupPrivateSize) {
8804 dynSizeVal = moduleTranslation.
lookupValue(dynGroupPrivateSize);
8805 dynSizeVal = builder.CreateIntCast(dynSizeVal, builder.getInt32Ty(),
8809 llvm::omp::OMPDynGroupprivateFallbackType fallbackType =
8812 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
8814 ompLoc, isOffloadEntry, allocaIP, builder.saveIP(), deallocBlocks,
8815 info, entryInfo, defaultAttrs, runtimeAttrs, ifCond, kernelInput,
8816 genMapInfoCB, bodyCB, argAccessorCB, customMapperCB, dds,
8817 targetOp.getNowait(), dynSizeVal, fallbackType);
8822 builder.restoreIP(*afterIP);
8825 builder.CreateFree(dds.DepArray);
8838 llvm::OpenMPIRBuilder *ompBuilder,
8847 if (FunctionOpInterface funcOp = dyn_cast<FunctionOpInterface>(op)) {
8848 if (
auto offloadMod = dyn_cast<omp::OffloadModuleInterface>(
8850 if (!offloadMod.getIsTargetDevice())
8853 omp::DeclareTargetDeviceType declareType =
8854 attribute.getDeviceType().getValue();
8856 if (declareType == omp::DeclareTargetDeviceType::host) {
8857 llvm::Function *llvmFunc =
8859 llvmFunc->dropAllReferences();
8860 llvmFunc->eraseFromParent();
8864 ompBuilder->Builder.ClearInsertionPoint();
8865 ompBuilder->Builder.SetCurrentDebugLocation(llvm::DebugLoc());
8866 }
else if (llvm::Function *llvmFunc =
8878 if (!llvmFunc->isDeclaration() && llvmFunc->hasExternalLinkage() &&
8879 llvmFunc->getVisibility() == llvm::GlobalValue::DefaultVisibility)
8880 llvmFunc->setVisibility(llvm::GlobalValue::HiddenVisibility);
8886 if (LLVM::GlobalOp gOp = dyn_cast<LLVM::GlobalOp>(op)) {
8887 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
8888 if (
auto *gVal = llvmModule->getNamedValue(gOp.getSymName())) {
8889 auto *gVar = cast<llvm::GlobalVariable>(gVal);
8891 bool isDeclaration = gOp.isDeclaration();
8892 bool isExternallyVisible =
8895 llvm::StringRef mangledName = gOp.getSymName();
8896 mlir::omp::DeclareTargetCaptureClause captureClause =
8897 attribute.getCaptureClause().getValue();
8903 std::vector<llvm::GlobalVariable *> generatedRefs;
8905 std::vector<llvm::Triple> targetTriple;
8906 auto targetTripleAttr = dyn_cast_or_null<mlir::StringAttr>(
8908 LLVM::LLVMDialect::getTargetTripleAttrName()));
8909 if (targetTripleAttr)
8910 targetTriple.emplace_back(targetTripleAttr.data());
8912 auto fileInfoCallBack = [&loc]() {
8913 std::string filename =
"";
8914 std::uint64_t lineNo = 0;
8917 filename = loc.getFilename().str();
8918 lineNo = loc.getLine();
8921 return std::pair<std::string, std::uint64_t>(llvm::StringRef(filename),
8925 bool requiresUSM = ompBuilder->Config.hasRequiresUnifiedSharedMemory();
8927 captureClause == omp::DeclareTargetCaptureClause::to ||
8928 captureClause == omp::DeclareTargetCaptureClause::enter;
8929 bool isHostOnly = attribute.getDeviceType().getValue() ==
8930 omp::DeclareTargetDeviceType::host;
8935 if (isToOrEnter && !isHostOnly && !requiresUSM &&
8936 gVar->hasLocalLinkage()) {
8937 gVar->setLinkage(llvm::GlobalValue::ExternalLinkage);
8938 isExternallyVisible =
true;
8942 if (ompBuilder->Config.isTargetDevice())
8943 gVar->setDSOLocal(
false);
8946 llvm::vfs::FileSystem &vfs = moduleTranslation.
getFileSystem();
8947 ompBuilder->registerTargetGlobalVariable(
8948 captureClauseKind, deviceClause, isDeclaration, isExternallyVisible,
8949 ompBuilder->getTargetEntryUniqueInfo(fileInfoCallBack, vfs),
8950 mangledName, generatedRefs,
false, targetTriple,
8952 gVal->getType(), gVal);
8954 if (ompBuilder->Config.isTargetDevice() &&
8955 (captureClause == omp::DeclareTargetCaptureClause::link ||
8957 llvm::Type *ptrTy = gVal->getType();
8961 ptrTy = llvm::PointerType::get(llvmModule->getContext(), 0);
8962 bool addrGlobalCreated = ompBuilder->getAddrOfDeclareTargetVar(
8963 captureClauseKind, deviceClause, isDeclaration, isExternallyVisible,
8964 ompBuilder->getTargetEntryUniqueInfo(fileInfoCallBack, vfs),
8965 mangledName, generatedRefs,
false, targetTriple,
8973 if (addrGlobalCreated)
8974 gVar->setLinkage(llvm::GlobalValue::InternalLinkage);
8980 if (ompBuilder->Config.isTargetDevice() && isHostOnly && isToOrEnter) {
8981 gVar->setLinkage(llvm::GlobalValue::ExternalLinkage);
8982 gVar->setInitializer(
nullptr);
8994class OpenMPDialectLLVMIRTranslationInterface
8995 :
public LLVMTranslationDialectInterface {
8997 using LLVMTranslationDialectInterface::LLVMTranslationDialectInterface;
9002 convertOperation(Operation *op, llvm::IRBuilderBase &builder,
9003 LLVM::ModuleTranslation &moduleTranslation)
const final;
9008 amendOperation(Operation *op, ArrayRef<llvm::Instruction *> instructions,
9009 NamedAttribute attribute,
9010 LLVM::ModuleTranslation &moduleTranslation)
const final;
9015 void registerAllocatedPtr(Value var, llvm::Value *ptr)
const {
9016 ompAllocatedPtrs[var] = ptr;
9021 llvm::Value *lookupAllocatedPtr(Value var)
const {
9022 auto it = ompAllocatedPtrs.find(var);
9023 return it != ompAllocatedPtrs.end() ? it->second :
nullptr;
9035LogicalResult OpenMPDialectLLVMIRTranslationInterface::amendOperation(
9036 Operation *op, ArrayRef<llvm::Instruction *> instructions,
9037 NamedAttribute attribute,
9038 LLVM::ModuleTranslation &moduleTranslation)
const {
9039 return llvm::StringSwitch<llvm::function_ref<LogicalResult(Attribute)>>(
9041 .Case(
"omp.is_target_device",
9042 [&](Attribute attr) {
9043 if (
auto deviceAttr = dyn_cast<BoolAttr>(attr)) {
9044 llvm::OpenMPIRBuilderConfig &config =
9046 config.setIsTargetDevice(deviceAttr.getValue());
9052 [&](Attribute attr) {
9053 if (
auto gpuAttr = dyn_cast<BoolAttr>(attr)) {
9054 llvm::OpenMPIRBuilderConfig &config =
9056 config.setIsGPU(gpuAttr.getValue());
9061 .Case(
"omp.host_ir_filepath",
9062 [&](Attribute attr) {
9063 if (
auto filepathAttr = dyn_cast<StringAttr>(attr)) {
9064 llvm::OpenMPIRBuilder *ompBuilder =
9066 ompBuilder->loadOffloadInfoMetadata(
9067 moduleTranslation.
getFileSystem(), filepathAttr.getValue());
9073 [&](Attribute attr) {
9074 if (
auto rtlAttr = dyn_cast<omp::FlagsAttr>(attr))
9078 .Case(
"omp.version",
9079 [&](Attribute attr) {
9080 if (
auto versionAttr = dyn_cast<omp::VersionAttr>(attr)) {
9081 llvm::OpenMPIRBuilder *ompBuilder =
9083 ompBuilder->M.addModuleFlag(llvm::Module::Max,
"openmp",
9084 versionAttr.getVersion());
9089 .Case(
"omp.declare_target",
9090 [&](Attribute attr) {
9091 if (
auto declareTargetAttr =
9092 dyn_cast<omp::DeclareTargetAttr>(attr)) {
9093 llvm::OpenMPIRBuilder *ompBuilder =
9096 ompBuilder, moduleTranslation);
9100 .Case(
"omp.requires",
9101 [&](Attribute attr) {
9102 if (
auto requiresAttr = dyn_cast<omp::ClauseRequiresAttr>(attr)) {
9103 using Requires = omp::ClauseRequires;
9104 Requires flags = requiresAttr.getValue();
9105 llvm::OpenMPIRBuilderConfig &config =
9107 config.setHasRequiresReverseOffload(
9108 bitEnumContainsAll(flags, Requires::reverse_offload));
9109 config.setHasRequiresUnifiedAddress(
9110 bitEnumContainsAll(flags, Requires::unified_address));
9111 config.setHasRequiresUnifiedSharedMemory(
9112 bitEnumContainsAll(flags, Requires::unified_shared_memory));
9113 config.setHasRequiresDynamicAllocators(
9114 bitEnumContainsAll(flags, Requires::dynamic_allocators));
9119 .Case(
"omp.target_triples",
9120 [&](Attribute attr) {
9121 if (
auto triplesAttr = dyn_cast<ArrayAttr>(attr)) {
9122 llvm::OpenMPIRBuilderConfig &config =
9124 config.TargetTriples.clear();
9125 config.TargetTriples.reserve(triplesAttr.size());
9126 for (Attribute tripleAttr : triplesAttr) {
9127 if (
auto tripleStrAttr = dyn_cast<StringAttr>(tripleAttr))
9128 config.TargetTriples.emplace_back(tripleStrAttr.getValue());
9136 .Default([](Attribute) {
9152 if (
auto declareTargetIface =
9153 llvm::dyn_cast<mlir::omp::DeclareTargetInterface>(
9154 parentFn.getOperation()))
9155 if (declareTargetIface.isDeclareTarget() &&
9156 declareTargetIface.getDeclareTargetDeviceType() !=
9157 mlir::omp::DeclareTargetDeviceType::host)
9167 llvm::Module *llvmModule) {
9168 llvm::Type *i64Ty = builder.getInt64Ty();
9169 llvm::Type *i32Ty = builder.getInt32Ty();
9170 llvm::Type *returnType = builder.getPtrTy(0);
9171 llvm::FunctionType *fnType =
9172 llvm::FunctionType::get(returnType, {i64Ty, i32Ty},
false);
9173 llvm::Function *
func = cast<llvm::Function>(
9174 llvmModule->getOrInsertFunction(
"omp_target_alloc", fnType).getCallee());
9178template <
typename T>
9182 llvm::DataLayout dataLayout =
9184 llvm::Type *llvmHeapTy =
9185 moduleTranslation.
convertType(op.getMemElemTypeAttr().getValue());
9187 auto alignment = op.getMemAlignment();
9188 llvm::TypeSize typeSize = llvm::alignTo(
9189 dataLayout.getTypeStoreSize(llvmHeapTy),
9190 alignment ? *alignment : dataLayout.getABITypeAlign(llvmHeapTy).value());
9192 llvm::Value *allocSize = builder.getInt64(typeSize.getFixedValue());
9193 return builder.CreateMul(
9195 builder.CreateIntCast(moduleTranslation.
lookupValue(op.getMemArraySize()),
9196 builder.getInt64Ty(),
9203 omp::TargetAllocMemOp op) {
9204 llvm::DataLayout dataLayout =
9206 llvm::Type *llvmHeapTy = moduleTranslation.
convertType(op.getAllocatedType());
9207 llvm::TypeSize typeSize = dataLayout.getTypeAllocSize(llvmHeapTy);
9208 llvm::Value *allocSize = builder.getInt64(typeSize.getFixedValue());
9209 for (
auto typeParam : op.getTypeparams()) {
9210 allocSize = builder.CreateMul(
9212 builder.CreateIntCast(moduleTranslation.
lookupValue(typeParam),
9213 builder.getInt64Ty(),
9222 auto allocMemOp = cast<omp::TargetAllocMemOp>(opInst);
9227 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
9231 llvm::Value *llvmDeviceNum = moduleTranslation.
lookupValue(deviceNum);
9233 llvm::Value *allocSize =
9236 llvm::CallInst *call =
9237 builder.CreateCall(ompTargetAllocFunc, {allocSize, llvmDeviceNum});
9238 llvm::Value *resultI64 = builder.CreatePtrToInt(call, builder.getInt64Ty());
9241 moduleTranslation.
mapValue(allocMemOp.getResult(), resultI64);
9247 llvm::IRBuilderBase &builder,
9251 moduleTranslation.
mapValue(allocMemOp.getResult(),
9252 ompBuilder->createOMPAllocShared(builder, size));
9259 const OpenMPDialectLLVMIRTranslationInterface &ompIface) {
9260 auto allocateDirOp = cast<omp::AllocateDirOp>(opInst);
9263 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
9264 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
9265 llvm::DataLayout dataLayout = llvmModule->getDataLayout();
9267 std::optional<int64_t> alignAttr = allocateDirOp.getAlign();
9269 llvm::Value *allocator;
9270 if (
auto allocatorVar = allocateDirOp.getAllocator()) {
9271 allocator = moduleTranslation.
lookupValue(allocatorVar);
9272 if (allocator->getType()->isIntegerTy())
9273 allocator = builder.CreateIntToPtr(allocator, builder.getPtrTy());
9274 else if (allocator->getType()->isPointerTy())
9275 allocator = builder.CreatePointerBitCastOrAddrSpaceCast(
9276 allocator, builder.getPtrTy());
9278 allocator = llvm::ConstantPointerNull::get(builder.getPtrTy());
9281 for (
Value var : vars) {
9282 llvm::Type *llvmVarTy = moduleTranslation.
convertType(var.getType());
9286 llvm::Type *typeToInspect = llvmVarTy;
9287 if (llvmVarTy->isPointerTy()) {
9290 if (
auto gop = dyn_cast<LLVM::GlobalOp>(globalOp))
9291 typeToInspect = moduleTranslation.
convertType(gop.getGlobalType());
9296 if (
auto arrTy = llvm::dyn_cast<llvm::ArrayType>(typeToInspect)) {
9297 llvm::Value *elementCount = builder.getInt64(1);
9298 llvm::Type *currentType = arrTy;
9299 while (
auto nestedArrTy = llvm::dyn_cast<llvm::ArrayType>(currentType)) {
9300 elementCount = builder.CreateMul(
9301 elementCount, builder.getInt64(nestedArrTy->getNumElements()));
9302 currentType = nestedArrTy->getElementType();
9304 uint64_t elemSizeInBits = dataLayout.getTypeSizeInBits(currentType);
9306 builder.CreateMul(elementCount, builder.getInt64(elemSizeInBits / 8));
9308 size = builder.getInt64(
9309 dataLayout.getTypeStoreSize(typeToInspect).getFixedValue());
9312 uint64_t alignValue =
9313 alignAttr ? alignAttr.value()
9314 : dataLayout.getABITypeAlign(typeToInspect).value();
9315 llvm::Value *alignConst = builder.getInt64(alignValue);
9317 size = builder.CreateAdd(size, builder.getInt64(alignValue - 1),
"",
true);
9318 size = builder.CreateUDiv(size, alignConst);
9319 size = builder.CreateMul(size, alignConst,
"",
true);
9321 std::string allocName =
9322 ompBuilder->createPlatformSpecificName({
".void.addr"});
9323 llvm::CallInst *allocCall;
9324 if (alignAttr.has_value()) {
9325 allocCall = ompBuilder->createOMPAlignedAlloc(
9326 ompLoc, builder.getInt64(alignAttr.value()), size, allocator,
9330 ompBuilder->createOMPAlloc(ompLoc, size, allocator, allocName);
9333 ompIface.registerAllocatedPtr(var, allocCall);
9342 const OpenMPDialectLLVMIRTranslationInterface &ompIface) {
9343 auto freeOp = cast<omp::AllocateFreeOp>(opInst);
9345 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
9347 llvm::Value *allocator;
9348 if (
auto allocatorVar = freeOp.getAllocator()) {
9349 allocator = moduleTranslation.
lookupValue(allocatorVar);
9350 if (allocator->getType()->isIntegerTy())
9351 allocator = builder.CreateIntToPtr(allocator, builder.getPtrTy());
9352 else if (allocator->getType()->isPointerTy())
9353 allocator = builder.CreatePointerBitCastOrAddrSpaceCast(
9354 allocator, builder.getPtrTy());
9356 allocator = llvm::ConstantPointerNull::get(builder.getPtrTy());
9361 for (
Value var : llvm::reverse(vars)) {
9362 llvm::Value *allocPtr = ompIface.lookupAllocatedPtr(var);
9364 return opInst.
emitError(
"omp.allocate_free: no allocation recorded");
9365 ompBuilder->createOMPFree(ompLoc, allocPtr, allocator,
"");
9372 llvm::Module *llvmModule) {
9373 llvm::Type *ptrTy = builder.getPtrTy(0);
9374 llvm::Type *i32Ty = builder.getInt32Ty();
9375 llvm::Type *voidTy = builder.getVoidTy();
9376 llvm::FunctionType *fnType =
9377 llvm::FunctionType::get(voidTy, {ptrTy, i32Ty},
false);
9378 llvm::Function *
func = dyn_cast<llvm::Function>(
9379 llvmModule->getOrInsertFunction(
"omp_target_free", fnType).getCallee());
9386 auto freeMemOp = cast<omp::TargetFreeMemOp>(opInst);
9391 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
9395 llvm::Value *llvmDeviceNum = moduleTranslation.
lookupValue(deviceNum);
9398 llvm::Value *llvmHeapref = moduleTranslation.
lookupValue(heapref);
9400 llvm::Value *intToPtr =
9401 builder.CreateIntToPtr(llvmHeapref, builder.getPtrTy(0));
9402 builder.CreateCall(ompTragetFreeFunc, {intToPtr, llvmDeviceNum});
9408 llvm::IRBuilderBase &builder,
9412 ompBuilder->createOMPFreeShared(
9413 builder, moduleTranslation.
lookupValue(freeMemOp.getHeapref()), size);
9422 auto groupprivateOp = cast<omp::GroupprivateOp>(opInst);
9427 bool isTargetDevice = ompBuilder->Config.isTargetDevice();
9431 bool shouldAllocate =
true;
9432 switch (groupprivateOp.getDeviceType().value_or(
9433 mlir::omp::DeclareTargetDeviceType::any)) {
9434 case mlir::omp::DeclareTargetDeviceType::host:
9435 shouldAllocate = !isTargetDevice;
9437 case mlir::omp::DeclareTargetDeviceType::nohost:
9438 shouldAllocate = isTargetDevice;
9440 case mlir::omp::DeclareTargetDeviceType::any:
9441 shouldAllocate =
true;
9447 &opInst, groupprivateOp.getSymNameAttr());
9450 <<
"expected symbol '" << groupprivateOp.getSymName()
9451 <<
"' to reference an LLVM global variable";
9453 llvm::GlobalValue *globalValue = moduleTranslation.
lookupGlobal(global);
9454 llvm::Type *varType = moduleTranslation.
convertType(global.getType());
9455 std::string varName = globalValue->getName().str();
9457 llvm::Value *resultPtr;
9458 if (shouldAllocate && isTargetDevice) {
9459 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
9460 llvm::Triple targetTriple(llvmModule->getTargetTriple());
9461 unsigned sharedAddressSpace;
9462 if (targetTriple.isAMDGCN())
9463 sharedAddressSpace = llvm::AMDGPUAS::LOCAL_ADDRESS;
9464 else if (targetTriple.isNVPTX())
9465 sharedAddressSpace = llvm::NVPTXAS::ADDRESS_SPACE_SHARED;
9467 return opInst.
emitError() <<
"groupprivate is not supported for target: "
9468 << targetTriple.str();
9469 llvm::GlobalVariable *sharedVar =
new llvm::GlobalVariable(
9470 *llvmModule, varType,
false,
9471 llvm::GlobalValue::InternalLinkage, llvm::PoisonValue::get(varType),
9472 varName,
nullptr, llvm::GlobalValue::NotThreadLocal,
9475 resultPtr = sharedVar;
9477 if (shouldAllocate && !isTargetDevice)
9478 opInst.
emitWarning(
"groupprivate directive is currently ignored on the "
9479 "host, using original global");
9480 resultPtr = globalValue;
9489LogicalResult OpenMPDialectLLVMIRTranslationInterface::convertOperation(
9490 Operation *op, llvm::IRBuilderBase &builder,
9491 LLVM::ModuleTranslation &moduleTranslation)
const {
9494 if (ompBuilder->Config.isTargetDevice() &&
9495 !isa<omp::TargetOp, omp::MapInfoOp, omp::TerminatorOp, omp::YieldOp>(
9498 return op->
emitOpError() <<
"unsupported host op found in device";
9506 bool isOutermostLoopWrapper =
9507 isa_and_present<omp::LoopWrapperInterface>(op) &&
9508 !dyn_cast_if_present<omp::LoopWrapperInterface>(op->
getParentOp());
9517 if (isa<omp::TaskloopContextOp>(op))
9518 isOutermostLoopWrapper =
true;
9519 else if (isa<omp::TaskloopWrapperOp>(op))
9520 isOutermostLoopWrapper =
false;
9522 if (isOutermostLoopWrapper)
9523 moduleTranslation.
stackPush<OpenMPLoopInfoStackFrame>();
9526 llvm::TypeSwitch<Operation *, LogicalResult>(op)
9527 .Case([&](omp::BarrierOp op) -> LogicalResult {
9531 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
9532 ompBuilder->createBarrier(builder.saveIP(),
9533 llvm::omp::OMPD_barrier);
9535 if (res.succeeded()) {
9538 builder.restoreIP(*afterIP);
9542 .Case([&](omp::TaskyieldOp op) {
9546 ompBuilder->createTaskyield(builder.saveIP());
9549 .Case([&](omp::FlushOp op) {
9561 ompBuilder->createFlush(builder.saveIP());
9564 .Case([&](omp::ParallelOp op) {
9567 .Case([&](omp::MaskedOp) {
9570 .Case([&](omp::MasterOp) {
9573 .Case([&](omp::CriticalOp) {
9576 .Case([&](omp::OrderedRegionOp) {
9579 .Case([&](omp::OrderedOp) {
9582 .Case([&](omp::WsloopOp) {
9585 .Case([&](omp::SimdOp) {
9588 .Case([&](omp::AtomicReadOp) {
9591 .Case([&](omp::AtomicWriteOp) {
9594 .Case([&](omp::AtomicUpdateOp op) {
9597 .Case([&](omp::AtomicCaptureOp op) {
9600 .Case([&](omp::AtomicCompareOp op) {
9603 .Case([&](omp::CancelOp op) {
9606 .Case([&](omp::CancellationPointOp op) {
9609 .Case([&](omp::SectionsOp) {
9612 .Case([&](omp::ScopeOp op) {
9615 .Case([&](omp::SingleOp op) {
9618 .Case([&](omp::TeamsOp op) {
9621 .Case([&](omp::TaskOp op) {
9624 .Case([&](omp::TaskloopWrapperOp op) {
9627 .Case([&](omp::TaskloopContextOp op) {
9630 .Case([&](omp::TaskgroupOp op) {
9633 .Case([&](omp::TaskwaitOp op) {
9636 .Case<omp::YieldOp, omp::TerminatorOp, omp::DeclareMapperOp,
9637 omp::DeclareMapperInfoOp, omp::DeclareReductionOp,
9638 omp::CriticalDeclareOp>([](
auto op) {
9651 .Case([&](omp::ThreadprivateOp) {
9654 .Case<omp::TargetDataOp, omp::TargetEnterDataOp,
9655 omp::TargetExitDataOp, omp::TargetUpdateOp>([&](
auto op) {
9658 .Case([&](omp::TargetOp) {
9661 .Case([&](omp::DistributeOp) {
9664 .Case([&](omp::LoopNestOp) {
9667 .Case<omp::MapInfoOp, omp::MapBoundsOp, omp::PrivateClauseOp,
9668 omp::AffinityEntryOp, omp::IteratorOp>([&](
auto op) {
9674 .Case([&](omp::NewCliOp op) {
9679 .Case([&](omp::CanonicalLoopOp op) {
9682 .Case([&](omp::UnrollHeuristicOp op) {
9691 .Case([&](omp::TileOp op) {
9692 return applyTile(op, builder, moduleTranslation);
9694 .Case([&](omp::FuseOp op) {
9695 return applyFuse(op, builder, moduleTranslation);
9697 .Case([&](omp::TargetAllocMemOp) {
9700 .Case([&](omp::TargetFreeMemOp) {
9703 .Case([&](omp::AllocateDirOp) {
9706 .Case([&](omp::AllocateFreeOp) {
9710 .Case([&](omp::AllocSharedMemOp op) {
9713 .Case([&](omp::FreeSharedMemOp op) {
9716 .Case([&](omp::GroupprivateOp) {
9719 .Default([&](Operation *inst) {
9721 <<
"not yet implemented: " << inst->
getName();
9724 if (isOutermostLoopWrapper)
9731 registry.
insert<omp::OpenMPDialect>();
9733 dialect->addInterfaces<OpenMPDialectLLVMIRTranslationInterface>();
static mlir::LogicalResult buildDependData(OperandRange dependVars, std::optional< ArrayAttr > dependKinds, OperandRange dependIterated, std::optional< ArrayAttr > dependIteratedKinds, llvm::IRBuilderBase &builder, mlir::LLVM::ModuleTranslation &moduleTranslation, llvm::OpenMPIRBuilder::DependenciesInfo &taskDeps)
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 void mapParentWithMembers(LLVM::ModuleTranslation &moduleTranslation, llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder &ompBuilder, DataLayout &dl, MapInfosTy &combinedInfo, MapInfoData &mapData, uint64_t mapDataIndex, llvm::omp::OpenMPOffloadMappingFlags memberOfFlag, TargetDirectiveEnumTy targetDirective)
static void processIndividualMap(llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder &ompBuilder, MapInfoData &mapData, size_t mapDataIdx, MapInfosTy &combinedInfo, TargetDirectiveEnumTy targetDirective, llvm::omp::OpenMPOffloadMappingFlags memberOfFlag=llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE, bool isTargetParam=true, int mapDataParentIdx=-1)
This function handles the insertion of a single item of map data from MapInfoData into the OMPIRBuild...
static llvm::OpenMPIRBuilder::InsertPointTy findAllocInsertPoints(llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, llvm::SmallVectorImpl< llvm::BasicBlock * > *deallocBlocks=nullptr)
Find the insertion point for allocas given the current insertion point for normal operations in the b...
static void sortMapIndices(llvm::SmallVectorImpl< size_t > &indices, omp::MapInfoOp mapInfo, bool first=true)
static LogicalResult convertOmpAtomicCapture(omp::AtomicCaptureOp atomicCaptureOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
owningDataPtrPtrReductionGens[i]
static LogicalResult convertOmpTaskloopContextOp(omp::TaskloopContextOp contextOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static Operation * getGlobalOpFromValue(Value value)
static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind convertToCaptureClauseKind(mlir::omp::DeclareTargetCaptureClause captureClause)
static mlir::LogicalResult convertIteratorRegion(llvm::Value *linearIV, IteratorInfo &iterInfo, mlir::Block &iteratorRegionBlock, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static omp::MapInfoOp getFirstOrLastMappedMemberPtr(omp::MapInfoOp mapInfo, bool first)
static OpTy castOrGetParentOfType(Operation *op, bool immediateParent=false)
If op is of the given type parameter, return it casted to that type. Otherwise, if its immediate pare...
static LogicalResult convertOmpOrderedRegion(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP 'ordered_region' operation into LLVM IR using OpenMPIRBuilder.
static LogicalResult convertFreeSharedMemOp(omp::FreeSharedMemOp freeMemOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static LogicalResult convertTargetFreeMemOp(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
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 OwningDataPtrPtrReductionGen makeRefDataPtrGen(omp::DeclareReductionOp decl, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, bool isByRef)
Create an OpenMPIRBuilder-compatible data_ptr_ptr reduction generator for the given reduction declara...
static void popCancelFinalizationCB(const ArrayRef< llvm::UncondBrInst * > cancelTerminators, llvm::OpenMPIRBuilder &ompBuilder, const llvm::OpenMPIRBuilder::InsertPointTy &afterIP)
If we cancelled the construct, we should branch to the finalization block of that construct....
static llvm::Value * getRefPtrIfDeclareTarget(Value value, LLVM::ModuleTranslation &moduleTranslation)
static llvm::Function * emitTaskReductionCombFn(omp::DeclareReductionOp decl, StringRef baseName, LLVM::ModuleTranslation &moduleTranslation)
Build an outlined combiner helper for a task_reduction declare_reduction op. Signature: void(ptr lhs,...
static LogicalResult convertOmpWsloop(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP workshare loop into LLVM IR using OpenMPIRBuilder.
static LogicalResult applyUnrollHeuristic(omp::UnrollHeuristicOp op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Apply a #pragma omp unroll / "!$omp unroll" transformation using the OpenMPIRBuilder.
static LogicalResult convertOmpMaster(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP 'master' operation into LLVM IR using OpenMPIRBuilder.
static void getAsIntegers(ArrayAttr values, llvm::SmallVector< int64_t > &ints)
static llvm::Value * findAssociatedValue(Value privateVar, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, llvm::DenseMap< Value, Value > *mappedPrivateVars=nullptr)
Return the llvm::Value * corresponding to the privateVar that is being privatized....
static ArrayRef< bool > getIsByRef(std::optional< ArrayRef< bool > > attr)
static llvm::Expected< llvm::Value * > lookupOrTranslatePureValue(Value value, LLVM::ModuleTranslation &moduleTranslation, llvm::IRBuilderBase &builder)
Look up the given value in the mapping, and if it's not there, translate its defining operation at th...
static LogicalResult allocReductionVars(T op, 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 void emitTaskReductionModifierFini(bool isWorksharing, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Emits __kmpc_task_reduction_modifier_fini(loc, gtid, is_ws) at the current builder insertion point,...
static LogicalResult convertOmpTaskwaitOp(omp::TaskwaitOp twOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static LogicalResult collectAndValidateTaskloopRedDecls(Operation *contextOp, std::optional< ArrayAttr > syms, StringRef opName, StringRef clauseName, SmallVectorImpl< omp::DeclareReductionOp > &out)
Look up and validate the declare_reduction ops referenced by a reduction-like clause on the omp....
static LogicalResult convertOmpLoopNest(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP loop nest into LLVM IR using OpenMPIRBuilder.
static mlir::LogicalResult fillIteratorLoop(mlir::omp::IteratorOp itersOp, llvm::IRBuilderBase &builder, mlir::LLVM::ModuleTranslation &moduleTranslation, IteratorInfo &iterInfo, llvm::StringRef loopName, IteratorStoreEntryTy genStoreEntry)
static llvm::Expected< llvm::BasicBlock * > allocatePrivateVars(T op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, PrivateVarsInfo &privateVarsInfo, const llvm::OpenMPIRBuilder::InsertPointTy &allocaIP, llvm::DenseMap< Value, Value > *mappedPrivateVars=nullptr)
Allocate and initialize delayed private variables. Returns the basic block which comes after all of t...
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.
static void genMapInfos(llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, DataLayout &dl, MapInfosTy &combinedInfo, MapInfoData &mapData, TargetDirectiveEnumTy targetDirective)
static llvm::AtomicOrdering convertAtomicOrdering(std::optional< omp::ClauseMemoryOrderKind > ao)
Convert an Atomic Ordering attribute to llvm::AtomicOrdering.
static void setInsertPointForPossiblyEmptyBlock(llvm::IRBuilderBase &builder, llvm::BasicBlock *block=nullptr)
llvm::function_ref< void(llvm::Value *linearIV, mlir::omp::YieldOp yield)> IteratorStoreEntryTy
static llvm::Function * emitTaskReductionInitFn(omp::DeclareReductionOp decl, StringRef baseName, LLVM::ModuleTranslation &moduleTranslation)
Build an outlined init helper for a task_reduction declare_reduction op. Signature: void(ptr priv,...
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 convertTargetAllocMemOp(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static omp::DistributeOp getDistributeCapturingTeamsReduction(omp::TeamsOp teamsOp)
static LogicalResult convertOmpCanonicalLoopOp(omp::CanonicalLoopOp op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Convert an omp.canonical_loop to LLVM-IR.
static LogicalResult convertOmpTargetData(Operation *op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static std::optional< int64_t > extractConstInteger(Value value)
If the given value is defined by an llvm.mlir.constant operation and it is of an integer type,...
static llvm::Expected< llvm::Value * > initPrivateVar(llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, omp::PrivateClauseOp &privDecl, llvm::Value *nonPrivateVar, BlockArgument &blockArg, llvm::Value *llvmPrivateVar, llvm::BasicBlock *privInitBlock, llvm::DenseMap< Value, Value > *mappedPrivateVars=nullptr)
Initialize a single (first)private variable. You probably want to use allocateAndInitPrivateVars inst...
static mlir::LogicalResult buildAffinityData(mlir::omp::TaskOp &taskOp, llvm::IRBuilderBase &builder, mlir::LLVM::ModuleTranslation &moduleTranslation, llvm::OpenMPIRBuilder::AffinityData &ad)
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 convertOmpDistribute(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static llvm::Value * getAllocationSize(llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, T op)
static llvm::Function * getOmpTargetAlloc(llvm::IRBuilderBase &builder, llvm::Module *llvmModule)
static llvm::omp::OMPDynGroupprivateFallbackType getDynGroupprivateFallbackType(omp::FallbackModifierAttr fallbackAttr)
static llvm::Expected< llvm::Function * > emitUserDefinedMapper(Operation *declMapperOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, llvm::StringRef mapperFuncName, TargetDirectiveEnumTy targetDirective)
static LogicalResult convertOmpOrdered(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP 'ordered' operation into LLVM IR using OpenMPIRBuilder.
static LogicalResult cleanupPrivateVars(T op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, Location loc, PrivateVarsInfo &privateVarsInfo)
static void processMapWithMembersOf(LLVM::ModuleTranslation &moduleTranslation, llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder &ompBuilder, DataLayout &dl, MapInfosTy &combinedInfo, MapInfoData &mapData, uint64_t mapDataIndex, TargetDirectiveEnumTy targetDirective)
static LogicalResult convertOmpMasked(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP 'masked' operation into LLVM IR using OpenMPIRBuilder.
static llvm::AtomicRMWInst::BinOp convertBinOpToAtomic(Operation &op)
Converts an LLVM dialect binary operation to the corresponding enum value for atomicrmw supported bin...
static LogicalResult convertOmpCancel(omp::CancelOp op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static int getMapDataMemberIdx(MapInfoData &mapData, omp::MapInfoOp memberOp)
allocatedType moduleTranslation static convertType(allocatedType) 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 LogicalResult applyFuse(omp::FuseOp op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Apply a #pragma omp fuse / !$omp fuse transformation using the OpenMPIRBuilder.
static llvm::Value * materializeRegionArgValue(llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, BlockArgument regionArg, llvm::Value *value)
static LogicalResult convertOmpScope(omp::ScopeOp &scopeOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP scope construct into LLVM IR.
static llvm::Value * getSizeInBytes(DataLayout &dl, const mlir::Type &type, Operation *clauseOp, llvm::Value *basePointer, llvm::Type *baseType, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static llvm::Error initPrivateVars(llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, PrivateVarsInfo &privateVarsInfo, llvm::DenseMap< Value, Value > *mappedPrivateVars=nullptr)
static LogicalResult convertAllocSharedMemOp(omp::AllocSharedMemOp allocMemOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static llvm::CanonicalLoopInfo * findCurrentLoopInfo(LLVM::ModuleTranslation &moduleTranslation)
Find the loop information structure for the loop nest being translated.
static OwningReductionGen makeReductionGen(omp::DeclareReductionOp decl, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Create an OpenMPIRBuilder-compatible reduction generator for the given reduction declaration.
static 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 storeAffinityEntry(llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder &ompBuilder, llvm::Value *affinityList, llvm::Value *index, llvm::Value *addr, llvm::Value *len)
static LogicalResult convertOmpParallel(omp::ParallelOp opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts the OpenMP parallel operation to LLVM IR.
static void pushCancelFinalizationCB(SmallVectorImpl< llvm::UncondBrInst * > &cancelTerminators, llvm::IRBuilderBase &llvmBuilder, llvm::OpenMPIRBuilder &ompBuilder, mlir::Operation *op, llvm::omp::Directive cancelDirective)
Shared implementation of a callback which adds a termiator for the new block created for the branch t...
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 void getTargetEntryUniqueInfo(llvm::TargetRegionEntryInfo &targetInfo, omp::TargetOp targetOp, llvm::OpenMPIRBuilder &ompBuilder, llvm::vfs::FileSystem &vfs, llvm::StringRef parentName="")
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 convertOmpGroupprivate(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP groupprivate operation into LLVM IR.
static llvm::Expected< llvm::Function * > getOrCreateUserDefinedMapperFunc(Operation *op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, TargetDirectiveEnumTy targetDirective)
static uint64_t getTypeByteSize(mlir::Type type, const DataLayout &dl)
static llvm::SmallString< 64 > getDeclareTargetRefPtrSuffix(LLVM::GlobalOp globalOp, llvm::OpenMPIRBuilder &ompBuilder, llvm::vfs::FileSystem &vfs)
static void extractHostEvalClauses(omp::TargetOp targetOp, Value &numThreads, Value &numTeamsLower, Value &numTeamsUpper, Value &threadLimit, llvm::SmallVectorImpl< Value > *lowerBounds=nullptr, llvm::SmallVectorImpl< Value > *upperBounds=nullptr, llvm::SmallVectorImpl< Value > *steps=nullptr)
Follow uses of host_eval-defined block arguments of the given omp.target operation and populate outpu...
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 convertOmpAtomicCompare(omp::AtomicCompareOp atomicCompareOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an omp.atomic.compare operation to LLVM IR.
static LogicalResult copyFirstPrivateVars(mlir::Operation *op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, SmallVectorImpl< llvm::Value * > &moldVars, ArrayRef< llvm::Value * > llvmPrivateVars, SmallVectorImpl< omp::PrivateClauseOp > &privateDecls, bool insertBarrier, llvm::DenseMap< Value, Value > *mappedPrivateVars=nullptr)
static LogicalResult convertAllocateDirOp(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, const OpenMPDialectLLVMIRTranslationInterface &ompIface)
static bool constructIsCancellable(Operation *op)
Returns true if the construct contains omp.cancel or omp.cancellation_point.
static llvm::omp::OpenMPOffloadMappingFlags convertClauseMapFlags(omp::ClauseMapFlags mlirFlags)
static void buildDependDataLocator(std::optional< ArrayAttr > dependKinds, OperandRange dependVars, LLVM::ModuleTranslation &moduleTranslation, SmallVectorImpl< llvm::OpenMPIRBuilder::DependData > &dds)
static std::optional< llvm::omp::OMPAtomicCompareOp > convertFCmpPredicateToAtomicCompareOp(LLVM::FCmpPredicate predicate)
Helper to extract the OMPAtomicCompareOp from a floating-point comparison predicate....
static llvm::Value * emitTaskReductionInitCall(ArrayRef< omp::DeclareReductionOp > redDecls, ArrayRef< llvm::Value * > origPtrs, StringRef helperNamePrefix, llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder::InsertPointTy allocaIP, LLVM::ModuleTranslation &moduleTranslation, bool isModifier=false, bool isWorksharing=false)
Emit the per-taskgroup task_reduction descriptor array and the __kmpc_taskred_init runtime call....
static void mapInitializationArgs(T loop, LLVM::ModuleTranslation &moduleTranslation, llvm::IRBuilderBase &builder, SmallVectorImpl< omp::DeclareReductionOp > &reductionDecls, DenseMap< Value, llvm::Value * > &reductionVariableMap, unsigned i)
Map input arguments to reduction initialization region.
static llvm::omp::ProcBindKind getProcBindKind(omp::ClauseProcBindKind kind)
Convert ProcBindKind from MLIR-generated enum to LLVM enum.
static void fillAffinityLocators(Operation::operand_range affinityVars, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, llvm::Value *affinityList)
static LogicalResult convertOmpTaskloopWrapperOp(omp::TaskloopWrapperOp loopWrapperOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
The correct entry point is convertOmpTaskloopContextOp. This gets called whilst lowering the body of ...
static void getOverlappedMembers(llvm::SmallVectorImpl< size_t > &overlapMapDataIdxs, omp::MapInfoOp parentOp)
static LogicalResult convertOmpSingle(omp::SingleOp &singleOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP single construct into LLVM IR using OpenMPIRBuilder.
static bool isDeclareTargetTo(Value value)
static uint64_t getArrayElementSizeInBits(LLVM::LLVMArrayType arrTy, DataLayout &dl)
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 LogicalResult convertOmpTarget(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind convertToDeviceClauseKind(mlir::omp::DeclareTargetDeviceType deviceClause)
static std::optional< llvm::omp::OMPAtomicCompareOp > convertICmpPredicateToAtomicCompareOp(LLVM::ICmpPredicate predicate)
Helper to extract the OMPAtomicCompareOp from an integer comparison predicate. Returns std::nullopt f...
static llvm::Error computeTaskloopBounds(omp::LoopNestOp loopOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, llvm::Value *&lbVal, llvm::Value *&ubVal, llvm::Value *&stepVal)
static LogicalResult checkImplementationStatus(Operation &op)
Check whether translation to LLVM IR for the given operation is currently supported.
static llvm::IRBuilderBase::InsertPoint createDeviceArgumentAccessor(omp::TargetOp targetOp, 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, llvm::ArrayRef< llvm::IRBuilderBase::InsertPoint > deallocIPs)
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, bool isNowait=false, bool isTeamsReduction=false)
static LogicalResult convertOmpCancellationPoint(omp::CancellationPointOp op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static bool opIsInSingleThread(mlir::Operation *op)
This can't always be determined statically, but when we can, it is good to avoid generating compiler-...
static uint64_t getReductionDataSize(OpTy &op)
static LogicalResult convertOmpAtomicRead(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Convert omp.atomic.read operation to LLVM IR.
static llvm::omp::Directive convertCancellationConstructType(omp::ClauseCancellationConstructType directive)
static void initTargetDefaultAttrs(omp::TargetOp targetOp, Operation *capturedOp, llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &attrs, bool isTargetDevice, bool isGPU)
Populate default MinTeams, MaxTeams and MaxThreads to their default values as stated by the correspon...
static llvm::omp::RTLDependenceKindTy convertDependKind(mlir::omp::ClauseTaskDepend kind)
static void initTargetRuntimeAttrs(llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, omp::TargetOp targetOp, Operation *capturedOp, llvm::OpenMPIRBuilder::TargetKernelRuntimeAttrs &attrs)
Gather LLVM runtime values for all clauses evaluated in the host that are passed to the kernel invoca...
static LogicalResult convertOmpTeams(omp::TeamsOp op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static Value getBaseValueForTypeLookup(Value value)
static bool isHostDeviceOp(Operation *op)
static LogicalResult convertDeclareTargetAttr(Operation *op, mlir::omp::DeclareTargetAttr attribute, llvm::OpenMPIRBuilder *ompBuilder, LLVM::ModuleTranslation &moduleTranslation)
static bool isDeclareTargetLink(Value value)
static LogicalResult convertFlagsAttr(Operation *op, mlir::omp::FlagsAttr attribute, LLVM::ModuleTranslation &moduleTranslation)
Lowers the FlagsAttr which is applied to the module when offloading. This attribute contains OpenMP R...
static bool checkIfPointerMap(omp::MapInfoOp mapOp)
static LogicalResult applyTile(omp::TileOp op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Apply a #pragma omp tile / !$omp tile transformation using the OpenMPIRBuilder.
static LogicalResult convertAllocateFreeOp(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, const OpenMPDialectLLVMIRTranslationInterface &ompIface)
static llvm::Function * getOmpTargetFree(llvm::IRBuilderBase &builder, llvm::Module *llvmModule)
static LogicalResult convertOmpTaskgroupOp(omp::TaskgroupOp tgOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP taskgroup construct into LLVM IR using OpenMPIRBuilder.
static void collectMapDataFromMapOperands(MapInfoData &mapData, SmallVectorImpl< Value > &mapVars, LLVM::ModuleTranslation &moduleTranslation, DataLayout &dl, llvm::IRBuilderBase &builder, ArrayRef< Value > useDevPtrOperands={}, ArrayRef< Value > useDevAddrOperands={}, ArrayRef< Value > hasDevAddrOperands={})
static void extractAtomicControlFlags(omp::AtomicUpdateOp atomicUpdateOp, bool &isIgnoreDenormalMode, bool &isFineGrainedMemory, bool &isRemoteMemory)
static Operation * genLoop(CodegenEnv &env, OpBuilder &builder, LoopId curr, unsigned numCases, bool needsUniv, ArrayRef< TensorLevel > tidLvls)
Generates a for-loop or a while-loop, depending on whether it implements singleton iteration or co-it...
#define MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(CLASS_NAME)
Attributes are known-constant values of operations.
This class represents an argument of a Block.
Block represents an ordered list of Operations.
BlockArgument getArgument(unsigned i)
unsigned getNumArguments()
OpListType & getOperations()
Operation * getTerminator()
Get the terminator operation of this block.
iterator_range< iterator > without_terminator()
Return an iterator range over the operation within this block excluding the terminator operation at t...
The main mechanism for performing data layout queries.
llvm::TypeSize getTypeSize(Type t) const
Returns the size of the given type in the current scope.
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.
An instance of this location represents a tuple of file, line number, and column number.
Implementation class for module translation.
llvm::BasicBlock * lookupBlock(Block *block) const
Finds an LLVM IR basic block that corresponds to the given MLIR block.
WalkResult stackWalk(llvm::function_ref< WalkResult(T &)> callback)
Calls callback for every ModuleTranslation stack frame of type T starting from the top of the stack.
void stackPush(Args &&...args)
Creates a stack frame of type T on ModuleTranslation stack.
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.
void mapFunction(StringRef name, llvm::Function *func)
Stores the mapping between a function name and its LLVM IR representation.
llvm::Value * lookupValue(Value value) const
Finds an LLVM IR value corresponding to the given MLIR value.
void invalidateOmpLoop(omp::NewCliOp mlir)
Mark an OpenMP loop as having been consumed.
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::vfs::FileSystem & getFileSystem()
Returns the virtual filesystem to use for file operations.
void mapOmpLoop(omp::NewCliOp mlir, llvm::CanonicalLoopInfo *llvm)
Map an MLIR OpenMP dialect CanonicalLoopInfo to its lowered LLVM-IR OpenMPIRBuilder CanonicalLoopInfo...
llvm::GlobalValue * lookupGlobal(Operation *op)
Finds an LLVM IR global value that corresponds to the given MLIR operation defining a global value.
SaveStateStack< T, ModuleTranslation > SaveStack
RAII object calling stackPush/stackPop on construction/destruction.
LogicalResult convertOperation(Operation &op, llvm::IRBuilderBase &builder)
Converts the given MLIR operation into LLVM IR using this translator.
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.
llvm::Module * getLLVMModule()
Returns the LLVM module in which the IR is being constructed.
void stackPop()
Pops the last element from the ModuleTranslation 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.
llvm::CanonicalLoopInfo * lookupOMPLoop(omp::NewCliOp mlir) const
Find the LLVM-IR loop that represents an MLIR loop.
llvm::LLVMContext & getLLVMContext() const
Returns the LLVM context in which the IR is being constructed.
Utility class to translate MLIR LLVM dialect types to LLVM IR.
unsigned getPreferredAlignment(Type type, const llvm::DataLayout &layout)
Returns the preferred alignment for the type given the data layout.
T findInstanceOf()
Return an instance of the given location type if one is nested under the current location.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
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.
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.
StringAttr getIdentifier() const
Return the name of this operation as a StringAttr.
Operation is the basic unit of execution within MLIR.
Region & getRegion(unsigned index)
Returns the region held by this operation at position 'index'.
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.
unsigned getNumRegions()
Returns the number of regions held by this operation.
Location getLoc()
The source location the operation was defined or derived from.
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
unsigned getNumOperands()
OperandRange operand_range
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
OperationName getName()
The name of an operation is the key identifier for it.
operand_range getOperands()
Returns an iterator on the underlying Value's.
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),...
user_range getUsers()
Returns a range of all users.
result_range getResults()
MLIRContext * getContext()
Return the context this operation is associated with.
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
unsigned getNumResults()
Return the number of results held by this operation.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
BlockArgListType getArguments()
unsigned getNumArguments()
Operation * getParentOp()
Return the parent operation this region is attached to.
BlockListType & getBlocks()
bool hasOneBlock()
Return true if this region has exactly one block.
Concrete CRTP base class for StateStack frames.
@ Private
The symbol is private and may only be referenced by SymbolRefAttrs local to the operations within the...
static Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
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:
static WalkResult advance()
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...
bool opInSharedDeviceContext(Operation &op)
Check whether the given operation is located in a context where an allocation to be used by multiple ...
bool allocaUsesRequireSharedMem(Value alloc)
Check whether the value representing an allocation, assumed to have been defined in a shared device c...
auto getDims(VectorType vType)
Returns a range over the dims (size and scalability) of a VectorType.
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.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
bool isPure(Operation *op)
Returns true if the given operation is pure, i.e., is speculatable that does not touch memory.
void registerOpenMPDialectTranslation(DialectRegistry ®istry)
Register the OpenMP dialect and the translation from it to the LLVM IR in the given registry;.
llvm::SetVector< T, Vector, Set, N > SetVector
SmallVector< Loops, 8 > tile(ArrayRef< scf::ForOp > forOps, ArrayRef< Value > sizes, ArrayRef< scf::ForOp > targets)
Performs tiling fo imperfectly nested loops (with interchange) by strip-mining the forOps by sizes an...
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
A util to collect info needed to convert delayed privatizers from MLIR to LLVM.
SmallVector< mlir::Value > mlirVars
SmallVector< omp::PrivateClauseOp > privatizers
MutableArrayRef< BlockArgument > blockArgs
SmallVector< llvm::Value * > llvmVars
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.