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;
157 void registerType(LLVM::ModuleTranslation &moduleTranslation,
158 mlir::Attribute &ty) {
159 linearVarTypes.push_back(moduleTranslation.
convertType(
160 mlir::cast<mlir::TypeAttr>(ty).getValue()));
164 void createLinearVar(llvm::IRBuilderBase &builder,
165 LLVM::ModuleTranslation &moduleTranslation,
166 llvm::Value *linearVar,
int idx) {
167 linearPreconditionVars.push_back(
168 builder.CreateAlloca(linearVarTypes[idx],
nullptr,
".linear_var"));
169 llvm::Value *linearLoopBodyTemp =
170 builder.CreateAlloca(linearVarTypes[idx],
nullptr,
".linear_result");
171 linearOrigVal.push_back(linearVar);
172 linearLoopBodyTemps.push_back(linearLoopBodyTemp);
176 inline void initLinearStep(LLVM::ModuleTranslation &moduleTranslation,
177 mlir::Value &linearStep) {
178 linearSteps.push_back(moduleTranslation.
lookupValue(linearStep));
182 void initLinearVar(llvm::IRBuilderBase &builder,
183 LLVM::ModuleTranslation &moduleTranslation,
184 llvm::BasicBlock *loopPreHeader) {
185 builder.SetInsertPoint(loopPreHeader->getTerminator());
186 for (
size_t index = 0; index < linearOrigVal.size(); index++) {
187 llvm::LoadInst *linearVarLoad =
188 builder.CreateLoad(linearVarTypes[index], linearOrigVal[index]);
189 builder.CreateStore(linearVarLoad, linearPreconditionVars[index]);
194 LogicalResult initLinearIV(omp::SimdOp simdOp) {
195 auto loopOp = cast<omp::LoopNestOp>(simdOp.getWrappedLoop());
197 if (loopOp.getIVs().size() != 1)
205 BlockArgument arg = loopOp.getIVs().front();
206 for (
const Operation *user : arg.
getUsers()) {
207 if (
auto storeOp = dyn_cast<LLVM::StoreOp>(user)) {
208 for (Value linearVar : simdOp.getLinearVars()) {
209 if (linearVar == storeOp.getAddr()) {
210 if (linearLoopIV && linearLoopIV != linearVar)
211 return simdOp.emitError(
212 "Could not determine the linear variable associated with the "
213 "loop nest induction variable");
214 linearLoopIV = linearVar;
223 void updateLinearVar(llvm::IRBuilderBase &builder, llvm::BasicBlock *loopBody,
224 llvm::Value *loopInductionVar) {
225 builder.SetInsertPoint(loopBody->getTerminator());
226 for (
size_t index = 0; index < linearPreconditionVars.size(); index++) {
227 llvm::Type *linearVarType = linearVarTypes[index];
228 llvm::Value *iv = loopInductionVar;
229 llvm::Value *step = linearSteps[index];
231 if (!iv->getType()->isIntegerTy())
232 llvm_unreachable(
"OpenMP loop induction variable must be an integer "
235 if (linearVarType->isIntegerTy()) {
237 iv = builder.CreateSExtOrTrunc(iv, linearVarType);
238 step = builder.CreateSExtOrTrunc(step, linearVarType);
240 llvm::LoadInst *linearVarStart =
241 builder.CreateLoad(linearVarType, linearPreconditionVars[index]);
242 llvm::Value *mulInst = builder.CreateMul(iv, step);
243 llvm::Value *addInst = builder.CreateAdd(linearVarStart, mulInst);
244 builder.CreateStore(addInst, linearLoopBodyTemps[index]);
245 }
else if (linearVarType->isFloatingPointTy()) {
247 step = builder.CreateSExtOrTrunc(step, iv->getType());
248 llvm::Value *mulInst = builder.CreateMul(iv, step);
250 llvm::LoadInst *linearVarStart =
251 builder.CreateLoad(linearVarType, linearPreconditionVars[index]);
252 llvm::Value *mulFp = builder.CreateSIToFP(mulInst, linearVarType);
253 llvm::Value *addInst = builder.CreateFAdd(linearVarStart, mulFp);
254 builder.CreateStore(addInst, linearLoopBodyTemps[index]);
257 "Linear variable must be of integer or floating-point type");
263 void updateLinearIV(llvm::IRBuilderBase &builder,
264 LLVM::ModuleTranslation &moduleTranslation) {
267 llvm::Value *linearIV = moduleTranslation.
lookupValue(linearLoopIV);
271 for (index = 0; index < linearOrigVal.size(); index++)
272 if (linearIV == linearOrigVal[index])
274 if (index == linearOrigVal.size())
278 llvm::Type *varType = linearVarTypes[index];
279 llvm::Value *var = linearLoopBodyTemps[index];
280 llvm::Value *step = linearSteps[index];
281 if (!varType->isIntegerTy())
282 llvm_unreachable(
"Linear iteration variable must be of integer type");
284 step = builder.CreateSExtOrTrunc(step, varType);
285 llvm::Value *val = builder.CreateLoad(varType, var);
286 llvm::Value *addInst = builder.CreateAdd(val, step);
287 builder.CreateStore(addInst, var);
292 void splitLinearFiniBB(llvm::IRBuilderBase &builder,
293 llvm::BasicBlock *loopExit) {
294 linearFinalizationBB = loopExit->splitBasicBlock(
295 loopExit->getTerminator(),
"omp_loop.linear_finalization");
296 linearExitBB = linearFinalizationBB->splitBasicBlock(
297 linearFinalizationBB->getTerminator(),
"omp_loop.linear_exit");
298 linearLastIterExitBB = linearFinalizationBB->splitBasicBlock(
299 linearFinalizationBB->getTerminator(),
"omp_loop.linear_lastiter_exit");
303 llvm::OpenMPIRBuilder::InsertPointOrErrorTy
304 finalizeLinearVar(llvm::IRBuilderBase &builder,
305 LLVM::ModuleTranslation &moduleTranslation,
306 llvm::Value *lastIter) {
308 builder.SetInsertPoint(linearFinalizationBB->getTerminator());
309 llvm::Value *loopLastIterLoad = builder.CreateLoad(
310 llvm::Type::getInt32Ty(builder.getContext()), lastIter);
311 llvm::Value *isLast =
312 builder.CreateCmp(llvm::CmpInst::ICMP_NE, loopLastIterLoad,
313 llvm::ConstantInt::get(
314 llvm::Type::getInt32Ty(builder.getContext()), 0));
316 builder.SetInsertPoint(linearLastIterExitBB->getTerminator());
317 for (
size_t index = 0; index < linearOrigVal.size(); index++) {
318 llvm::LoadInst *linearVarTemp =
319 builder.CreateLoad(linearVarTypes[index], linearLoopBodyTemps[index]);
320 builder.CreateStore(linearVarTemp, linearOrigVal[index]);
326 builder.SetInsertPoint(linearFinalizationBB->getTerminator());
327 builder.CreateCondBr(isLast, linearLastIterExitBB, linearExitBB);
328 linearFinalizationBB->getTerminator()->eraseFromParent();
330 builder.SetInsertPoint(linearExitBB->getTerminator());
332 builder, llvm::omp::OMPD_barrier);
337 void emitStoresForLinearVar(llvm::IRBuilderBase &builder) {
338 for (
size_t index = 0; index < linearOrigVal.size(); index++) {
339 llvm::LoadInst *linearVarTemp =
340 builder.CreateLoad(linearVarTypes[index], linearLoopBodyTemps[index]);
341 builder.CreateStore(linearVarTemp, linearOrigVal[index]);
347 void rewriteInPlace(llvm::IRBuilderBase &builder, llvm::BasicBlock *startBB,
348 llvm::BasicBlock *endBB,
size_t varIndex) {
349 llvm::SmallVector<llvm::BasicBlock *, 32> worklist;
350 llvm::SmallPtrSet<llvm::BasicBlock *, 32> collectedBBs;
352 assert(startBB && endBB &&
"Invalid startBB/endBB");
355 worklist.push_back(startBB);
356 collectedBBs.insert(startBB);
358 while (!worklist.empty()) {
359 llvm::BasicBlock *bb = worklist.pop_back_val();
364 for (llvm::BasicBlock *succ : llvm::successors(bb)) {
365 if (collectedBBs.insert(succ).second)
366 worklist.push_back(succ);
371 llvm::SmallVector<llvm::User *> users(linearOrigVal[varIndex]->users());
372 for (
auto *user : users) {
373 if (
auto *userInst = dyn_cast<llvm::Instruction>(user)) {
374 if (collectedBBs.contains(userInst->getParent()))
375 user->replaceUsesOfWith(linearOrigVal[varIndex],
376 linearLoopBodyTemps[varIndex]);
387 SymbolRefAttr symbolName) {
388 omp::PrivateClauseOp privatizer =
391 assert(privatizer &&
"privatizer not found in the symbol table");
402 auto todo = [&op](StringRef clauseName) {
403 return op.
emitError() <<
"not yet implemented: Unhandled clause "
404 << clauseName <<
" in " << op.
getName()
408 auto checkAllocate = [&todo](
auto op, LogicalResult &
result) {
409 if (!op.getAllocateVars().empty() || !op.getAllocatorVars().empty())
410 result = todo(
"allocate");
412 auto checkBare = [&todo](
auto op, LogicalResult &
result) {
413 if (op.getKernelType() == omp::TargetExecMode::bare)
414 result = todo(
"ompx_bare");
416 auto checkDepend = [&todo](
auto op, LogicalResult &
result) {
417 if (!op.getDependVars().empty() || op.getDependKinds())
420 auto checkHint = [](
auto op, LogicalResult &) {
424 auto checkInReduction = [&todo](
auto op, LogicalResult &
result) {
425 if (isa<omp::TargetOp, omp::TaskOp, omp::TaskloopContextOp>(
426 op.getOperation())) {
427 if (
auto byrefAttr = op.getInReductionByref()) {
428 for (
bool isByRef : *byrefAttr) {
430 result = todo(
"in_reduction with byref modifier");
435 if (isa<omp::TargetOp>(op.getOperation())) {
436 if (
auto inReductionSyms = op.getInReductionSyms()) {
438 (*inReductionSyms).template getAsRange<SymbolRefAttr>()) {
443 "symbol resolution should be guaranteed by the op verifier");
444 if (decl.getInitializerRegion().front().getNumArguments() != 1) {
445 result = todo(
"in_reduction with two-argument initializer");
448 if (!decl.getCleanupRegion().empty()) {
449 result = todo(
"in_reduction with cleanup region");
455 }
else if (!op.getInReductionVars().empty() || op.getInReductionByref() ||
456 op.getInReductionSyms()) {
457 result = todo(
"in_reduction");
460 auto checkNowait = [&todo](
auto op, LogicalResult &
result) {
464 auto checkOrder = [&todo](
auto op, LogicalResult &
result) {
465 if (op.getOrder() || op.getOrderMod())
468 auto checkPrivate = [&todo](
auto op, LogicalResult &
result) {
469 if (!op.getPrivateVars().empty() || op.getPrivateSyms())
470 result = todo(
"privatization");
472 auto checkReduction = [&todo](
auto op, LogicalResult &
result) {
473 if (isa<omp::TeamsOp>(op))
474 if (!op.getReductionVars().empty() || op.getReductionByref() ||
475 op.getReductionSyms())
476 result = todo(
"reduction");
477 if (op.getReductionMod() &&
478 op.getReductionMod().value() != omp::ReductionModifier::defaultmod) {
479 omp::ReductionModifier mod = op.getReductionMod().value();
483 bool taskModifierSupported =
484 mod == omp::ReductionModifier::task &&
485 isa<omp::ParallelOp, omp::WsloopOp, omp::SectionsOp>(op);
486 if (!taskModifierSupported) {
487 result = todo(
"reduction with modifier");
488 }
else if (
auto byref = op.getReductionByref()) {
491 for (
bool isByRef : *byref)
493 result = todo(
"task reduction modifier with by-ref reduction");
499 auto checkTaskReductionByref = [&todo](
auto op, LogicalResult &
result) {
500 if (
auto byrefAttr = op.getTaskReductionByref())
501 for (
bool isByRef : *byrefAttr)
503 result = todo(
"task_reduction with byref modifier");
507 auto checkReductionByref = [&todo](
auto op, LogicalResult &
result) {
508 if (
auto byrefAttr = op.getReductionByref())
509 for (
bool isByRef : *byrefAttr)
511 result = todo(
"reduction with byref modifier");
515 auto checkNumTeams = [&todo](
auto op, LogicalResult &
result) {
516 if (op.hasNumTeamsMultiDim())
517 result = todo(
"num_teams with multi-dimensional values");
519 auto checkNumThreads = [&todo](
auto op, LogicalResult &
result) {
520 if (op.hasNumThreadsMultiDim())
521 result = todo(
"num_threads with multi-dimensional values");
524 auto checkThreadLimit = [&todo](
auto op, LogicalResult &
result) {
525 if (op.hasThreadLimitMultiDim())
526 result = todo(
"thread_limit with multi-dimensional values");
528 auto checkMap = [&todo](
auto op, LogicalResult &
result) {
529 if (!op.getMapIterated().empty())
530 result = todo(
"map/motion clause with iterator modifier");
533 auto checkDynGroupprivate = [&todo](
auto op, LogicalResult &
result) {
534 if (op.getDynGroupprivateSize())
535 result = todo(
"dyn_groupprivate");
540 .Case([&](omp::DistributeOp op) {
541 checkAllocate(op,
result);
544 .Case([&](omp::SectionsOp op) {
545 checkAllocate(op,
result);
547 checkReduction(op,
result);
549 .Case([&](omp::ScopeOp op) {
550 checkAllocate(op,
result);
551 checkReduction(op,
result);
553 .Case([&](omp::SingleOp op) {
554 checkAllocate(op,
result);
557 .Case([&](omp::TeamsOp op) {
558 checkAllocate(op,
result);
560 checkNumTeams(op,
result);
561 checkThreadLimit(op,
result);
562 checkDynGroupprivate(op,
result);
564 .Case([&](omp::TaskOp op) {
565 checkAllocate(op,
result);
566 checkInReduction(op,
result);
568 .Case([&](omp::TaskgroupOp op) {
569 checkAllocate(op,
result);
570 checkTaskReductionByref(op,
result);
572 .Case([&](omp::TaskwaitOp op) { checkNowait(op,
result); })
573 .Case([&](omp::TaskloopContextOp op) {
574 checkAllocate(op,
result);
575 checkInReduction(op,
result);
576 checkReduction(op,
result);
577 checkReductionByref(op,
result);
579 .Case([&](omp::WsloopOp op) {
580 checkAllocate(op,
result);
582 checkReduction(op,
result);
584 .Case([&](omp::ParallelOp op) {
585 checkAllocate(op,
result);
586 checkReduction(op,
result);
587 checkNumThreads(op,
result);
589 .Case([&](omp::SimdOp op) { checkReduction(op,
result); })
590 .Case<omp::AtomicReadOp, omp::AtomicWriteOp, omp::AtomicUpdateOp,
591 omp::AtomicCaptureOp>([&](
auto op) { checkHint(op,
result); })
592 .Case([&](omp::AtomicCompareOp op) {
598 auto structTy = dyn_cast<LLVM::LLVMStructType>(argType);
604 result = todo(
"compare for complex types wider than 128 bits");
606 .Case<omp::TargetEnterDataOp, omp::TargetExitDataOp>([&](
auto op) {
610 .Case([&](omp::TargetUpdateOp op) {
614 .Case([&](omp::TargetOp op) {
615 checkAllocate(op,
result);
617 checkInReduction(op,
result);
619 checkThreadLimit(op,
result);
621 .Case([&](omp::TargetDataOp op) { checkMap(op,
result); })
622 .Case([&](omp::DeclareMapperInfoOp op) { checkMap(op,
result); })
633 llvm::handleAllErrors(
635 [&](
const PreviouslyReportedError &) {
result = failure(); },
636 [&](
const llvm::ErrorInfoBase &err) {
659 llvm::OpenMPIRBuilder::InsertPointTy allocInsertPoint;
662 [&](OpenMPAllocStackFrame &frame) {
663 allocInsertPoint = frame.allocInsertPoint;
664 deallocInsertPoints = frame.deallocBlocks;
672 allocInsertPoint.getBlock()->getParent() ==
673 builder.GetInsertBlock()->getParent()) {
675 deallocBlocks->insert(deallocBlocks->end(), deallocInsertPoints.begin(),
676 deallocInsertPoints.end());
677 return allocInsertPoint;
687 if (builder.GetInsertBlock() ==
688 &builder.GetInsertBlock()->getParent()->getEntryBlock()) {
689 assert(builder.GetInsertPoint() == builder.GetInsertBlock()->end() &&
690 "Assuming end of basic block");
691 llvm::BasicBlock *entryBB = llvm::BasicBlock::Create(
692 builder.getContext(),
"entry", builder.GetInsertBlock()->getParent(),
693 builder.GetInsertBlock()->getNextNode());
694 builder.CreateBr(entryBB);
695 builder.SetInsertPoint(entryBB);
701 for (llvm::BasicBlock &block : *builder.GetInsertBlock()->getParent()) {
705 llvm::Instruction *terminator = block.getTerminatorOrNull();
706 if (isa_and_present<llvm::ReturnInst>(terminator))
707 deallocBlocks->emplace_back(&block);
711 llvm::BasicBlock &funcEntryBlock =
712 builder.GetInsertBlock()->getParent()->getEntryBlock();
713 return llvm::OpenMPIRBuilder::InsertPointTy(
714 &funcEntryBlock, funcEntryBlock.getFirstInsertionPt());
720static llvm::CanonicalLoopInfo *
722 llvm::CanonicalLoopInfo *loopInfo =
nullptr;
723 moduleTranslation.
stackWalk<OpenMPLoopInfoStackFrame>(
724 [&](OpenMPLoopInfoStackFrame &frame) {
725 loopInfo = frame.loopInfo;
737 Region ®ion, StringRef blockName, llvm::IRBuilderBase &builder,
740 bool isLoopWrapper = isa<omp::LoopWrapperInterface>(region.
getParentOp());
742 llvm::BasicBlock *continuationBlock =
743 splitBB(builder,
true,
"omp.region.cont");
744 llvm::BasicBlock *sourceBlock = builder.GetInsertBlock();
746 llvm::LLVMContext &llvmContext = builder.getContext();
747 for (
Block &bb : region) {
748 llvm::BasicBlock *llvmBB = llvm::BasicBlock::Create(
749 llvmContext, blockName, builder.GetInsertBlock()->getParent(),
750 builder.GetInsertBlock()->getNextNode());
751 moduleTranslation.
mapBlock(&bb, llvmBB);
754 llvm::Instruction *sourceTerminator = sourceBlock->getTerminator();
761 unsigned numYields = 0;
763 if (!isLoopWrapper) {
764 bool operandsProcessed =
false;
766 if (omp::YieldOp yield = dyn_cast<omp::YieldOp>(bb.getTerminator())) {
767 if (!operandsProcessed) {
768 for (
unsigned i = 0, e = yield->getNumOperands(); i < e; ++i) {
769 continuationBlockPHITypes.push_back(
770 moduleTranslation.
convertType(yield->getOperand(i).getType()));
772 operandsProcessed =
true;
774 assert(continuationBlockPHITypes.size() == yield->getNumOperands() &&
775 "mismatching number of values yielded from the region");
776 for (
unsigned i = 0, e = yield->getNumOperands(); i < e; ++i) {
777 llvm::Type *operandType =
778 moduleTranslation.
convertType(yield->getOperand(i).getType());
780 assert(continuationBlockPHITypes[i] == operandType &&
781 "values of mismatching types yielded from the region");
791 if (!continuationBlockPHITypes.empty())
793 continuationBlockPHIs &&
794 "expected continuation block PHIs if converted regions yield values");
795 if (continuationBlockPHIs) {
796 llvm::IRBuilderBase::InsertPointGuard guard(builder);
797 continuationBlockPHIs->reserve(continuationBlockPHITypes.size());
798 builder.SetInsertPoint(continuationBlock, continuationBlock->begin());
799 for (llvm::Type *ty : continuationBlockPHITypes)
800 continuationBlockPHIs->push_back(builder.CreatePHI(ty, numYields));
806 for (
Block *bb : blocks) {
807 llvm::BasicBlock *llvmBB = moduleTranslation.
lookupBlock(bb);
810 if (bb->isEntryBlock()) {
811 assert(sourceTerminator->getNumSuccessors() == 1 &&
812 "provided entry block has multiple successors");
813 assert(sourceTerminator->getSuccessor(0) == continuationBlock &&
814 "ContinuationBlock is not the successor of the entry block");
815 sourceTerminator->setSuccessor(0, llvmBB);
818 llvm::IRBuilderBase::InsertPointGuard guard(builder);
820 moduleTranslation.
convertBlock(*bb, bb->isEntryBlock(), builder)))
821 return llvm::make_error<PreviouslyReportedError>();
826 builder.CreateBr(continuationBlock);
837 Operation *terminator = bb->getTerminator();
838 if (isa<omp::TerminatorOp, omp::YieldOp>(terminator)) {
839 builder.CreateBr(continuationBlock);
841 for (
unsigned i = 0, e = terminator->
getNumOperands(); i < e; ++i)
842 (*continuationBlockPHIs)[i]->addIncoming(
856 return continuationBlock;
862 case omp::ClauseProcBindKind::Close:
863 return llvm::omp::ProcBindKind::OMP_PROC_BIND_close;
864 case omp::ClauseProcBindKind::Master:
865 return llvm::omp::ProcBindKind::OMP_PROC_BIND_master;
866 case omp::ClauseProcBindKind::Primary:
867 return llvm::omp::ProcBindKind::OMP_PROC_BIND_primary;
868 case omp::ClauseProcBindKind::Spread:
869 return llvm::omp::ProcBindKind::OMP_PROC_BIND_spread;
871 llvm_unreachable(
"Unknown ClauseProcBindKind kind");
878 auto maskedOp = cast<omp::MaskedOp>(opInst);
879 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
884 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
887 auto ®ion = maskedOp.getRegion();
888 builder.restoreIP(codeGenIP);
896 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
898 llvm::Value *filterVal =
nullptr;
899 if (
auto filterVar = maskedOp.getFilteredThreadId()) {
900 filterVal = moduleTranslation.
lookupValue(filterVar);
902 llvm::LLVMContext &llvmContext = builder.getContext();
904 llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvmContext), 0);
906 assert(filterVal !=
nullptr);
907 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
908 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
915 builder.restoreIP(*afterIP);
923 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
924 auto masterOp = cast<omp::MasterOp>(opInst);
929 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
932 auto ®ion = masterOp.getRegion();
933 builder.restoreIP(codeGenIP);
941 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
943 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
944 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
951 builder.restoreIP(*afterIP);
959 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
960 auto criticalOp = cast<omp::CriticalOp>(opInst);
965 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
968 auto ®ion = cast<omp::CriticalOp>(opInst).getRegion();
969 builder.restoreIP(codeGenIP);
977 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
979 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
980 llvm::LLVMContext &llvmContext = moduleTranslation.
getLLVMContext();
981 llvm::Constant *hint =
nullptr;
984 if (criticalOp.getNameAttr()) {
987 auto symbolRef = cast<SymbolRefAttr>(criticalOp.getNameAttr());
988 auto criticalDeclareOp =
992 llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvmContext),
993 static_cast<int>(criticalDeclareOp.getHint()));
995 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
997 ompLoc, bodyGenCB, finiCB, criticalOp.getName().value_or(
""), hint);
1002 builder.restoreIP(*afterIP);
1009 template <
typename OP>
1012 cast<
omp::BlockArgOpenMPOpInterface>(*op).getPrivateBlockArgs()) {
1015 collectPrivatizationDecls<OP>(op);
1030 void collectPrivatizationDecls(OP op) {
1031 std::optional<ArrayAttr> attr = op.getPrivateSyms();
1036 for (
auto symbolRef : attr->getAsRange<SymbolRefAttr>()) {
1043template <
typename T>
1047 std::optional<ArrayAttr> attr = op.getReductionSyms();
1051 reductions.reserve(reductions.size() + op.getNumReductionVars());
1052 for (
auto symbolRef : attr->getAsRange<SymbolRefAttr>()) {
1053 reductions.push_back(
1068 Operation *contextOp, std::optional<ArrayAttr> syms, StringRef opName,
1072 out.reserve(out.size() + syms->size());
1073 for (
auto sym : syms->getAsRange<SymbolRefAttr>()) {
1078 <<
"failed to resolve " << clauseName
1079 <<
" declare_reduction symbol " << sym.getRootReference() <<
" in "
1081 if (decl.getInitializerRegion().front().getNumArguments() != 1)
1083 <<
"not yet implemented: " << clauseName
1084 <<
" with two-argument initializer in " << opName;
1085 if (!decl.getCleanupRegion().empty())
1086 return contextOp->
emitError() <<
"not yet implemented: " << clauseName
1087 <<
" with cleanup region in " << opName;
1088 if (decl.getReductionRegion().empty())
1090 << clauseName <<
" declare_reduction is missing a combiner region";
1091 out.push_back(decl);
1102 Region ®ion, StringRef blockName, llvm::IRBuilderBase &builder,
1111 llvm::Instruction *potentialTerminator =
1112 builder.GetInsertBlock()->empty() ?
nullptr
1113 : &builder.GetInsertBlock()->back();
1115 if (potentialTerminator && potentialTerminator->isTerminator())
1116 potentialTerminator->removeFromParent();
1117 moduleTranslation.
mapBlock(®ion.
front(), builder.GetInsertBlock());
1120 region.
front(),
true, builder)))
1124 if (continuationBlockArgs)
1126 *continuationBlockArgs,
1133 if (potentialTerminator && potentialTerminator->isTerminator()) {
1134 llvm::BasicBlock *block = builder.GetInsertBlock();
1135 if (block->empty()) {
1141 potentialTerminator->insertInto(block, block->begin());
1143 potentialTerminator->insertAfter(&block->back());
1157 if (continuationBlockArgs)
1158 llvm::append_range(*continuationBlockArgs, phis);
1159 builder.SetInsertPoint(*continuationBlock,
1160 (*continuationBlock)->getFirstInsertionPt());
1167using OwningReductionGen =
1168 std::function<llvm::OpenMPIRBuilder::InsertPointOrErrorTy(
1169 llvm::OpenMPIRBuilder::InsertPointTy, llvm::Value *, llvm::Value *,
1171using OwningAtomicReductionGen =
1172 std::function<llvm::OpenMPIRBuilder::InsertPointOrErrorTy(
1173 llvm::OpenMPIRBuilder::InsertPointTy, llvm::Type *, llvm::Value *,
1175using OwningDataPtrPtrReductionGen =
1176 std::function<llvm::OpenMPIRBuilder::InsertPointOrErrorTy(
1177 llvm::OpenMPIRBuilder::InsertPointTy, llvm::Value *, llvm::Value *&)>;
1183static OwningReductionGen
1189 OwningReductionGen gen =
1190 [&, decl](llvm::OpenMPIRBuilder::InsertPointTy insertPoint,
1191 llvm::Value *
lhs, llvm::Value *
rhs,
1192 llvm::Value *&
result)
mutable
1193 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
1194 moduleTranslation.
mapValue(decl.getReductionLhsArg(),
lhs);
1195 moduleTranslation.
mapValue(decl.getReductionRhsArg(),
rhs);
1196 builder.restoreIP(insertPoint);
1199 "omp.reduction.nonatomic.body", builder,
1200 moduleTranslation, &phis)))
1201 return llvm::createStringError(
1202 "failed to inline `combiner` region of `omp.declare_reduction`");
1203 result = llvm::getSingleElement(phis);
1204 return builder.saveIP();
1213static OwningAtomicReductionGen
1215 llvm::IRBuilderBase &builder,
1217 if (decl.getAtomicReductionRegion().empty())
1218 return OwningAtomicReductionGen();
1224 [&, decl](llvm::OpenMPIRBuilder::InsertPointTy insertPoint, llvm::Type *,
1225 llvm::Value *
lhs, llvm::Value *
rhs)
mutable
1226 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
1227 moduleTranslation.
mapValue(decl.getAtomicReductionLhsArg(),
lhs);
1228 moduleTranslation.
mapValue(decl.getAtomicReductionRhsArg(),
rhs);
1229 builder.restoreIP(insertPoint);
1232 "omp.reduction.atomic.body", builder,
1233 moduleTranslation, &phis)))
1234 return llvm::createStringError(
1235 "failed to inline `atomic` region of `omp.declare_reduction`");
1236 assert(phis.empty());
1237 return builder.saveIP();
1246static OwningDataPtrPtrReductionGen
1249 if (!isByRef || decl.getDataPtrPtrRegion().empty())
1250 return OwningDataPtrPtrReductionGen();
1252 OwningDataPtrPtrReductionGen refDataPtrGen =
1253 [&, decl](llvm::OpenMPIRBuilder::InsertPointTy insertPoint,
1254 llvm::Value *byRefVal, llvm::Value *&
result)
mutable
1255 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
1256 moduleTranslation.
mapValue(decl.getDataPtrPtrRegionArg(), byRefVal);
1257 builder.restoreIP(insertPoint);
1260 "omp.data_ptr_ptr.body", builder,
1261 moduleTranslation, &phis)))
1262 return llvm::createStringError(
1263 "failed to inline `data_ptr_ptr` region of `omp.declare_reduction`");
1264 result = llvm::getSingleElement(phis);
1265 return builder.saveIP();
1268 return refDataPtrGen;
1275 auto orderedOp = cast<omp::OrderedOp>(opInst);
1280 omp::ClauseDepend dependType = *orderedOp.getDoacrossDependType();
1281 bool isDependSource = dependType == omp::ClauseDepend::dependsource;
1282 unsigned numLoops = *orderedOp.getDoacrossNumLoops();
1284 moduleTranslation.
lookupValues(orderedOp.getDoacrossDependVars());
1286 size_t indexVecValues = 0;
1287 while (indexVecValues < vecValues.size()) {
1289 storeValues.reserve(numLoops);
1290 for (
unsigned i = 0; i < numLoops; i++) {
1291 storeValues.push_back(vecValues[indexVecValues]);
1294 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
1296 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
1297 builder.restoreIP(moduleTranslation.
getOpenMPBuilder()->createOrderedDepend(
1298 ompLoc, allocaIP, numLoops, storeValues,
".cnt.addr", isDependSource));
1308 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1309 auto orderedRegionOp = cast<omp::OrderedRegionOp>(opInst);
1314 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
1317 auto ®ion = cast<omp::OrderedRegionOp>(opInst).getRegion();
1318 builder.restoreIP(codeGenIP);
1326 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
1328 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
1329 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
1331 ompLoc, bodyGenCB, finiCB, !orderedRegionOp.getParLevelSimd());
1336 builder.restoreIP(*afterIP);
1342struct DeferredStore {
1343 DeferredStore(llvm::Value *value, llvm::Value *address)
1344 : value(value), address(address) {}
1347 llvm::Value *address;
1354template <
typename T>
1357 llvm::IRBuilderBase &builder,
1359 const llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
1365 llvm::IRBuilderBase::InsertPointGuard guard(builder);
1366 builder.SetInsertPoint(allocaIP.getBlock()->getTerminator());
1372 deferredStores.reserve(op.getNumReductionVars());
1374 for (std::size_t i = 0; i < op.getNumReductionVars(); ++i) {
1375 Region &allocRegion = reductionDecls[i].getAllocRegion();
1377 if (allocRegion.
empty())
1382 builder, moduleTranslation, &phis)))
1383 return op.emitError(
1384 "failed to inline `alloc` region of `omp.declare_reduction`");
1386 assert(phis.size() == 1 &&
"expected one allocation to be yielded");
1387 builder.SetInsertPoint(allocaIP.getBlock()->getTerminator());
1391 llvm::Type *ptrTy = builder.getPtrTy();
1395 if (useDeviceSharedMem) {
1396 var = ompBuilder->createOMPAllocShared(builder, varTy);
1398 var = builder.CreateAlloca(varTy);
1399 var = builder.CreatePointerBitCastOrAddrSpaceCast(var, ptrTy);
1402 llvm::Value *castPhi =
1403 builder.CreatePointerBitCastOrAddrSpaceCast(phis[0], ptrTy);
1405 deferredStores.emplace_back(castPhi, var);
1407 privateReductionVariables[i] = var;
1408 moduleTranslation.
mapValue(reductionArgs[i], castPhi);
1409 reductionVariableMap.try_emplace(op.getReductionVars()[i], castPhi);
1411 assert(allocRegion.
empty() &&
1412 "allocaction is implicit for by-val reduction");
1414 llvm::Type *ptrTy = builder.getPtrTy();
1418 if (useDeviceSharedMem) {
1419 var = ompBuilder->createOMPAllocShared(builder, varTy);
1421 var = builder.CreateAlloca(varTy);
1422 var = builder.CreatePointerBitCastOrAddrSpaceCast(var, ptrTy);
1425 moduleTranslation.
mapValue(reductionArgs[i], var);
1426 privateReductionVariables[i] = var;
1427 reductionVariableMap.try_emplace(op.getReductionVars()[i], var);
1435template <
typename T>
1438 llvm::IRBuilderBase &builder,
1443 mlir::omp::DeclareReductionOp &reduction = reductionDecls[i];
1444 Region &initializerRegion = reduction.getInitializerRegion();
1447 mlir::Value mlirSource = loop.getReductionVars()[i];
1448 llvm::Value *llvmSource = moduleTranslation.
lookupValue(mlirSource);
1449 llvm::Value *origVal = llvmSource;
1451 if (!isa<LLVM::LLVMPointerType>(
1452 reduction.getInitializerMoldArg().getType()) &&
1453 isa<LLVM::LLVMPointerType>(mlirSource.
getType())) {
1456 reduction.getInitializerMoldArg().getType()),
1457 llvmSource,
"omp_orig");
1459 moduleTranslation.
mapValue(reduction.getInitializerMoldArg(), origVal);
1462 llvm::Value *allocation =
1463 reductionVariableMap.lookup(loop.getReductionVars()[i]);
1464 moduleTranslation.
mapValue(reduction.getInitializerAllocArg(), allocation);
1470 llvm::BasicBlock *block =
nullptr) {
1471 if (block ==
nullptr)
1472 block = builder.GetInsertBlock();
1474 if (!block->hasTerminator())
1475 builder.SetInsertPoint(block);
1477 builder.SetInsertPoint(block->getTerminator());
1485template <
typename OP>
1488 llvm::IRBuilderBase &builder,
1490 llvm::BasicBlock *latestAllocaBlock,
1496 if (op.getNumReductionVars() == 0)
1502 llvm::BasicBlock *initBlock = splitBB(builder,
true,
"omp.reduction.init");
1503 auto allocaIP = llvm::IRBuilderBase::InsertPoint(
1504 latestAllocaBlock, latestAllocaBlock->getTerminator()->getIterator());
1505 builder.restoreIP(allocaIP);
1508 for (
unsigned i = 0; i < op.getNumReductionVars(); ++i) {
1510 if (!reductionDecls[i].getAllocRegion().empty())
1518 if (useDeviceSharedMem)
1519 byRefVars[i] = ompBuilder->createOMPAllocShared(builder, varTy);
1521 byRefVars[i] = builder.CreateAlloca(varTy);
1529 for (
auto [data, addr] : deferredStores)
1530 builder.CreateStore(data, addr);
1535 for (
unsigned i = 0; i < op.getNumReductionVars(); ++i) {
1540 reductionVariableMap, i);
1548 "omp.reduction.neutral", builder,
1549 moduleTranslation, &phis)))
1552 assert(phis.size() == 1 &&
"expected one value to be yielded from the "
1553 "reduction neutral element declaration region");
1558 if (!reductionDecls[i].getAllocRegion().empty())
1567 builder.CreateStore(phis[0], byRefVars[i]);
1569 privateReductionVariables[i] = byRefVars[i];
1570 moduleTranslation.
mapValue(reductionArgs[i], phis[0]);
1571 reductionVariableMap.try_emplace(op.getReductionVars()[i], phis[0]);
1574 builder.CreateStore(phis[0], privateReductionVariables[i]);
1581 moduleTranslation.
forgetMapping(reductionDecls[i].getInitializerRegion());
1588template <
typename T>
1589static void collectReductionInfo(
1590 T loop, llvm::IRBuilderBase &builder,
1599 unsigned numReductions = loop.getNumReductionVars();
1601 for (
unsigned i = 0; i < numReductions; ++i) {
1604 owningAtomicReductionGens.push_back(
1607 reductionDecls[i], builder, moduleTranslation, isByRef[i]));
1611 reductionInfos.reserve(numReductions);
1612 for (
unsigned i = 0; i < numReductions; ++i) {
1613 llvm::OpenMPIRBuilder::ReductionGenAtomicCBTy
atomicGen =
nullptr;
1614 if (owningAtomicReductionGens[i])
1615 atomicGen = owningAtomicReductionGens[i];
1616 llvm::Value *variable =
1617 moduleTranslation.
lookupValue(loop.getReductionVars()[i]);
1620 if (
auto alloca = mlir::dyn_cast<LLVM::AllocaOp>(op)) {
1621 allocatedType = alloca.getElemType();
1628 reductionInfos.push_back(
1630 privateReductionVariables[i],
1631 llvm::OpenMPIRBuilder::EvalKind::Scalar,
1635 allocatedType ? moduleTranslation.
convertType(allocatedType) :
nullptr,
1636 reductionDecls[i].getByrefElementType()
1638 *reductionDecls[i].getByrefElementType())
1648 llvm::IRBuilderBase &builder, StringRef regionName,
1649 bool shouldLoadCleanupRegionArg =
true) {
1650 for (
auto [i, cleanupRegion] : llvm::enumerate(cleanupRegions)) {
1651 if (cleanupRegion->empty())
1657 llvm::Instruction *potentialTerminator =
1658 builder.GetInsertBlock()->empty() ?
nullptr
1659 : &builder.GetInsertBlock()->back();
1660 if (potentialTerminator && potentialTerminator->isTerminator())
1661 builder.SetInsertPoint(potentialTerminator);
1662 llvm::Value *privateVarValue =
1663 shouldLoadCleanupRegionArg
1664 ? builder.CreateLoad(
1666 privateVariables[i])
1667 : privateVariables[i];
1672 moduleTranslation)))
1685 OP op, llvm::IRBuilderBase &builder,
1687 llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
1690 bool isNowait =
false,
bool isTeamsReduction =
false) {
1692 if (op.getNumReductionVars() == 0)
1704 collectReductionInfo(op, builder, moduleTranslation, reductionDecls,
1706 owningReductionGenRefDataPtrGens,
1707 privateReductionVariables, reductionInfos, isByRef);
1712 llvm::UnreachableInst *tempTerminator = builder.CreateUnreachable();
1713 builder.SetInsertPoint(tempTerminator);
1714 llvm::OpenMPIRBuilder::InsertPointOrErrorTy contInsertPoint =
1715 ompBuilder->createReductions(builder, allocaIP, reductionInfos, isByRef,
1716 isNowait, isTeamsReduction);
1721 if (!contInsertPoint->getBlock())
1722 return op->emitOpError() <<
"failed to convert reductions";
1724 llvm::OpenMPIRBuilder::InsertPointTy afterIP = *contInsertPoint;
1725 if (!isTeamsReduction) {
1726 llvm::OpenMPIRBuilder::InsertPointOrErrorTy barrierIP =
1727 ompBuilder->createBarrier(*contInsertPoint, llvm::omp::OMPD_for);
1731 afterIP = *barrierIP;
1734 tempTerminator->eraseFromParent();
1735 builder.restoreIP(afterIP);
1739 llvm::transform(reductionDecls, std::back_inserter(reductionRegions),
1740 [](omp::DeclareReductionOp reductionDecl) {
1741 return &reductionDecl.getCleanupRegion();
1744 reductionRegions, privateReductionVariables, moduleTranslation, builder,
1745 "omp.reduction.cleanup");
1748 if (useDeviceSharedMem) {
1749 for (
auto [var, reductionDecl] :
1750 llvm::zip_equal(privateReductionVariables, reductionDecls))
1751 ompBuilder->createOMPFreeShared(
1752 builder, var, moduleTranslation.
convertType(reductionDecl.getType()));
1765template <
typename OP>
1769 llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
1774 if (op.getNumReductionVars() == 0)
1780 allocaIP, reductionDecls,
1781 privateReductionVariables, reductionVariableMap,
1782 deferredStores, isByRef)))
1785 return initReductionVars(op, reductionArgs, builder, moduleTranslation,
1786 allocaIP.getBlock(), reductionDecls,
1787 privateReductionVariables, reductionVariableMap,
1788 isByRef, deferredStores);
1802 if (mappedPrivateVars ==
nullptr || !mappedPrivateVars->contains(privateVar))
1805 Value blockArg = (*mappedPrivateVars)[privateVar];
1808 assert(isa<LLVM::LLVMPointerType>(blockArgType) &&
1809 "A block argument corresponding to a mapped var should have "
1812 if (privVarType == blockArgType)
1819 if (!isa<LLVM::LLVMPointerType>(privVarType))
1820 return builder.CreateLoad(moduleTranslation.
convertType(privVarType),
1837 llvm::Type *regionArgType =
1839 if (regionArgType->isPointerTy() || !value->getType()->isPointerTy())
1842 return builder.CreateLoad(regionArgType, value);
1852 omp::PrivateClauseOp &privDecl, llvm::Value *nonPrivateVar,
1854 llvm::BasicBlock *privInitBlock,
1856 Region &initRegion = privDecl.getInitRegion();
1857 if (initRegion.
empty())
1858 return llvmPrivateVar;
1860 assert(nonPrivateVar);
1861 moduleTranslation.
mapValue(privDecl.getInitMoldArg(), nonPrivateVar);
1862 moduleTranslation.
mapValue(privDecl.getInitPrivateArg(), llvmPrivateVar);
1867 moduleTranslation, &phis)))
1868 return llvm::createStringError(
1869 "failed to inline `init` region of `omp.private`");
1871 assert(phis.size() == 1 &&
"expected one allocation to be yielded");
1888 llvm::Value *llvmPrivateVar, llvm::BasicBlock *privInitBlock,
1891 builder, moduleTranslation, privDecl,
1894 blockArg, llvmPrivateVar, privInitBlock, mappedPrivateVars);
1903 return llvm::Error::success();
1905 llvm::BasicBlock *privInitBlock = splitBB(builder,
true,
"omp.private.init");
1908 for (
auto [idx, zip] : llvm::enumerate(llvm::zip_equal(
1911 auto [privDecl, mlirPrivVar, blockArg, llvmPrivateVar] = zip;
1913 builder, moduleTranslation, privDecl, mlirPrivVar, blockArg,
1914 llvmPrivateVar, privInitBlock, mappedPrivateVars);
1917 return privVarOrErr.takeError();
1919 llvmPrivateVar = privVarOrErr.get();
1920 moduleTranslation.
mapValue(blockArg, llvmPrivateVar);
1925 return llvm::Error::success();
1931template <
typename T>
1936 const llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
1939 llvm::Instruction *allocaTerminator = allocaIP.getBlock()->getTerminator();
1940 splitBB(llvm::OpenMPIRBuilder::InsertPointTy(allocaIP.getBlock(),
1941 allocaTerminator->getIterator()),
1942 true, allocaTerminator->getStableDebugLoc(),
1943 "omp.region.after_alloca");
1945 llvm::IRBuilderBase::InsertPointGuard guard(builder);
1947 allocaTerminator = allocaIP.getBlock()->getTerminator();
1948 builder.SetInsertPoint(allocaTerminator);
1950 assert(allocaTerminator->getNumSuccessors() == 1 &&
1951 "This is an unconditional branch created by splitBB");
1953 llvm::DataLayout dataLayout = builder.GetInsertBlock()->getDataLayout();
1954 llvm::BasicBlock *afterAllocas = allocaTerminator->getSuccessor(0);
1958 unsigned int allocaAS =
1959 moduleTranslation.
getLLVMModule()->getDataLayout().getAllocaAddrSpace();
1962 .getProgramAddressSpace();
1964 for (
auto [privDecl, mlirPrivVar, blockArg] :
1967 llvm::Type *llvmAllocType =
1968 moduleTranslation.
convertType(privDecl.getType());
1969 builder.SetInsertPoint(allocaIP.getBlock()->getTerminator());
1970 llvm::Value *llvmPrivateVar =
nullptr;
1972 llvmPrivateVar = ompBuilder->createOMPAllocShared(builder, llvmAllocType);
1974 llvmPrivateVar = builder.CreateAlloca(
1975 llvmAllocType,
nullptr,
"omp.private.alloc");
1976 if (allocaAS != defaultAS)
1977 llvmPrivateVar = builder.CreateAddrSpaceCast(
1978 llvmPrivateVar, builder.getPtrTy(defaultAS));
1981 privateVarsInfo.
llvmVars.push_back(llvmPrivateVar);
1984 return afterAllocas;
1992 if (mlir::isa<omp::SingleOp, omp::CriticalOp>(parent))
2001 if (mlir::isa<omp::ParallelOp>(parent))
2015 bool needsFirstprivate =
2016 llvm::any_of(privateDecls, [](omp::PrivateClauseOp &privOp) {
2017 return privOp.getDataSharingType() ==
2018 omp::DataSharingClauseType::FirstPrivate;
2021 if (!needsFirstprivate)
2024 llvm::BasicBlock *copyBlock =
2025 splitBB(builder,
true,
"omp.private.copy");
2028 for (
auto [decl, moldVar, llvmVar] :
2029 llvm::zip_equal(privateDecls, moldVars, llvmPrivateVars)) {
2030 if (decl.getDataSharingType() != omp::DataSharingClauseType::FirstPrivate)
2034 Region ©Region = decl.getCopyRegion();
2037 builder, moduleTranslation, decl.getCopyMoldArg(), moldVar);
2039 builder, moduleTranslation, decl.getCopyPrivateArg(), llvmVar);
2041 moduleTranslation.
mapValue(decl.getCopyMoldArg(), copyMoldVar);
2044 moduleTranslation.
mapValue(decl.getCopyPrivateArg(), copyPrivateVar);
2048 moduleTranslation)))
2049 return decl.emitError(
"failed to inline `copy` region of `omp.private`");
2063 llvm::OpenMPIRBuilder::InsertPointOrErrorTy res =
2064 ompBuilder->createBarrier(builder, llvm::omp::OMPD_barrier);
2080 llvm::transform(mlirPrivateVars, moldVars.begin(), [&](
mlir::Value mlirVar) {
2082 llvm::Value *moldVar = findAssociatedValue(
2083 mlirVar, builder, moduleTranslation, mappedPrivateVars);
2088 llvmPrivateVars, privateDecls, insertBarrier,
2092template <
typename T>
2100 std::back_inserter(privateCleanupRegions),
2101 [](omp::PrivateClauseOp privatizer) {
2102 return &privatizer.getDeallocRegion();
2106 privateVarsInfo.
llvmVars, moduleTranslation,
2107 builder,
"omp.private.dealloc",
2109 return mlir::emitError(loc,
"failed to inline `dealloc` region of an "
2110 "`omp.private` op in");
2114 for (
auto [privDecl, llvmPrivVar, blockArg] :
2118 ompBuilder->createOMPFreeShared(
2119 builder, llvmPrivVar,
2120 moduleTranslation.
convertType(privDecl.getType()));
2134 if (mlir::isa<omp::CancelOp, omp::CancellationPointOp>(child))
2151 llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder::InsertPointTy allocaIP,
2153 bool isWorksharing =
false);
2161 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2162 using StorableBodyGenCallbackTy =
2163 llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
2165 auto sectionsOp = cast<omp::SectionsOp>(opInst);
2171 assert(isByRef.size() == sectionsOp.getNumReductionVars());
2175 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
2179 sectionsOp.getNumReductionVars());
2183 cast<omp::BlockArgOpenMPOpInterface>(opInst).getReductionBlockArgs();
2186 sectionsOp, reductionArgs, builder, moduleTranslation, allocaIP,
2187 reductionDecls, privateReductionVariables, reductionVariableMap,
2191 bool isTaskReductionMod =
2192 sectionsOp.getReductionMod() == omp::ReductionModifier::task &&
2193 sectionsOp.getNumReductionVars() > 0;
2198 auto sectionOp = dyn_cast<omp::SectionOp>(op);
2202 Region ®ion = sectionOp.getRegion();
2203 auto sectionCB = [§ionsOp, ®ion, &builder, &moduleTranslation](
2204 InsertPointTy allocaIP, InsertPointTy codeGenIP,
2206 builder.restoreIP(codeGenIP);
2213 sectionsOp.getRegion().getNumArguments());
2214 for (
auto [sectionsArg, sectionArg] : llvm::zip_equal(
2215 sectionsOp.getRegion().getArguments(), region.
getArguments())) {
2216 llvm::Value *llvmVal = moduleTranslation.
lookupValue(sectionsArg);
2218 moduleTranslation.
mapValue(sectionArg, llvmVal);
2225 sectionCBs.push_back(sectionCB);
2231 if (sectionCBs.empty())
2239 if (isTaskReductionMod &&
2241 "__omp_taskred_mod_", builder, allocaIP,
2242 moduleTranslation,
true,
2244 return sectionsOp.emitError(
2245 "failed to emit task reduction modifier initialization");
2247 assert(isa<omp::SectionOp>(*sectionsOp.getRegion().op_begin()));
2252 auto privCB = [&](InsertPointTy, InsertPointTy codeGenIP, llvm::Value &,
2253 llvm::Value &vPtr, llvm::Value *&replacementValue)
2254 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
2255 replacementValue = &vPtr;
2261 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
2265 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2266 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2268 ompLoc, allocaIP, sectionCBs, privCB, finiCB, isCancellable,
2269 sectionsOp.getNowait());
2274 builder.restoreIP(*afterIP);
2277 if (isTaskReductionMod)
2283 sectionsOp, builder, moduleTranslation, allocaIP, reductionDecls,
2284 privateReductionVariables, isByRef, sectionsOp.getNowait());
2291 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2298 assert(isByRef.size() == scopeOp.getNumReductionVars());
2307 scopeOp.getNumReductionVars());
2311 cast<omp::BlockArgOpenMPOpInterface>(*scopeOp).getReductionBlockArgs();
2315 scopeOp, builder, moduleTranslation, privateVarsInfo, allocaIP);
2320 scopeOp, reductionArgs, builder, moduleTranslation, allocaIP,
2321 reductionDecls, privateReductionVariables, reductionVariableMap,
2326 [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
2328 builder.restoreIP(codeGenIP);
2334 return llvm::make_error<PreviouslyReportedError>();
2337 scopeOp, builder, moduleTranslation, privateVarsInfo.
mlirVars,
2339 scopeOp.getPrivateNeedsBarrier())))
2340 return llvm::make_error<PreviouslyReportedError>();
2347 auto finiCB = [&](InsertPointTy codeGenIP) -> llvm::Error {
2348 InsertPointTy oldIP = builder.saveIP();
2349 builder.restoreIP(codeGenIP);
2351 scopeOp.getLoc(), privateVarsInfo)))
2352 return llvm::make_error<PreviouslyReportedError>();
2353 builder.restoreIP(oldIP);
2354 return llvm::Error::success();
2357 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2358 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2359 ompBuilder->createScope(ompLoc, bodyCB, finiCB, scopeOp.getNowait());
2364 builder.restoreIP(*afterIP);
2368 scopeOp, builder, moduleTranslation, allocaIP, reductionDecls,
2369 privateReductionVariables, isByRef, scopeOp.getNowait(),
2377 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2378 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2383 auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
2385 builder.restoreIP(codegenIP);
2387 builder, moduleTranslation)
2390 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
2394 std::optional<ArrayAttr> cpFuncs = singleOp.getCopyprivateSyms();
2397 for (
size_t i = 0, e = cpVars.size(); i < e; ++i) {
2398 llvmCPVars.push_back(moduleTranslation.
lookupValue(cpVars[i]));
2400 singleOp, cast<SymbolRefAttr>((*cpFuncs)[i]));
2401 llvmCPFuncs.push_back(
2405 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2407 ompLoc, bodyCB, finiCB, singleOp.getNowait(), llvmCPVars,
2413 builder.restoreIP(*afterIP);
2417static omp::DistributeOp
2421 omp::DistributeOp distOp;
2422 WalkResult walk = teamsOp.getRegion().walk([&](omp::DistributeOp op) {
2428 if (walk.wasInterrupted() || !distOp)
2432 llvm::cast<mlir::omp::BlockArgOpenMPOpInterface>(teamsOp.getOperation());
2436 for (
auto ra : iface.getReductionBlockArgs())
2437 for (
auto &use : ra.getUses()) {
2438 auto *useOp = use.getOwner();
2440 if (mlir::isa<LLVM::DbgDeclareOp, LLVM::DbgValueOp>(useOp)) {
2441 debugUses.push_back(useOp);
2444 if (!distOp->isProperAncestor(useOp))
2451 for (
auto *use : debugUses)
2460 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2465 unsigned numReductionVars = op.getNumReductionVars();
2469 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
2475 if (doTeamsReduction) {
2476 isByRef =
getIsByRef(op.getReductionByref());
2478 assert(isByRef.size() == op.getNumReductionVars());
2481 llvm::cast<omp::BlockArgOpenMPOpInterface>(*op).getReductionBlockArgs();
2486 op, reductionArgs, builder, moduleTranslation, allocaIP,
2487 reductionDecls, privateReductionVariables, reductionVariableMap,
2492 auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
2495 moduleTranslation, allocaIP, deallocBlocks);
2496 builder.restoreIP(codegenIP);
2502 llvm::Value *numTeamsLower =
nullptr;
2503 if (
Value numTeamsLowerVar = op.getNumTeamsLower())
2504 numTeamsLower = moduleTranslation.
lookupValue(numTeamsLowerVar);
2506 llvm::Value *numTeamsUpper =
nullptr;
2507 if (!op.getNumTeamsUpperVars().empty())
2508 numTeamsUpper = moduleTranslation.
lookupValue(op.getNumTeams(0));
2510 llvm::Value *threadLimit =
nullptr;
2511 if (!op.getThreadLimitVars().empty())
2512 threadLimit = moduleTranslation.
lookupValue(op.getThreadLimit(0));
2514 llvm::Value *ifExpr =
nullptr;
2515 if (
Value ifVar = op.getIfExpr())
2518 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2519 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2521 ompLoc, bodyCB, numTeamsLower, numTeamsUpper, threadLimit, ifExpr);
2526 builder.restoreIP(*afterIP);
2527 if (doTeamsReduction) {
2530 op, builder, moduleTranslation, allocaIP, reductionDecls,
2531 privateReductionVariables, isByRef,
2537static llvm::omp::RTLDependenceKindTy
2540 case mlir::omp::ClauseTaskDepend::taskdependin:
2541 return llvm::omp::RTLDependenceKindTy::DepIn;
2545 case mlir::omp::ClauseTaskDepend::taskdependout:
2546 case mlir::omp::ClauseTaskDepend::taskdependinout:
2547 return llvm::omp::RTLDependenceKindTy::DepInOut;
2548 case mlir::omp::ClauseTaskDepend::taskdependmutexinoutset:
2549 return llvm::omp::RTLDependenceKindTy::DepMutexInOutSet;
2550 case mlir::omp::ClauseTaskDepend::taskdependinoutset:
2551 return llvm::omp::RTLDependenceKindTy::DepInOutSet;
2553 llvm_unreachable(
"unhandled depend kind");
2557 std::optional<ArrayAttr> dependKinds,
OperandRange dependVars,
2560 if (dependVars.empty())
2562 for (
auto dep : llvm::zip(dependVars, dependKinds->getValue())) {
2564 cast<mlir::omp::ClauseTaskDependAttr>(std::get<1>(dep)).getValue();
2566 llvm::Value *depVal = moduleTranslation.
lookupValue(std::get<0>(dep));
2567 llvm::OpenMPIRBuilder::DependData dd(type, depVal->getType(), depVal);
2568 dds.emplace_back(dd);
2580 llvm::IRBuilderBase &llvmBuilder, llvm::OpenMPIRBuilder &ompBuilder,
2582 auto finiCB = [&](llvm::OpenMPIRBuilder::InsertPointTy ip) -> llvm::Error {
2583 llvm::IRBuilderBase::InsertPointGuard guard(llvmBuilder);
2587 llvmBuilder.restoreIP(ip);
2593 cancelTerminators.push_back(llvmBuilder.CreateBr(ip.getBlock()));
2594 return llvm::Error::success();
2599 ompBuilder.pushFinalizationCB(
2609 llvm::OpenMPIRBuilder &ompBuilder,
2610 const llvm::OpenMPIRBuilder::InsertPointTy &afterIP) {
2611 ompBuilder.popFinalizationCB();
2612 llvm::BasicBlock *constructFini = afterIP.getBlock()->getSinglePredecessor();
2613 for (llvm::UncondBrInst *cancelBranch : cancelTerminators)
2614 cancelBranch->setSuccessor(constructFini);
2620class TaskContextStructManager {
2622 TaskContextStructManager(llvm::IRBuilderBase &builder,
2623 LLVM::ModuleTranslation &moduleTranslation,
2624 MutableArrayRef<omp::PrivateClauseOp> privateDecls)
2625 : builder{builder}, moduleTranslation{moduleTranslation},
2626 privateDecls{privateDecls} {}
2632 void generateTaskContextStruct();
2638 void createGEPsToPrivateVars();
2644 SmallVector<llvm::Value *>
2645 createGEPsToPrivateVars(llvm::Value *altStructPtr)
const;
2648 void freeStructPtr();
2650 MutableArrayRef<llvm::Value *> getLLVMPrivateVarGEPs() {
2651 return llvmPrivateVarGEPs;
2654 llvm::Value *getStructPtr() {
return structPtr; }
2657 llvm::IRBuilderBase &builder;
2658 LLVM::ModuleTranslation &moduleTranslation;
2659 MutableArrayRef<omp::PrivateClauseOp> privateDecls;
2662 SmallVector<llvm::Type *> privateVarTypes;
2666 SmallVector<llvm::Value *> llvmPrivateVarGEPs;
2669 llvm::Value *structPtr =
nullptr;
2671 llvm::Type *structTy =
nullptr;
2682 llvm::SmallVector<llvm::Value *> lowerBounds;
2683 llvm::SmallVector<llvm::Value *> upperBounds;
2684 llvm::SmallVector<llvm::Value *> steps;
2685 llvm::SmallVector<llvm::Value *> trips;
2687 llvm::Value *totalTrips;
2689 llvm::Value *lookUpAsI64(mlir::Value val,
const LLVM::ModuleTranslation &mt,
2690 llvm::IRBuilderBase &builder) {
2694 if (v->getType()->isIntegerTy(64))
2696 if (v->getType()->isIntegerTy())
2697 return builder.CreateSExtOrTrunc(v, builder.getInt64Ty());
2702 IteratorInfo(mlir::omp::IteratorOp itersOp,
2703 mlir::LLVM::ModuleTranslation &moduleTranslation,
2704 llvm::IRBuilderBase &builder) {
2705 dims = itersOp.getLoopLowerBounds().size();
2706 lowerBounds.resize(dims);
2707 upperBounds.resize(dims);
2711 for (
unsigned d = 0; d < dims; ++d) {
2712 llvm::Value *lb = lookUpAsI64(itersOp.getLoopLowerBounds()[d],
2713 moduleTranslation, builder);
2714 llvm::Value *ub = lookUpAsI64(itersOp.getLoopUpperBounds()[d],
2715 moduleTranslation, builder);
2717 lookUpAsI64(itersOp.getLoopSteps()[d], moduleTranslation, builder);
2718 assert(lb && ub && st &&
2719 "Expect lowerBounds, upperBounds, and steps in IteratorOp");
2720 assert((!llvm::isa<llvm::ConstantInt>(st) ||
2721 !llvm::cast<llvm::ConstantInt>(st)->isZero()) &&
2722 "Expect non-zero step in IteratorOp");
2724 lowerBounds[d] = lb;
2725 upperBounds[d] = ub;
2729 llvm::Value *diff = builder.CreateSub(ub, lb);
2730 llvm::Value *
div = builder.CreateSDiv(diff, st);
2731 trips[d] = builder.CreateAdd(
2732 div, llvm::ConstantInt::get(builder.getInt64Ty(), 1));
2735 totalTrips = llvm::ConstantInt::get(builder.getInt64Ty(), 1);
2736 for (
unsigned d = 0; d < dims; ++d)
2737 totalTrips = builder.CreateMul(totalTrips, trips[d]);
2740 unsigned getDims()
const {
return dims; }
2741 llvm::ArrayRef<llvm::Value *> getLowerBounds()
const {
return lowerBounds; }
2742 llvm::ArrayRef<llvm::Value *> getUpperBounds()
const {
return upperBounds; }
2743 llvm::ArrayRef<llvm::Value *> getSteps()
const {
return steps; }
2744 llvm::ArrayRef<llvm::Value *> getTrips()
const {
return trips; }
2745 llvm::Value *getTotalTrips()
const {
return totalTrips; }
2750void TaskContextStructManager::generateTaskContextStruct() {
2751 if (privateDecls.empty())
2753 privateVarTypes.reserve(privateDecls.size());
2755 for (omp::PrivateClauseOp &privOp : privateDecls) {
2758 if (!privOp.readsFromMold())
2760 Type mlirType = privOp.getType();
2761 privateVarTypes.push_back(moduleTranslation.
convertType(mlirType));
2764 if (privateVarTypes.empty())
2767 structTy = llvm::StructType::get(moduleTranslation.
getLLVMContext(),
2770 llvm::DataLayout dataLayout =
2771 builder.GetInsertBlock()->getModule()->getDataLayout();
2772 llvm::Type *intPtrTy = builder.getIntPtrTy(dataLayout);
2773 llvm::Constant *allocSize = llvm::ConstantExpr::getSizeOf(structTy);
2776 structPtr = builder.CreateMalloc(intPtrTy, structTy, allocSize,
2778 "omp.task.context_ptr");
2781SmallVector<llvm::Value *> TaskContextStructManager::createGEPsToPrivateVars(
2782 llvm::Value *altStructPtr)
const {
2783 SmallVector<llvm::Value *> ret;
2786 ret.reserve(privateDecls.size());
2787 llvm::Value *zero = builder.getInt32(0);
2789 for (
auto privDecl : privateDecls) {
2790 if (!privDecl.readsFromMold()) {
2792 ret.push_back(
nullptr);
2795 llvm::Value *iVal = builder.getInt32(i);
2796 llvm::Value *gep = builder.CreateGEP(structTy, altStructPtr, {zero, iVal});
2803void TaskContextStructManager::createGEPsToPrivateVars() {
2805 assert(privateVarTypes.empty());
2809 llvmPrivateVarGEPs = createGEPsToPrivateVars(structPtr);
2812void TaskContextStructManager::freeStructPtr() {
2816 llvm::IRBuilderBase::InsertPointGuard guard{builder};
2818 builder.SetInsertPoint(builder.GetInsertBlock()->getTerminator());
2819 builder.CreateFree(structPtr);
2823 llvm::OpenMPIRBuilder &ompBuilder,
2824 llvm::Value *affinityList, llvm::Value *
index,
2825 llvm::Value *addr, llvm::Value *len) {
2826 llvm::StructType *kmpTaskAffinityInfoTy =
2827 ompBuilder.getKmpTaskAffinityInfoTy();
2828 llvm::Value *entry = builder.CreateInBoundsGEP(
2829 kmpTaskAffinityInfoTy, affinityList,
index,
"omp.affinity.entry");
2831 addr = builder.CreatePtrToInt(addr, kmpTaskAffinityInfoTy->getElementType(0));
2832 len = builder.CreateIntCast(len, kmpTaskAffinityInfoTy->getElementType(1),
2834 llvm::Value *flags = builder.getInt32(0);
2836 builder.CreateStore(addr,
2837 builder.CreateStructGEP(kmpTaskAffinityInfoTy, entry, 0));
2838 builder.CreateStore(len,
2839 builder.CreateStructGEP(kmpTaskAffinityInfoTy, entry, 1));
2840 builder.CreateStore(flags,
2841 builder.CreateStructGEP(kmpTaskAffinityInfoTy, entry, 2));
2845 llvm::IRBuilderBase &builder,
2847 llvm::Value *affinityList) {
2848 for (
auto [i, affinityVar] : llvm::enumerate(affinityVars)) {
2849 auto entryOp = affinityVar.getDefiningOp<mlir::omp::AffinityEntryOp>();
2850 assert(entryOp &&
"affinity item must be omp.affinity_entry");
2852 llvm::Value *addr = moduleTranslation.
lookupValue(entryOp.getAddr());
2853 llvm::Value *len = moduleTranslation.
lookupValue(entryOp.getLen());
2854 assert(addr && len &&
"expect affinity addr and len to be non-null");
2856 affinityList, builder.getInt64(i), addr, len);
2860static mlir::LogicalResult
2863 llvm::IRBuilderBase &builder,
2865 llvm::Value *tmp = linearIV;
2866 for (
int d = (
int)iterInfo.getDims() - 1; d >= 0; --d) {
2867 llvm::Value *trip = iterInfo.getTrips()[d];
2869 llvm::Value *idx = builder.CreateURem(tmp, trip);
2871 tmp = builder.CreateUDiv(tmp, trip);
2874 llvm::Value *physIV = builder.CreateAdd(
2875 iterInfo.getLowerBounds()[d],
2876 builder.CreateMul(idx, iterInfo.getSteps()[d]),
"omp.it.phys_iv");
2882 moduleTranslation.
mapBlock(&iteratorRegionBlock, builder.GetInsertBlock());
2883 if (mlir::failed(moduleTranslation.
convertBlock(iteratorRegionBlock,
2886 return mlir::failure();
2888 return mlir::success();
2894static mlir::LogicalResult
2897 IteratorInfo &iterInfo, llvm::StringRef loopName,
2902 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
2904 auto bodyGen = [&](llvm::OpenMPIRBuilder::InsertPointTy bodyIP,
2905 llvm::Value *linearIV) -> llvm::Error {
2906 llvm::IRBuilderBase::InsertPointGuard guard(builder);
2907 builder.restoreIP(bodyIP);
2910 builder, moduleTranslation))) {
2911 return llvm::make_error<llvm::StringError>(
2912 "failed to convert iterator region", llvm::inconvertibleErrorCode());
2916 mlir::dyn_cast<mlir::omp::YieldOp>(iteratorRegionBlock.
getTerminator());
2917 assert(yield && yield.getResults().size() == 1 &&
2918 "expect omp.yield in iterator region to have one result");
2920 genStoreEntry(linearIV, yield);
2926 return llvm::Error::success();
2929 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2931 loc, iterInfo.getTotalTrips(), bodyGen, loopName);
2935 builder.restoreIP(*afterIP);
2937 return mlir::success();
2940static mlir::LogicalResult
2943 llvm::OpenMPIRBuilder::AffinityData &ad) {
2945 if (taskOp.getAffinityVars().empty() && taskOp.getIterated().empty()) {
2948 return mlir::success();
2952 llvm::StructType *kmpTaskAffinityInfoTy =
2955 auto allocateAffinityList = [&](llvm::Value *count) -> llvm::Value * {
2956 llvm::IRBuilderBase::InsertPointGuard guard(builder);
2957 if (llvm::isa<llvm::Constant>(count) || llvm::isa<llvm::Argument>(count))
2959 return builder.CreateAlloca(kmpTaskAffinityInfoTy, count,
2960 "omp.affinity_list");
2963 auto createAffinity =
2964 [&](llvm::Value *count,
2965 llvm::Value *info) -> llvm::OpenMPIRBuilder::AffinityData {
2966 llvm::OpenMPIRBuilder::AffinityData ad{};
2967 ad.Count = builder.CreateTrunc(count, builder.getInt32Ty());
2969 builder.CreatePointerBitCastOrAddrSpaceCast(info, builder.getPtrTy(0));
2973 if (!taskOp.getAffinityVars().empty()) {
2974 llvm::Value *count = llvm::ConstantInt::get(
2975 builder.getInt64Ty(), taskOp.getAffinityVars().size());
2976 llvm::Value *list = allocateAffinityList(count);
2979 ads.emplace_back(createAffinity(count, list));
2982 if (!taskOp.getIterated().empty()) {
2983 for (
auto [i, iter] : llvm::enumerate(taskOp.getIterated())) {
2984 auto itersOp = iter.getDefiningOp<omp::IteratorOp>();
2985 assert(itersOp &&
"iterated value must be defined by omp.iterator");
2986 IteratorInfo iterInfo(itersOp, moduleTranslation, builder);
2987 llvm::Value *affList = allocateAffinityList(iterInfo.getTotalTrips());
2989 itersOp, builder, moduleTranslation, iterInfo,
"iterator",
2990 [&](llvm::Value *linearIV, mlir::omp::YieldOp yield) {
2991 auto entryOp = yield.getResults()[0]
2992 .getDefiningOp<mlir::omp::AffinityEntryOp>();
2993 assert(entryOp &&
"expect yield produce an affinity entry");
3000 affList, linearIV, addr, len);
3002 return llvm::failure();
3003 ads.emplace_back(createAffinity(iterInfo.getTotalTrips(), affList));
3007 llvm::Value *totalAffinityCount = builder.getInt32(0);
3008 for (
const auto &affinity : ads)
3009 totalAffinityCount = builder.CreateAdd(
3011 builder.CreateIntCast(affinity.Count, builder.getInt32Ty(),
3014 llvm::Value *affinityInfo = ads.front().Info;
3015 if (ads.size() > 1) {
3016 llvm::StructType *kmpTaskAffinityInfoTy =
3018 llvm::Value *affinityInfoElemSize = builder.getInt64(
3019 moduleTranslation.
getLLVMModule()->getDataLayout().getTypeAllocSize(
3020 kmpTaskAffinityInfoTy));
3022 llvm::Value *packedAffinityInfo = allocateAffinityList(totalAffinityCount);
3023 llvm::Value *packedAffinityInfoOffset = builder.getInt32(0);
3024 for (
const auto &affinity : ads) {
3025 llvm::Value *affinityCount = builder.CreateIntCast(
3026 affinity.Count, builder.getInt32Ty(),
false);
3027 llvm::Value *affinityCountInt64 = builder.CreateIntCast(
3028 affinityCount, builder.getInt64Ty(),
false);
3029 llvm::Value *affinityInfoSize =
3030 builder.CreateMul(affinityCountInt64, affinityInfoElemSize);
3032 llvm::Value *packedAffinityInfoIndex = builder.CreateIntCast(
3033 packedAffinityInfoOffset, kmpTaskAffinityInfoTy->getElementType(0),
3035 packedAffinityInfoIndex = builder.CreateInBoundsGEP(
3036 kmpTaskAffinityInfoTy, packedAffinityInfo, packedAffinityInfoIndex);
3038 builder.CreateMemCpy(
3039 packedAffinityInfoIndex, llvm::Align(1),
3040 builder.CreatePointerBitCastOrAddrSpaceCast(
3041 affinity.Info, builder.getPtrTy(packedAffinityInfoIndex->getType()
3042 ->getPointerAddressSpace())),
3043 llvm::Align(1), affinityInfoSize);
3045 packedAffinityInfoOffset =
3046 builder.CreateAdd(packedAffinityInfoOffset, affinityCount);
3049 affinityInfo = packedAffinityInfo;
3052 ad.Count = totalAffinityCount;
3053 ad.Info = affinityInfo;
3055 return mlir::success();
3061static mlir::LogicalResult
3064 std::optional<ArrayAttr> dependIteratedKinds,
3065 llvm::IRBuilderBase &builder,
3067 llvm::OpenMPIRBuilder::DependenciesInfo &taskDeps) {
3068 if (dependIterated.empty()) {
3071 return mlir::success();
3075 llvm::Type *dependInfoTy = ompBuilder.DependInfo;
3076 unsigned numLocator = dependVars.size();
3079 llvm::Value *totalCount =
3080 llvm::ConstantInt::get(builder.getInt64Ty(), numLocator);
3083 for (
auto iter : dependIterated) {
3084 auto itersOp = iter.getDefiningOp<mlir::omp::IteratorOp>();
3085 assert(itersOp &&
"depend_iterated value must be defined by omp.iterator");
3086 iterInfos.emplace_back(itersOp, moduleTranslation, builder);
3088 builder.CreateAdd(totalCount, iterInfos.back().getTotalTrips());
3093 llvm::Constant *allocSize = llvm::ConstantExpr::getSizeOf(dependInfoTy);
3094 llvm::Value *depArray =
3095 builder.CreateMalloc(ompBuilder.SizeTy, dependInfoTy, allocSize,
3096 totalCount,
nullptr,
".dep.arr.addr");
3099 if (numLocator > 0) {
3102 for (
auto [i, dd] : llvm::enumerate(dds)) {
3103 llvm::Value *idx = llvm::ConstantInt::get(builder.getInt64Ty(), i);
3104 llvm::Value *entry =
3105 builder.CreateInBoundsGEP(dependInfoTy, depArray, idx);
3106 ompBuilder.emitTaskDependency(builder, entry, dd);
3111 llvm::Value *offset =
3112 llvm::ConstantInt::get(builder.getInt64Ty(), numLocator);
3113 for (
auto [i, iterInfo] : llvm::enumerate(iterInfos)) {
3114 auto kindAttr = cast<mlir::omp::ClauseTaskDependAttr>(
3115 dependIteratedKinds->getValue()[i]);
3116 llvm::omp::RTLDependenceKindTy rtlKind =
3119 auto itersOp = dependIterated[i].getDefiningOp<mlir::omp::IteratorOp>();
3121 itersOp, builder, moduleTranslation, iterInfo,
"dep_iterator",
3122 [&](llvm::Value *linearIV, mlir::omp::YieldOp yield) {
3124 moduleTranslation.
lookupValue(yield.getResults()[0]);
3125 llvm::Value *idx = builder.CreateAdd(offset, linearIV);
3126 llvm::Value *entry =
3127 builder.CreateInBoundsGEP(dependInfoTy, depArray, idx);
3128 ompBuilder.emitTaskDependency(
3130 llvm::OpenMPIRBuilder::DependData{rtlKind, addr->getType(),
3133 return mlir::failure();
3136 offset = builder.CreateAdd(offset, iterInfo.getTotalTrips());
3139 taskDeps.DepArray = depArray;
3140 taskDeps.NumDeps = builder.CreateTrunc(totalCount, builder.getInt32Ty());
3141 return mlir::success();
3148 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
3153 TaskContextStructManager taskStructMgr{builder, moduleTranslation,
3165 InsertPointTy allocaIP =
3170 assert(builder.GetInsertPoint() == builder.GetInsertBlock()->end());
3171 llvm::BasicBlock *taskStartBlock = llvm::BasicBlock::Create(
3172 builder.getContext(),
"omp.task.start",
3173 builder.GetInsertBlock()->getParent());
3174 llvm::Instruction *branchToTaskStartBlock = builder.CreateBr(taskStartBlock);
3175 builder.SetInsertPoint(branchToTaskStartBlock);
3178 llvm::BasicBlock *copyBlock =
3179 splitBB(builder,
true,
"omp.private.copy");
3180 llvm::BasicBlock *initBlock =
3181 splitBB(builder,
true,
"omp.private.init");
3197 moduleTranslation, allocaIP, deallocBlocks);
3200 builder.SetInsertPoint(initBlock->getTerminator());
3203 taskStructMgr.generateTaskContextStruct();
3210 taskStructMgr.createGEPsToPrivateVars();
3212 for (
auto [privDecl, mlirPrivVar, blockArg, llvmPrivateVarAlloc] :
3215 taskStructMgr.getLLVMPrivateVarGEPs())) {
3217 if (!privDecl.readsFromMold())
3219 assert(llvmPrivateVarAlloc &&
3220 "reads from mold so shouldn't have been skipped");
3223 initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar,
3224 blockArg, llvmPrivateVarAlloc, initBlock);
3225 if (!privateVarOrErr)
3226 return handleError(privateVarOrErr, *taskOp.getOperation());
3235 [[maybe_unused]] llvm::Value *llvmPrivateVar = llvmPrivateVarAlloc;
3236 if ((privateVarOrErr.get() != llvmPrivateVarAlloc) &&
3237 !mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
3238 builder.CreateStore(privateVarOrErr.get(), llvmPrivateVarAlloc);
3240 llvmPrivateVar = builder.CreateLoad(privateVarOrErr.get()->getType(),
3241 llvmPrivateVarAlloc);
3243 assert(llvmPrivateVar->getType() ==
3244 moduleTranslation.
convertType(blockArg.getType()));
3254 taskOp, builder, moduleTranslation, privateVarsInfo.
mlirVars,
3255 taskStructMgr.getLLVMPrivateVarGEPs(), privateVarsInfo.
privatizers,
3256 taskOp.getPrivateNeedsBarrier())))
3257 return llvm::failure();
3259 llvm::OpenMPIRBuilder::AffinityData ad;
3261 return llvm::failure();
3271 taskOp.getOperation(), taskOp.getInReductionSyms(),
"omp.task",
3272 "in_reduction", inRedDecls)))
3275 inRedOrigPtrs.reserve(inRedDecls.size());
3276 for (
Value v : taskOp.getInReductionVars())
3277 inRedOrigPtrs.push_back(moduleTranslation.
lookupValue(v));
3280 builder.SetInsertPoint(taskStartBlock);
3283 [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
3288 moduleTranslation, allocaIP, deallocBlocks);
3291 builder.restoreIP(codegenIP);
3293 llvm::BasicBlock *privInitBlock =
nullptr;
3295 for (
auto [i, zip] : llvm::enumerate(llvm::zip_equal(
3298 auto [blockArg, privDecl, mlirPrivVar] = zip;
3300 if (privDecl.readsFromMold())
3303 llvm::IRBuilderBase::InsertPointGuard guard(builder);
3304 llvm::Type *llvmAllocType =
3305 moduleTranslation.
convertType(privDecl.getType());
3306 builder.SetInsertPoint(allocaIP.getBlock()->getTerminator());
3307 llvm::Value *llvmPrivateVar = builder.CreateAlloca(
3308 llvmAllocType,
nullptr,
"omp.private.alloc");
3311 initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar,
3312 blockArg, llvmPrivateVar, privInitBlock);
3313 if (!privateVarOrError)
3314 return privateVarOrError.takeError();
3315 moduleTranslation.
mapValue(blockArg, privateVarOrError.get());
3316 privateVarsInfo.
llvmVars[i] = privateVarOrError.get();
3319 taskStructMgr.createGEPsToPrivateVars();
3320 for (
auto [i, llvmPrivVar] :
3321 llvm::enumerate(taskStructMgr.getLLVMPrivateVarGEPs())) {
3323 assert(privateVarsInfo.
llvmVars[i] &&
3324 "This is added in the loop above");
3327 privateVarsInfo.
llvmVars[i] = llvmPrivVar;
3332 for (
auto [blockArg, llvmPrivateVar, privateDecl] :
3336 if (!privateDecl.readsFromMold())
3339 if (!mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
3340 llvmPrivateVar = builder.CreateLoad(
3341 moduleTranslation.
convertType(blockArg.getType()), llvmPrivateVar);
3343 assert(llvmPrivateVar->getType() ==
3344 moduleTranslation.
convertType(blockArg.getType()));
3345 moduleTranslation.
mapValue(blockArg, llvmPrivateVar);
3356 if (!inRedDecls.empty()) {
3357 auto iface = cast<omp::BlockArgOpenMPOpInterface>(taskOp.getOperation());
3360 llvm::LLVMContext &llvmCtx = m->getContext();
3361 llvm::OpenMPIRBuilder::LocationDescription bodyLoc(builder);
3362 uint32_t srcLocSize;
3363 llvm::Constant *srcLocStr =
3364 ompB.getOrCreateSrcLocStr(bodyLoc, srcLocSize);
3365 llvm::Value *bodyIdent = ompB.getOrCreateIdent(srcLocStr, srcLocSize);
3368 ompB.updateToLocation(bodyLoc);
3369 llvm::Value *bodyGtid = ompB.getOrCreateThreadID(bodyIdent);
3370 llvm::FunctionCallee getThData = ompB.getOrCreateRuntimeFunction(
3371 *m, llvm::omp::OMPRTL___kmpc_task_reduction_get_th_data);
3372 llvm::Type *ptrTy = llvm::PointerType::getUnqual(llvmCtx);
3373 llvm::Value *nullDesc = llvm::ConstantPointerNull::get(ptrTy);
3375 for (
auto [blockArg, origPtr] :
3376 llvm::zip_equal(inRedBlockArgs, inRedOrigPtrs)) {
3383 llvm::Value *lookupPtr = origPtr;
3384 if (
auto *origPtrTy =
3385 llvm::dyn_cast<llvm::PointerType>(lookupPtr->getType());
3386 origPtrTy && origPtrTy->getAddressSpace() != 0)
3387 lookupPtr = builder.CreateAddrSpaceCast(lookupPtr, ptrTy);
3388 llvm::Value *priv = builder.CreateCall(
3389 getThData, {bodyGtid, nullDesc, lookupPtr},
"omp.inred.priv");
3390 if (
auto *argPtrTy = llvm::dyn_cast<llvm::PointerType>(
3391 moduleTranslation.
convertType(blockArg.getType()));
3392 argPtrTy && argPtrTy->getAddressSpace() != 0)
3393 priv = builder.CreateAddrSpaceCast(priv, argPtrTy);
3394 moduleTranslation.
mapValue(blockArg, priv);
3399 taskOp.getRegion(),
"omp.task.region", builder, moduleTranslation);
3400 if (failed(
handleError(continuationBlockOrError, *taskOp)))
3401 return llvm::make_error<PreviouslyReportedError>();
3403 builder.SetInsertPoint(continuationBlockOrError.get()->getTerminator());
3406 taskOp.getLoc(), privateVarsInfo)))
3407 return llvm::make_error<PreviouslyReportedError>();
3410 taskStructMgr.freeStructPtr();
3412 return llvm::Error::success();
3421 llvm::omp::Directive::OMPD_taskgroup);
3423 llvm::OpenMPIRBuilder::DependenciesInfo dependencies;
3424 if (failed(
buildDependData(taskOp.getDependVars(), taskOp.getDependKinds(),
3425 taskOp.getDependIterated(),
3426 taskOp.getDependIteratedKinds(), builder,
3427 moduleTranslation, dependencies)))
3430 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
3431 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
3433 ompLoc, allocaIP, deallocBlocks, bodyCB, !taskOp.getUntied(),
3435 moduleTranslation.
lookupValue(taskOp.getIfExpr()), dependencies, ad,
3436 taskOp.getMergeable(),
3437 moduleTranslation.
lookupValue(taskOp.getEventHandle()),
3438 moduleTranslation.
lookupValue(taskOp.getPriority()));
3446 builder.restoreIP(*afterIP);
3448 if (dependencies.DepArray)
3449 builder.CreateFree(dependencies.DepArray);
3458 llvm::IRBuilderBase &builder,
3466 loopWrapperOp.getRegion(),
"omp.taskloop.wrapper.region", builder,
3469 if (failed(
handleError(continuationBlockOrError, opInst)))
3472 builder.SetInsertPoint(continuationBlockOrError.get());
3480static llvm::Expected<llvm::Value *>
3483 llvm::IRBuilderBase &builder) {
3484 if (llvm::Value *mapped = moduleTranslation.
lookupValue(value))
3489 return llvm::make_error<llvm::StringError>(
3490 "value is a block argument and is not mapped",
3491 llvm::inconvertibleErrorCode());
3493 return llvm::make_error<llvm::StringError>(
3494 "unsupported op defining taskloop loop bound",
3495 llvm::inconvertibleErrorCode());
3505 if (!operandOrError)
3506 return operandOrError.takeError();
3507 moduleTranslation.
mapValue(operand, *operandOrError);
3508 mappingsToRemove.push_back(operand);
3512 return llvm::make_error<llvm::StringError>(
3513 "failed to convert op defining taskloop loop bound",
3514 llvm::inconvertibleErrorCode());
3517 assert(
result &&
"expected conversion of loop bound op to produce a value");
3521 mappingsToRemove.push_back(resultValue);
3523 for (
Value mappedValue : mappingsToRemove)
3532 llvm::Value *&lbVal, llvm::Value *&ubVal,
3533 llvm::Value *&stepVal) {
3541 return firstLbOrErr.takeError();
3543 llvm::Type *boundType = (*firstLbOrErr)->getType();
3544 ubVal = builder.getIntN(boundType->getIntegerBitWidth(), 1);
3545 if (loopOp.getCollapseNumLoops() > 1) {
3563 for (uint64_t i = 0; i < loopOp.getCollapseNumLoops(); i++) {
3565 i == 0 ? std::move(firstLbOrErr)
3569 return lbOrErr.takeError();
3571 upperBounds[i], moduleTranslation, builder);
3573 return ubOrErr.takeError();
3577 return stepOrErr.takeError();
3579 llvm::Value *loopLb = *lbOrErr;
3580 llvm::Value *loopUb = *ubOrErr;
3581 llvm::Value *loopStep = *stepOrErr;
3587 llvm::Value *loopLbMinusOne = builder.CreateSub(
3588 loopLb, builder.getIntN(boundType->getIntegerBitWidth(), 1));
3589 llvm::Value *loopUbMinusOne = builder.CreateSub(
3590 loopUb, builder.getIntN(boundType->getIntegerBitWidth(), 1));
3591 llvm::Value *boundsCmp = builder.CreateICmpSLT(loopLb, loopUb);
3592 llvm::Value *ubMinusLb = builder.CreateSub(loopUb, loopLbMinusOne);
3593 llvm::Value *lbMinusUb = builder.CreateSub(loopLb, loopUbMinusOne);
3594 llvm::Value *loopTripCount =
3595 builder.CreateSelect(boundsCmp, ubMinusLb, lbMinusUb);
3596 loopTripCount = builder.CreateBinaryIntrinsic(
3597 llvm::Intrinsic::abs, loopTripCount, builder.getFalse());
3601 llvm::Value *loopTripCountDivStep =
3602 builder.CreateSDiv(loopTripCount, loopStep);
3603 loopTripCountDivStep = builder.CreateBinaryIntrinsic(
3604 llvm::Intrinsic::abs, loopTripCountDivStep, builder.getFalse());
3605 llvm::Value *loopTripCountRem =
3606 builder.CreateSRem(loopTripCount, loopStep);
3607 loopTripCountRem = builder.CreateBinaryIntrinsic(
3608 llvm::Intrinsic::abs, loopTripCountRem, builder.getFalse());
3609 llvm::Value *needsRoundUp = builder.CreateICmpNE(
3611 builder.getIntN(loopTripCountRem->getType()->getIntegerBitWidth(),
3614 builder.CreateAdd(loopTripCountDivStep,
3615 builder.CreateZExtOrTrunc(
3616 needsRoundUp, loopTripCountDivStep->getType()));
3617 ubVal = builder.CreateMul(ubVal, loopTripCount);
3619 lbVal = builder.getIntN(boundType->getIntegerBitWidth(), 1);
3620 stepVal = builder.getIntN(boundType->getIntegerBitWidth(), 1);
3625 return ubOrErr.takeError();
3629 return stepOrErr.takeError();
3630 lbVal = *firstLbOrErr;
3632 stepVal = *stepOrErr;
3635 assert(lbVal !=
nullptr &&
"Expected value for lbVal");
3636 assert(ubVal !=
nullptr &&
"Expected value for ubVal");
3637 assert(stepVal !=
nullptr &&
"Expected value for stepVal");
3638 return llvm::Error::success();
3644 llvm::IRBuilderBase &builder,
3646 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
3648 omp::TaskloopWrapperOp loopWrapperOp = contextOp.getLoopOp();
3656 TaskContextStructManager taskStructMgr{builder, moduleTranslation,
3660 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
3663 assert(builder.GetInsertPoint() == builder.GetInsertBlock()->end());
3664 llvm::BasicBlock *taskloopStartBlock = llvm::BasicBlock::Create(
3665 builder.getContext(),
"omp.taskloop.wrapper.start",
3666 builder.GetInsertBlock()->getParent());
3667 llvm::Instruction *branchToTaskloopStartBlock =
3668 builder.CreateBr(taskloopStartBlock);
3669 builder.SetInsertPoint(branchToTaskloopStartBlock);
3671 llvm::BasicBlock *copyBlock =
3672 splitBB(builder,
true,
"omp.private.copy");
3673 llvm::BasicBlock *initBlock =
3674 splitBB(builder,
true,
"omp.private.init");
3677 moduleTranslation, allocaIP, deallocBlocks);
3680 builder.SetInsertPoint(initBlock->getTerminator());
3683 taskStructMgr.generateTaskContextStruct();
3684 taskStructMgr.createGEPsToPrivateVars();
3686 llvmFirstPrivateVars.resize(privateVarsInfo.
blockArgs.size());
3688 for (
auto [i, zip] : llvm::enumerate(llvm::zip_equal(
3690 privateVarsInfo.
blockArgs, taskStructMgr.getLLVMPrivateVarGEPs()))) {
3691 auto [privDecl, mlirPrivVar, blockArg, llvmPrivateVarAlloc] = zip;
3693 if (!privDecl.readsFromMold())
3695 assert(llvmPrivateVarAlloc &&
3696 "reads from mold so shouldn't have been skipped");
3699 initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar,
3700 blockArg, llvmPrivateVarAlloc, initBlock);
3701 if (!privateVarOrErr)
3702 return handleError(privateVarOrErr, *contextOp.getOperation());
3704 llvmFirstPrivateVars[i] = privateVarOrErr.get();
3706 llvm::IRBuilderBase::InsertPointGuard guard(builder);
3707 builder.SetInsertPoint(builder.GetInsertBlock()->getTerminator());
3709 [[maybe_unused]] llvm::Value *llvmPrivateVar = llvmPrivateVarAlloc;
3710 if ((privateVarOrErr.get() != llvmPrivateVarAlloc) &&
3711 !mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
3712 builder.CreateStore(privateVarOrErr.get(), llvmPrivateVarAlloc);
3714 llvmPrivateVar = builder.CreateLoad(privateVarOrErr.get()->getType(),
3715 llvmPrivateVarAlloc);
3717 assert(llvmPrivateVar->getType() ==
3718 moduleTranslation.
convertType(blockArg.getType()));
3724 contextOp, builder, moduleTranslation, privateVarsInfo.
mlirVars,
3725 taskStructMgr.getLLVMPrivateVarGEPs(), privateVarsInfo.
privatizers,
3726 contextOp.getPrivateNeedsBarrier())))
3727 return llvm::failure();
3737 contextOp.getOperation(), contextOp.getReductionSyms(),
3738 "omp.taskloop.context",
"reduction", redDecls)))
3742 contextOp.getOperation(), contextOp.getInReductionSyms(),
3743 "omp.taskloop.context",
"in_reduction", inRedDecls)))
3749 redOrigPtrs.reserve(redDecls.size());
3750 for (
Value v : contextOp.getReductionVars())
3751 redOrigPtrs.push_back(moduleTranslation.
lookupValue(v));
3753 inRedOrigPtrs.reserve(inRedDecls.size());
3754 for (
Value v : contextOp.getInReductionVars())
3755 inRedOrigPtrs.push_back(moduleTranslation.
lookupValue(v));
3759 builder.SetInsertPoint(taskloopStartBlock);
3761 llvm::OpenMPIRBuilder &ompBuilderRef = *moduleTranslation.
getOpenMPBuilder();
3768 bool implicitTaskgroup = !redDecls.empty();
3769 llvm::Value *redDesc =
nullptr;
3770 if (implicitTaskgroup) {
3771 llvm::OpenMPIRBuilder::LocationDescription redLoc(builder);
3772 uint32_t srcLocSize;
3773 llvm::Constant *srcLocStr =
3774 ompBuilderRef.getOrCreateSrcLocStr(redLoc, srcLocSize);
3775 llvm::Value *ident = ompBuilderRef.getOrCreateIdent(srcLocStr, srcLocSize);
3778 ompBuilderRef.updateToLocation(redLoc);
3779 llvm::Value *outerGtid = ompBuilderRef.getOrCreateThreadID(ident);
3780 llvm::FunctionCallee taskgroupFn = ompBuilderRef.getOrCreateRuntimeFunction(
3781 *module, llvm::omp::OMPRTL___kmpc_taskgroup);
3782 builder.CreateCall(taskgroupFn, {ident, outerGtid});
3785 "__omp_taskloop_taskred_", builder,
3786 allocaIP, moduleTranslation);
3791 auto loopOp = cast<omp::LoopNestOp>(loopWrapperOp.getWrappedLoop());
3792 llvm::Value *lbVal =
nullptr;
3793 llvm::Value *ubVal =
nullptr;
3794 llvm::Value *stepVal =
nullptr;
3796 loopOp, builder, moduleTranslation, lbVal, ubVal, stepVal))
3800 [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
3805 moduleTranslation, allocaIP, deallocBlocks);
3808 builder.restoreIP(codegenIP);
3810 llvm::BasicBlock *privInitBlock =
nullptr;
3812 for (
auto [i, zip] : llvm::enumerate(llvm::zip_equal(
3815 auto [blockArg, privDecl, mlirPrivVar] = zip;
3817 if (privDecl.readsFromMold())
3820 llvm::IRBuilderBase::InsertPointGuard guard(builder);
3821 llvm::Type *llvmAllocType =
3822 moduleTranslation.
convertType(privDecl.getType());
3823 builder.SetInsertPoint(allocaIP.getBlock()->getTerminator());
3824 llvm::Value *llvmPrivateVar = builder.CreateAlloca(
3825 llvmAllocType,
nullptr,
"omp.private.alloc");
3828 initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar,
3829 blockArg, llvmPrivateVar, privInitBlock);
3830 if (!privateVarOrError)
3831 return privateVarOrError.takeError();
3832 moduleTranslation.
mapValue(blockArg, privateVarOrError.get());
3833 privateVarsInfo.
llvmVars[i] = privateVarOrError.get();
3836 taskStructMgr.createGEPsToPrivateVars();
3837 for (
auto [i, llvmPrivVar] :
3838 llvm::enumerate(taskStructMgr.getLLVMPrivateVarGEPs())) {
3840 assert(privateVarsInfo.
llvmVars[i] &&
3841 "This is added in the loop above");
3844 privateVarsInfo.
llvmVars[i] = llvmPrivVar;
3849 for (
auto [blockArg, llvmPrivateVar, privateDecl] :
3853 if (!privateDecl.readsFromMold())
3856 if (!mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
3857 llvmPrivateVar = builder.CreateLoad(
3858 moduleTranslation.
convertType(blockArg.getType()), llvmPrivateVar);
3860 assert(llvmPrivateVar->getType() ==
3861 moduleTranslation.
convertType(blockArg.getType()));
3862 moduleTranslation.
mapValue(blockArg, llvmPrivateVar);
3874 if (!redDecls.empty() || !inRedDecls.empty()) {
3876 cast<omp::BlockArgOpenMPOpInterface>(contextOp.getOperation());
3879 llvm::LLVMContext &llvmCtx = m->getContext();
3880 llvm::OpenMPIRBuilder::LocationDescription bodyLoc(builder);
3881 uint32_t srcLocSize;
3882 llvm::Constant *srcLocStr =
3883 ompB.getOrCreateSrcLocStr(bodyLoc, srcLocSize);
3884 llvm::Value *bodyIdent = ompB.getOrCreateIdent(srcLocStr, srcLocSize);
3887 ompB.updateToLocation(bodyLoc);
3888 llvm::Value *bodyGtid = ompB.getOrCreateThreadID(bodyIdent);
3889 llvm::FunctionCallee getThData = ompB.getOrCreateRuntimeFunction(
3890 *m, llvm::omp::OMPRTL___kmpc_task_reduction_get_th_data);
3891 llvm::Type *ptrTy = llvm::PointerType::getUnqual(llvmCtx);
3901 auto remapReductionArg = [&](
BlockArgument blockArg, llvm::Value *desc,
3902 llvm::Value *origPtr,
3903 const llvm::Twine &name) {
3904 if (
auto *origPtrTy =
3905 llvm::dyn_cast<llvm::PointerType>(origPtr->getType());
3906 origPtrTy && origPtrTy->getAddressSpace() != 0)
3907 origPtr = builder.CreateAddrSpaceCast(origPtr, ptrTy);
3909 builder.CreateCall(getThData, {bodyGtid, desc, origPtr}, name);
3910 if (
auto *argPtrTy = llvm::dyn_cast<llvm::PointerType>(
3912 argPtrTy && argPtrTy->getAddressSpace() != 0)
3913 priv = builder.CreateAddrSpaceCast(priv, argPtrTy);
3914 moduleTranslation.
mapValue(blockArg, priv);
3918 for (
auto [blockArg, origPtr] :
3919 llvm::zip_equal(redBlockArgs, redOrigPtrs))
3920 remapReductionArg(blockArg, redDesc, origPtr,
"omp.taskred.priv");
3922 llvm::Value *nullDesc = llvm::ConstantPointerNull::get(ptrTy);
3923 for (
auto [blockArg, origPtr] :
3924 llvm::zip_equal(inRedBlockArgs, inRedOrigPtrs))
3925 remapReductionArg(blockArg, nullDesc, origPtr,
"omp.inred.priv");
3931 contextOp.getRegion(),
"omp.taskloop.context.region", builder,
3934 if (failed(
handleError(continuationBlockOrError, opInst)))
3935 return llvm::make_error<PreviouslyReportedError>();
3937 builder.SetInsertPoint(continuationBlockOrError.get()->getTerminator());
3945 contextOp.getLoc(), privateVarsInfo)))
3946 return llvm::make_error<PreviouslyReportedError>();
3949 taskStructMgr.freeStructPtr();
3951 return llvm::Error::success();
3957 auto taskDupCB = [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
3958 llvm::Value *destPtr, llvm::Value *srcPtr)
3960 llvm::IRBuilderBase::InsertPointGuard guard(builder);
3961 builder.restoreIP(codegenIP);
3964 builder.getPtrTy(srcPtr->getType()->getPointerAddressSpace());
3966 builder.CreateLoad(ptrTy, srcPtr,
"omp.taskloop.context.src");
3968 TaskContextStructManager &srcStructMgr = taskStructMgr;
3969 TaskContextStructManager destStructMgr(builder, moduleTranslation,
3971 destStructMgr.generateTaskContextStruct();
3972 llvm::Value *dest = destStructMgr.getStructPtr();
3973 dest->setName(
"omp.taskloop.context.dest");
3974 builder.CreateStore(dest, destPtr);
3977 srcStructMgr.createGEPsToPrivateVars(src);
3979 destStructMgr.createGEPsToPrivateVars(dest);
3982 for (
auto [privDecl, mold, blockArg, llvmPrivateVarAlloc] :
3983 llvm::zip_equal(privateVarsInfo.
privatizers, srcGEPs,
3986 if (!privDecl.readsFromMold())
3988 assert(llvmPrivateVarAlloc &&
3989 "reads from mold so shouldn't have been skipped");
3992 builder, moduleTranslation, privDecl.getInitMoldArg(), mold);
3994 builder, moduleTranslation, privDecl, moldArg, blockArg,
3995 llvmPrivateVarAlloc, builder.GetInsertBlock());
3996 if (!privateVarOrErr)
3997 return privateVarOrErr.takeError();
4006 [[maybe_unused]] llvm::Value *llvmPrivateVar = llvmPrivateVarAlloc;
4007 if ((privateVarOrErr.get() != llvmPrivateVarAlloc) &&
4008 !mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
4009 builder.CreateStore(privateVarOrErr.get(), llvmPrivateVarAlloc);
4011 llvmPrivateVar = builder.CreateLoad(privateVarOrErr.get()->getType(),
4012 llvmPrivateVarAlloc);
4014 assert(llvmPrivateVar->getType() ==
4015 moduleTranslation.
convertType(blockArg.getType()));
4023 moduleTranslation, srcGEPs, destGEPs,
4025 contextOp.getPrivateNeedsBarrier())))
4026 return llvm::make_error<PreviouslyReportedError>();
4028 return builder.saveIP();
4036 llvm::Value *ifCond =
nullptr;
4037 llvm::Value *grainsize =
nullptr;
4039 mlir::Value grainsizeVal = contextOp.getGrainsize();
4040 mlir::Value numTasksVal = contextOp.getNumTasks();
4041 if (
Value ifVar = contextOp.getIfExpr())
4044 grainsize = moduleTranslation.
lookupValue(grainsizeVal);
4046 }
else if (numTasksVal) {
4047 grainsize = moduleTranslation.
lookupValue(numTasksVal);
4051 llvm::OpenMPIRBuilder::TaskDupCallbackTy taskDupOrNull =
nullptr;
4052 if (taskStructMgr.getStructPtr())
4053 taskDupOrNull = taskDupCB;
4063 llvm::omp::Directive::OMPD_taskgroup);
4065 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4066 bool effectiveNoGroup = contextOp.getNogroup() || implicitTaskgroup;
4067 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
4069 ompLoc, allocaIP, deallocBlocks, bodyCB, loopInfo, lbVal, ubVal,
4070 stepVal, contextOp.getUntied(), ifCond, grainsize, effectiveNoGroup,
4071 sched, moduleTranslation.
lookupValue(contextOp.getFinal()),
4072 contextOp.getMergeable(),
4073 moduleTranslation.
lookupValue(contextOp.getPriority()),
4074 loopOp.getCollapseNumLoops(), taskDupOrNull,
4075 taskStructMgr.getStructPtr());
4082 builder.restoreIP(*afterIP);
4086 if (implicitTaskgroup) {
4087 llvm::OpenMPIRBuilder::LocationDescription endLoc(builder);
4088 uint32_t srcLocSize;
4089 llvm::Constant *srcLocStr =
4090 ompBuilder.getOrCreateSrcLocStr(endLoc, srcLocSize);
4091 llvm::Value *ident = ompBuilder.getOrCreateIdent(srcLocStr, srcLocSize);
4094 ompBuilder.updateToLocation(endLoc);
4095 llvm::Value *outerGtid = ompBuilder.getOrCreateThreadID(ident);
4096 llvm::FunctionCallee endTgFn = ompBuilder.getOrCreateRuntimeFunction(
4098 llvm::omp::OMPRTL___kmpc_end_taskgroup);
4099 builder.CreateCall(endTgFn, {ident, outerGtid});
4110static llvm::Function *
4113 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
4114 llvm::LLVMContext &ctx = llvmModule->getContext();
4115 llvm::Type *voidTy = llvm::Type::getVoidTy(ctx);
4116 llvm::Type *ptrTy = llvm::PointerType::getUnqual(ctx);
4117 llvm::FunctionType *fty =
4118 llvm::FunctionType::get(voidTy, {ptrTy, ptrTy},
false);
4119 llvm::Function *fn =
4120 llvm::Function::Create(fty, llvm::GlobalValue::InternalLinkage,
4121 baseName +
".red.init", llvmModule);
4122 fn->setDoesNotRecurse();
4123 fn->getArg(0)->setName(
"priv");
4124 fn->getArg(1)->setName(
"orig");
4126 llvm::BasicBlock *entry = llvm::BasicBlock::Create(ctx,
"entry", fn);
4127 llvm::IRBuilder<>
b(entry);
4134 Value moldArg = decl.getInitializerMoldArg();
4135 llvm::Value *origVal = fn->getArg(1);
4136 if (!isa<LLVM::LLVMPointerType>(moldArg.
getType()))
4138 fn->getArg(1),
"omp.orig");
4139 moduleTranslation.
mapValue(moldArg, origVal);
4142 "omp.taskred.init",
b, moduleTranslation,
4144 fn->eraseFromParent();
4147 assert(phis.size() == 1 &&
4148 "expected one value yielded from reduction initializer");
4149 b.CreateStore(phis[0], fn->getArg(0));
4152 moduleTranslation.
forgetMapping(decl.getInitializerRegion());
4160static llvm::Function *
4163 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
4164 llvm::LLVMContext &ctx = llvmModule->getContext();
4165 llvm::Type *voidTy = llvm::Type::getVoidTy(ctx);
4166 llvm::Type *ptrTy = llvm::PointerType::getUnqual(ctx);
4167 llvm::FunctionType *fty =
4168 llvm::FunctionType::get(voidTy, {ptrTy, ptrTy},
false);
4169 llvm::Function *fn =
4170 llvm::Function::Create(fty, llvm::GlobalValue::InternalLinkage,
4171 baseName +
".red.comb", llvmModule);
4172 fn->setDoesNotRecurse();
4173 fn->getArg(0)->setName(
"lhs");
4174 fn->getArg(1)->setName(
"rhs");
4176 llvm::BasicBlock *entry = llvm::BasicBlock::Create(ctx,
"entry", fn);
4177 llvm::IRBuilder<>
b(entry);
4179 llvm::Type *elemTy = moduleTranslation.
convertType(decl.getType());
4180 Block &combBlock = decl.getReductionRegion().
front();
4182 "expected two arguments in declare_reduction combiner");
4183 llvm::Value *lhsVal =
b.CreateLoad(elemTy, fn->getArg(0),
"omp.lhs");
4184 llvm::Value *rhsVal =
b.CreateLoad(elemTy, fn->getArg(1),
"omp.rhs");
4190 "omp.taskred.comb",
b, moduleTranslation,
4192 fn->eraseFromParent();
4195 assert(phis.size() == 1 &&
4196 "expected one value yielded from reduction combiner");
4197 b.CreateStore(phis[0], fn->getArg(0));
4223 llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder::InsertPointTy allocaIP,
4225 bool isWorksharing) {
4226 assert(redDecls.size() == origPtrs.size() &&
4227 "expected one orig pointer per reduction decl");
4229 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
4230 llvm::LLVMContext &ctx = llvmModule->getContext();
4231 const llvm::DataLayout &dl = llvmModule->getDataLayout();
4233 llvm::Type *ptrTy = llvm::PointerType::getUnqual(ctx);
4234 llvm::Type *i32Ty = llvm::Type::getInt32Ty(ctx);
4235 llvm::Type *sizeTy =
4236 llvm::Type::getIntNTy(ctx, dl.getPointerSizeInBits(0));
4240 llvm::StructType *redInputTy =
4241 llvm::StructType::getTypeByName(ctx,
"kmp_taskred_input_t");
4243 redInputTy = llvm::StructType::create(
4244 ctx, {ptrTy, ptrTy, sizeTy, ptrTy, ptrTy, ptrTy, i32Ty},
4245 "kmp_taskred_input_t");
4247 unsigned n = redDecls.size();
4248 llvm::ArrayType *arrTy = llvm::ArrayType::get(redInputTy, n);
4251 llvm::AllocaInst *arrAlloca;
4253 llvm::IRBuilderBase::InsertPointGuard guard(builder);
4254 builder.restoreIP(allocaIP);
4256 builder.CreateAlloca(arrTy,
nullptr,
".taskred.input");
4260 llvm::Value *zero = builder.getInt32(0);
4261 for (
unsigned i = 0; i < n; ++i) {
4262 omp::DeclareReductionOp decl = redDecls[i];
4263 llvm::Value *orig = origPtrs[i];
4264 if (
auto *origPtrTy = llvm::dyn_cast<llvm::PointerType>(orig->getType());
4265 origPtrTy && origPtrTy->getAddressSpace() != 0)
4266 orig = builder.CreateAddrSpaceCast(orig, ptrTy);
4267 llvm::Type *elemTy = moduleTranslation.
convertType(decl.getType());
4268 uint64_t size = dl.getTypeAllocSize(elemTy).getFixedValue();
4270 std::string baseName =
4271 (llvm::Twine(helperNamePrefix) + decl.getSymName()).str();
4272 llvm::Function *initFn =
4274 llvm::Function *combFn =
4276 if (!initFn || !combFn)
4278 llvm::Value *elemPtr = builder.CreateInBoundsGEP(
4279 arrTy, arrAlloca, {zero, builder.getInt32(i)},
".taskred.elem");
4280 auto storeField = [&](
unsigned fieldIdx, llvm::Value *val) {
4281 llvm::Value *fieldPtr =
4282 builder.CreateStructGEP(redInputTy, elemPtr, fieldIdx);
4283 builder.CreateStore(val, fieldPtr);
4285 storeField(0, orig);
4286 storeField(1, orig);
4287 storeField(2, llvm::ConstantInt::get(sizeTy, size));
4288 storeField(3, initFn);
4289 storeField(4, llvm::ConstantPointerNull::get(ptrTy));
4290 storeField(5, combFn);
4291 storeField(6, llvm::ConstantInt::get(i32Ty, 0));
4295 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4296 uint32_t srcLocSize;
4297 llvm::Constant *srcLocStr =
4298 ompBuilder->getOrCreateSrcLocStr(ompLoc, srcLocSize);
4299 llvm::Value *ident = ompBuilder->getOrCreateIdent(srcLocStr, srcLocSize);
4300 ompBuilder->updateToLocation(ompLoc);
4301 llvm::Value *gtid = ompBuilder->getOrCreateThreadID(ident);
4305 llvm::FunctionCallee modInit = ompBuilder->getOrCreateRuntimeFunction(
4306 *llvmModule, llvm::omp::OMPRTL___kmpc_taskred_modifier_init);
4307 return builder.CreateCall(modInit,
4309 builder.getInt32(isWorksharing ? 1 : 0),
4310 builder.getInt32(n), arrAlloca},
4314 llvm::FunctionCallee taskredInit = ompBuilder->getOrCreateRuntimeFunction(
4315 *llvmModule, llvm::omp::OMPRTL___kmpc_taskred_init);
4316 return builder.CreateCall(taskredInit, {gtid, builder.getInt32(n), arrAlloca},
4327 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
4328 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4329 uint32_t srcLocSize;
4330 llvm::Constant *srcLocStr =
4331 ompBuilder->getOrCreateSrcLocStr(ompLoc, srcLocSize);
4332 llvm::Value *ident = ompBuilder->getOrCreateIdent(srcLocStr, srcLocSize);
4333 ompBuilder->updateToLocation(ompLoc);
4334 llvm::Value *gtid = ompBuilder->getOrCreateThreadID(ident);
4335 llvm::FunctionCallee fini = ompBuilder->getOrCreateRuntimeFunction(
4336 *llvmModule, llvm::omp::OMPRTL___kmpc_task_reduction_modifier_fini);
4337 builder.CreateCall(fini,
4338 {ident, gtid, builder.getInt32(isWorksharing ? 1 : 0)});
4345 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4354 if (
auto syms = tgOp.getTaskReductionSyms()) {
4355 redDecls.reserve(syms->size());
4356 for (
auto sym : syms->getAsRange<SymbolRefAttr>()) {
4360 return tgOp.emitError()
4361 <<
"failed to resolve task_reduction declare_reduction symbol "
4362 << sym.getRootReference() <<
" in omp.taskgroup";
4363 if (decl.getInitializerRegion().front().getNumArguments() != 1)
4364 return tgOp.emitError(
"not yet implemented: task_reduction with "
4365 "two-argument initializer in omp.taskgroup");
4366 if (!decl.getCleanupRegion().empty())
4367 return tgOp.emitError(
"not yet implemented: task_reduction with "
4368 "cleanup region in omp.taskgroup");
4369 if (decl.getReductionRegion().empty())
4370 return tgOp.emitError(
"task_reduction declare_reduction is missing a "
4372 redDecls.push_back(decl);
4377 [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
4379 builder.restoreIP(codegenIP);
4381 if (!redDecls.empty()) {
4383 origPtrs.reserve(redDecls.size());
4384 for (
Value v : tgOp.getTaskReductionVars())
4385 origPtrs.push_back(moduleTranslation.
lookupValue(v));
4387 builder, allocaIP, moduleTranslation))
4388 return llvm::createStringError(
4389 llvm::inconvertibleErrorCode(),
4390 "failed to emit task_reduction initialization for omp.taskgroup");
4398 for (
auto [i, blockArg] :
4399 llvm::enumerate(tgOp.getRegion().getArguments())) {
4401 moduleTranslation.
lookupValue(tgOp.getTaskReductionVars()[i]);
4402 moduleTranslation.
mapValue(blockArg, orig);
4406 builder, moduleTranslation)
4411 InsertPointTy allocaIP =
4413 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4414 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
4416 ompLoc, allocaIP, deallocBlocks, bodyCB);
4421 builder.restoreIP(*afterIP);
4428 if (!initOp.getDependVars().empty() || initOp.getDependKinds() ||
4429 !initOp.getDependIterated().empty() || initOp.getDependIteratedKinds())
4430 return initOp.emitError()
4431 <<
"not yet implemented: Unhandled clause depend in "
4432 << omp::InteropInitOp::getOperationName() <<
" operation";
4435 llvm::Value *interopVar =
4436 moduleTranslation.
lookupValue(initOp.getInteropVar());
4437 llvm::Value *device = initOp.getDevice()
4438 ? moduleTranslation.
lookupValue(initOp.getDevice())
4442 llvm::Value *numDeps = llvm::ConstantInt::get(builder.getInt32Ty(), 0);
4443 llvm::Value *depArray = llvm::ConstantPointerNull::get(builder.getPtrTy());
4444 bool hasNowait = initOp.getNowait();
4451 bool hasTarget =
false, hasTargetSync =
false;
4453 switch (cast<omp::InteropTypeAttr>(typeAttr).getValue()) {
4454 case omp::InteropType::target:
4457 case omp::InteropType::targetsync:
4458 hasTargetSync =
true;
4462 llvm::omp::OMPInteropType interopType =
4463 (!hasTarget && hasTargetSync) ? llvm::omp::OMPInteropType::TargetSync
4464 : llvm::omp::OMPInteropType::Target;
4465 ompBuilder->createOMPInteropInit(builder, interopVar, interopType, device,
4466 numDeps, depArray, hasNowait);
4472 llvm::IRBuilderBase &builder,
4474 if (!destroyOp.getDependVars().empty() || destroyOp.getDependKinds() ||
4475 !destroyOp.getDependIterated().empty() ||
4476 destroyOp.getDependIteratedKinds())
4477 return destroyOp.emitError()
4478 <<
"not yet implemented: Unhandled clause depend in "
4479 << omp::InteropDestroyOp::getOperationName() <<
" operation";
4482 llvm::Value *interopVar =
4483 moduleTranslation.
lookupValue(destroyOp.getInteropVar());
4484 llvm::Value *device =
4485 destroyOp.getDevice()
4486 ? moduleTranslation.
lookupValue(destroyOp.getDevice())
4489 llvm::Value *numDeps = llvm::ConstantInt::get(builder.getInt32Ty(), 0);
4490 llvm::Value *depArray = llvm::ConstantPointerNull::get(builder.getPtrTy());
4491 bool hasNowait = destroyOp.getNowait();
4493 ompBuilder->createOMPInteropDestroy(builder, interopVar, device, numDeps,
4494 depArray, hasNowait);
4501 if (!useOp.getDependVars().empty() || useOp.getDependKinds() ||
4502 !useOp.getDependIterated().empty() || useOp.getDependIteratedKinds())
4503 return useOp.emitError()
4504 <<
"not yet implemented: Unhandled clause depend in "
4505 << omp::InteropUseOp::getOperationName() <<
" operation";
4508 llvm::Value *interopVar =
4509 moduleTranslation.
lookupValue(useOp.getInteropVar());
4510 llvm::Value *device = useOp.getDevice()
4511 ? moduleTranslation.
lookupValue(useOp.getDevice())
4514 llvm::Value *numDeps = llvm::ConstantInt::get(builder.getInt32Ty(), 0);
4515 llvm::Value *depArray = llvm::ConstantPointerNull::get(builder.getPtrTy());
4516 bool hasNowait = useOp.getNowait();
4518 ompBuilder->createOMPInteropUse(builder, interopVar, device, numDeps,
4519 depArray, hasNowait);
4529 llvm::OpenMPIRBuilder::DependenciesInfo dds;
4531 twOp.getDependVars(), twOp.getDependKinds(), twOp.getDependIterated(),
4532 twOp.getDependIteratedKinds(), builder, moduleTranslation, dds))) {
4538 builder.CreateFree(dds.DepArray);
4549 auto wsloopOp = cast<omp::WsloopOp>(opInst);
4553 auto loopOp = cast<omp::LoopNestOp>(wsloopOp.getWrappedLoop());
4555 assert(isByRef.size() == wsloopOp.getNumReductionVars());
4559 wsloopOp.getScheduleKind().value_or(omp::ClauseScheduleKind::Static);
4562 llvm::Value *step = moduleTranslation.
lookupValue(loopOp.getLoopSteps()[0]);
4563 llvm::Type *ivType = step->getType();
4564 llvm::Value *chunk =
nullptr;
4565 if (wsloopOp.getScheduleChunk()) {
4566 llvm::Value *chunkVar =
4567 moduleTranslation.
lookupValue(wsloopOp.getScheduleChunk());
4568 chunk = builder.CreateSExtOrTrunc(chunkVar, ivType);
4571 omp::DistributeOp distributeOp =
nullptr;
4572 llvm::Value *distScheduleChunk =
nullptr;
4573 bool hasDistSchedule =
false;
4574 if (llvm::isa_and_present<omp::DistributeOp>(opInst.
getParentOp())) {
4575 distributeOp = cast<omp::DistributeOp>(opInst.
getParentOp());
4576 hasDistSchedule = distributeOp.getDistScheduleStatic();
4577 if (distributeOp.getDistScheduleChunkSize()) {
4578 llvm::Value *chunkVar = moduleTranslation.
lookupValue(
4579 distributeOp.getDistScheduleChunkSize());
4580 distScheduleChunk = builder.CreateSExtOrTrunc(chunkVar, ivType);
4589 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
4593 wsloopOp.getNumReductionVars());
4596 wsloopOp, builder, moduleTranslation, privateVarsInfo, allocaIP);
4603 cast<omp::BlockArgOpenMPOpInterface>(opInst).getReductionBlockArgs();
4608 moduleTranslation, allocaIP, reductionDecls,
4609 privateReductionVariables, reductionVariableMap,
4610 deferredStores, isByRef)))
4619 wsloopOp, builder, moduleTranslation, privateVarsInfo.
mlirVars,
4621 wsloopOp.getPrivateNeedsBarrier())))
4624 assert(afterAllocas.get()->getSinglePredecessor());
4625 if (failed(initReductionVars(wsloopOp, reductionArgs, builder,
4627 afterAllocas.get()->getSinglePredecessor(),
4628 reductionDecls, privateReductionVariables,
4629 reductionVariableMap, isByRef, deferredStores)))
4635 bool isTaskReductionMod =
4636 wsloopOp.getReductionMod() == omp::ReductionModifier::task &&
4637 wsloopOp.getNumReductionVars() > 0;
4638 if (isTaskReductionMod &&
4640 "__omp_taskred_mod_", builder, allocaIP,
4641 moduleTranslation,
true,
4643 return wsloopOp.emitError(
4644 "failed to emit task reduction modifier initialization");
4647 bool isOrdered = wsloopOp.getOrdered().has_value();
4648 std::optional<omp::ScheduleModifier> scheduleMod = wsloopOp.getScheduleMod();
4649 bool isSimd = wsloopOp.getScheduleSimd();
4650 bool loopNeedsBarrier = !wsloopOp.getNowait();
4655 llvm::omp::WorksharingLoopType workshareLoopType =
4656 llvm::isa_and_present<omp::DistributeOp>(opInst.
getParentOp())
4657 ? llvm::omp::WorksharingLoopType::DistributeForStaticLoop
4658 : llvm::omp::WorksharingLoopType::ForStaticLoop;
4662 llvm::omp::Directive::OMPD_for);
4664 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4667 LinearClauseProcessor linearClauseProcessor;
4669 if (!wsloopOp.getLinearVars().empty()) {
4670 auto linearVarTypes = wsloopOp.getLinearVarTypes().value();
4672 linearClauseProcessor.registerType(moduleTranslation, linearVarType);
4674 for (
auto [idx, linearVar] : llvm::enumerate(wsloopOp.getLinearVars()))
4675 linearClauseProcessor.createLinearVar(
4676 builder, moduleTranslation, moduleTranslation.
lookupValue(linearVar),
4678 for (
mlir::Value linearStep : wsloopOp.getLinearStepVars())
4679 linearClauseProcessor.initLinearStep(moduleTranslation, linearStep);
4683 wsloopOp.getRegion(),
"omp.wsloop.region", builder, moduleTranslation);
4691 if (!wsloopOp.getLinearVars().empty()) {
4692 linearClauseProcessor.initLinearVar(builder, moduleTranslation,
4693 loopInfo->getPreheader());
4694 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterBarrierIP =
4696 builder, llvm::omp::OMPD_barrier);
4699 builder.restoreIP(*afterBarrierIP);
4700 linearClauseProcessor.updateLinearVar(builder, loopInfo->getBody(),
4701 loopInfo->getIndVar());
4702 linearClauseProcessor.splitLinearFiniBB(builder, loopInfo->getExit());
4705 builder.SetInsertPoint(*regionBlock, (*regionBlock)->begin());
4708 bool noLoopMode =
false;
4709 omp::TargetOp targetOp = wsloopOp->getParentOfType<mlir::omp::TargetOp>();
4711 targetOp.getKernelType() == omp::TargetExecMode::spmd_no_loop) {
4713 cast<omp::ComposableOpInterface>(*targetOp).findCapturedOp();
4717 if (loopOp == targetCapturedOp)
4721 for (
size_t index = 0;
index < wsloopOp.getLinearVars().size();
index++)
4722 linearClauseProcessor.rewriteInPlace(builder, loopInfo->getBody(),
4723 loopInfo->getLatch(),
index);
4725 llvm::OpenMPIRBuilder::InsertPointOrErrorTy wsloopIP =
4726 ompBuilder->applyWorkshareLoop(
4727 ompLoc.DL, loopInfo, allocaIP, loopNeedsBarrier,
4728 convertToScheduleKind(schedule), chunk, isSimd,
4729 scheduleMod == omp::ScheduleModifier::monotonic,
4730 scheduleMod == omp::ScheduleModifier::nonmonotonic, isOrdered,
4731 workshareLoopType, noLoopMode, hasDistSchedule, distScheduleChunk);
4737 if (!wsloopOp.getLinearVars().empty()) {
4738 llvm::OpenMPIRBuilder::InsertPointTy oldIP = builder.saveIP();
4739 assert(loopInfo->getLastIter() &&
4740 "`lastiter` in CanonicalLoopInfo is nullptr");
4741 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterBarrierIP =
4742 linearClauseProcessor.finalizeLinearVar(builder, moduleTranslation,
4743 loopInfo->getLastIter());
4747 builder.restoreIP(oldIP);
4754 if (isTaskReductionMod)
4760 wsloopOp, builder, moduleTranslation, allocaIP, reductionDecls,
4761 privateReductionVariables, isByRef, wsloopOp.getNowait(),
4766 wsloopOp.getLoc(), privateVarsInfo);
4773 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4775 assert(isByRef.size() == opInst.getNumReductionVars());
4788 opInst.getNumReductionVars());
4794 bool isTaskReductionMod =
4795 opInst.getReductionMod() == omp::ReductionModifier::task &&
4796 opInst.getNumReductionVars() > 0;
4799 [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
4802 opInst, builder, moduleTranslation, privateVarsInfo, allocaIP);
4804 return llvm::make_error<PreviouslyReportedError>();
4810 cast<omp::BlockArgOpenMPOpInterface>(*opInst).getReductionBlockArgs();
4813 InsertPointTy(allocaIP.getBlock(),
4814 allocaIP.getBlock()->getTerminator()->getIterator());
4817 opInst, reductionArgs, builder, moduleTranslation, allocaIP,
4818 reductionDecls, privateReductionVariables, reductionVariableMap,
4819 deferredStores, isByRef)))
4820 return llvm::make_error<PreviouslyReportedError>();
4822 assert(afterAllocas.get()->getSinglePredecessor());
4823 builder.restoreIP(codeGenIP);
4829 return llvm::make_error<PreviouslyReportedError>();
4832 opInst, builder, moduleTranslation, privateVarsInfo.
mlirVars,
4834 opInst.getPrivateNeedsBarrier())))
4835 return llvm::make_error<PreviouslyReportedError>();
4838 initReductionVars(opInst, reductionArgs, builder, moduleTranslation,
4839 afterAllocas.get()->getSinglePredecessor(),
4840 reductionDecls, privateReductionVariables,
4841 reductionVariableMap, isByRef, deferredStores)))
4842 return llvm::make_error<PreviouslyReportedError>();
4847 if (isTaskReductionMod &&
4849 "__omp_taskred_mod_", builder, allocaIP,
4850 moduleTranslation,
true,
4852 return llvm::createStringError(
4853 "failed to emit task reduction modifier initialization");
4858 moduleTranslation, allocaIP, deallocBlocks);
4862 opInst.getRegion(),
"omp.par.region", builder, moduleTranslation);
4864 return regionBlock.takeError();
4867 if (opInst.getNumReductionVars() > 0) {
4872 owningReductionGenRefDataPtrGens;
4874 collectReductionInfo(opInst, builder, moduleTranslation, reductionDecls,
4876 owningReductionGenRefDataPtrGens,
4877 privateReductionVariables, reductionInfos, isByRef);
4880 builder.SetInsertPoint((*regionBlock)->getTerminator());
4884 if (isTaskReductionMod)
4889 llvm::UnreachableInst *tempTerminator = builder.CreateUnreachable();
4890 builder.SetInsertPoint(tempTerminator);
4892 llvm::OpenMPIRBuilder::InsertPointOrErrorTy contInsertPoint =
4893 ompBuilder->createReductions(builder, allocaIP, reductionInfos,
4897 if (!contInsertPoint)
4898 return contInsertPoint.takeError();
4900 if (!contInsertPoint->getBlock())
4901 return llvm::make_error<PreviouslyReportedError>();
4903 tempTerminator->eraseFromParent();
4904 builder.restoreIP(*contInsertPoint);
4907 return llvm::Error::success();
4910 auto privCB = [](InsertPointTy allocaIP, InsertPointTy codeGenIP,
4911 llvm::Value &, llvm::Value &val, llvm::Value *&replVal) {
4920 auto finiCB = [&](InsertPointTy codeGenIP) -> llvm::Error {
4921 InsertPointTy oldIP = builder.saveIP();
4922 builder.restoreIP(codeGenIP);
4927 llvm::transform(reductionDecls, std::back_inserter(reductionCleanupRegions),
4928 [](omp::DeclareReductionOp reductionDecl) {
4929 return &reductionDecl.getCleanupRegion();
4932 reductionCleanupRegions, privateReductionVariables,
4933 moduleTranslation, builder,
"omp.reduction.cleanup")))
4934 return llvm::createStringError(
4935 "failed to inline `cleanup` region of `omp.declare_reduction`");
4938 opInst.getLoc(), privateVarsInfo)))
4939 return llvm::make_error<PreviouslyReportedError>();
4943 if (isCancellable) {
4944 auto IPOrErr = ompBuilder->createBarrier(
4945 llvm::OpenMPIRBuilder::LocationDescription(builder),
4946 llvm::omp::Directive::OMPD_unknown,
4950 return IPOrErr.takeError();
4953 builder.restoreIP(oldIP);
4954 return llvm::Error::success();
4957 llvm::Value *ifCond =
nullptr;
4958 if (
auto ifVar = opInst.getIfExpr())
4960 llvm::Value *numThreads =
nullptr;
4961 if (!opInst.getNumThreadsVars().empty())
4962 numThreads = moduleTranslation.
lookupValue(opInst.getNumThreads(0));
4963 auto pbKind = llvm::omp::OMP_PROC_BIND_default;
4964 if (
auto bind = opInst.getProcBindKind())
4968 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
4970 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4972 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
4973 ompBuilder->createParallel(ompLoc, allocaIP, deallocBlocks, bodyGenCB,
4974 privCB, finiCB, ifCond, numThreads, pbKind,
4980 builder.restoreIP(*afterIP);
4985static llvm::omp::OrderKind
4988 return llvm::omp::OrderKind::OMP_ORDER_unknown;
4990 case omp::ClauseOrderKind::Concurrent:
4991 return llvm::omp::OrderKind::OMP_ORDER_concurrent;
4993 llvm_unreachable(
"Unknown ClauseOrderKind kind");
5001 auto simdOp = cast<omp::SimdOp>(opInst);
5009 cast<omp::BlockArgOpenMPOpInterface>(opInst).getReductionBlockArgs();
5012 simdOp.getNumReductionVars());
5017 assert(isByRef.size() == simdOp.getNumReductionVars());
5019 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
5023 simdOp, builder, moduleTranslation, privateVarsInfo, allocaIP);
5028 LinearClauseProcessor linearClauseProcessor;
5029 if (linearClauseProcessor.initLinearIV(simdOp).failed())
5032 if (!simdOp.getLinearVars().empty()) {
5033 auto linearVarTypes = simdOp.getLinearVarTypes().value();
5035 linearClauseProcessor.registerType(moduleTranslation, linearVarType);
5036 for (
auto [idx, linearVar] : llvm::enumerate(simdOp.getLinearVars())) {
5037 bool isImplicit =
false;
5038 for (
auto [mlirPrivVar, llvmPrivateVar] : llvm::zip_equal(
5042 if (linearVar == mlirPrivVar) {
5044 linearClauseProcessor.createLinearVar(builder, moduleTranslation,
5045 llvmPrivateVar, idx);
5051 linearClauseProcessor.createLinearVar(
5052 builder, moduleTranslation,
5055 for (
mlir::Value linearStep : simdOp.getLinearStepVars())
5056 linearClauseProcessor.initLinearStep(moduleTranslation, linearStep);
5060 moduleTranslation, allocaIP, reductionDecls,
5061 privateReductionVariables, reductionVariableMap,
5062 deferredStores, isByRef)))
5073 assert(afterAllocas.get()->getSinglePredecessor());
5074 if (failed(initReductionVars(simdOp, reductionArgs, builder,
5076 afterAllocas.get()->getSinglePredecessor(),
5077 reductionDecls, privateReductionVariables,
5078 reductionVariableMap, isByRef, deferredStores)))
5081 llvm::ConstantInt *simdlen =
nullptr;
5082 if (std::optional<uint64_t> simdlenVar = simdOp.getSimdlen())
5083 simdlen = builder.getInt64(simdlenVar.value());
5085 llvm::ConstantInt *safelen =
nullptr;
5086 if (std::optional<uint64_t> safelenVar = simdOp.getSafelen())
5087 safelen = builder.getInt64(safelenVar.value());
5089 llvm::MapVector<llvm::Value *, llvm::Value *> alignedVars;
5092 llvm::BasicBlock *sourceBlock = builder.GetInsertBlock();
5093 std::optional<ArrayAttr> alignmentValues = simdOp.getAlignments();
5095 for (
size_t i = 0; i < operands.size(); ++i) {
5096 llvm::Value *alignment =
nullptr;
5097 llvm::Value *llvmVal = moduleTranslation.
lookupValue(operands[i]);
5098 llvm::Type *ty = llvmVal->getType();
5100 auto intAttr = cast<IntegerAttr>((*alignmentValues)[i]);
5101 alignment = builder.getInt64(intAttr.getInt());
5102 assert(ty->isPointerTy() &&
"Invalid type for aligned variable");
5103 assert(alignment &&
"Invalid alignment value");
5107 if (!intAttr.getValue().isPowerOf2())
5110 auto curInsert = builder.saveIP();
5111 builder.SetInsertPoint(sourceBlock);
5112 llvmVal = builder.CreateLoad(ty, llvmVal);
5113 builder.restoreIP(curInsert);
5114 alignedVars[llvmVal] = alignment;
5118 simdOp.getRegion(),
"omp.simd.region", builder, moduleTranslation);
5125 if (simdOp.getLinearVars().size()) {
5126 linearClauseProcessor.initLinearVar(builder, moduleTranslation,
5127 loopInfo->getPreheader());
5129 linearClauseProcessor.updateLinearVar(builder, loopInfo->getBody(),
5130 loopInfo->getIndVar());
5132 builder.SetInsertPoint(*regionBlock, (*regionBlock)->begin());
5134 for (
size_t index = 0;
index < simdOp.getLinearVars().size();
index++)
5135 linearClauseProcessor.rewriteInPlace(builder, loopInfo->getBody(),
5136 loopInfo->getLatch(),
index);
5138 ompBuilder->applySimd(loopInfo, alignedVars,
5140 ? moduleTranslation.
lookupValue(simdOp.getIfExpr())
5142 order, simdlen, safelen);
5144 linearClauseProcessor.updateLinearIV(builder, moduleTranslation);
5145 linearClauseProcessor.emitStoresForLinearVar(builder);
5151 for (
auto [i, tuple] : llvm::enumerate(
5152 llvm::zip(reductionDecls, isByRef, simdOp.getReductionVars(),
5153 privateReductionVariables))) {
5154 auto [decl, byRef, reductionVar, privateReductionVar] = tuple;
5156 OwningReductionGen gen =
makeReductionGen(decl, builder, moduleTranslation);
5157 llvm::Value *originalVariable = moduleTranslation.
lookupValue(reductionVar);
5158 llvm::Type *reductionType = moduleTranslation.
convertType(decl.getType());
5162 llvm::Value *redValue = originalVariable;
5165 builder.CreateLoad(reductionType, redValue,
"red.value." + Twine(i));
5166 llvm::Value *privateRedValue = builder.CreateLoad(
5167 reductionType, privateReductionVar,
"red.private.value." + Twine(i));
5168 llvm::Value *reduced;
5170 auto res = gen(builder.saveIP(), redValue, privateRedValue, reduced);
5173 builder.restoreIP(res.get());
5177 builder.CreateStore(reduced, originalVariable);
5182 llvm::transform(reductionDecls, std::back_inserter(reductionRegions),
5183 [](omp::DeclareReductionOp reductionDecl) {
5184 return &reductionDecl.getCleanupRegion();
5187 moduleTranslation, builder,
5188 "omp.reduction.cleanup")))
5200 auto loopOp = cast<omp::LoopNestOp>(opInst);
5206 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5211 auto bodyGen = [&](llvm::OpenMPIRBuilder::InsertPointTy ip,
5212 llvm::Value *iv) -> llvm::Error {
5215 loopOp.getRegion().front().getArgument(loopInfos.size()), iv);
5220 bodyInsertPoints.push_back(ip);
5222 if (loopInfos.size() != loopOp.getNumLoops() - 1)
5223 return llvm::Error::success();
5226 builder.restoreIP(ip);
5228 loopOp.getRegion(),
"omp.loop_nest.region", builder, moduleTranslation);
5230 return regionBlock.takeError();
5232 builder.SetInsertPoint(*regionBlock, (*regionBlock)->begin());
5233 return llvm::Error::success();
5241 for (
unsigned i = 0, e = loopOp.getNumLoops(); i < e; ++i) {
5242 llvm::Value *lowerBound =
5243 moduleTranslation.
lookupValue(loopOp.getLoopLowerBounds()[i]);
5244 llvm::Value *upperBound =
5245 moduleTranslation.
lookupValue(loopOp.getLoopUpperBounds()[i]);
5246 llvm::Value *step = moduleTranslation.
lookupValue(loopOp.getLoopSteps()[i]);
5251 llvm::OpenMPIRBuilder::LocationDescription loc = ompLoc;
5252 llvm::OpenMPIRBuilder::InsertPointTy computeIP = ompLoc.IP;
5254 loc = llvm::OpenMPIRBuilder::LocationDescription(bodyInsertPoints.back(),
5256 computeIP = loopInfos.front()->getPreheaderIP();
5260 ompBuilder->createCanonicalLoop(
5261 loc, bodyGen, lowerBound, upperBound, step,
5262 true, loopOp.getLoopInclusive(), computeIP);
5267 loopInfos.push_back(*loopResult);
5270 llvm::OpenMPIRBuilder::InsertPointTy afterIP =
5271 loopInfos.front()->getAfterIP();
5274 if (
const auto &tiles = loopOp.getTileSizes()) {
5275 llvm::Type *ivType = loopInfos.front()->getIndVarType();
5278 for (
auto tile : tiles.value()) {
5279 llvm::Value *tileVal = llvm::ConstantInt::get(ivType,
tile);
5280 tileSizes.push_back(tileVal);
5283 std::vector<llvm::CanonicalLoopInfo *> newLoops =
5284 ompBuilder->tileLoops(ompLoc.DL, loopInfos, tileSizes);
5288 llvm::BasicBlock *afterBB = newLoops.front()->getAfter();
5289 llvm::BasicBlock *afterAfterBB = afterBB->getSingleSuccessor();
5290 afterIP = {afterAfterBB, afterAfterBB->begin()};
5294 for (
const auto &newLoop : newLoops)
5295 loopInfos.push_back(newLoop);
5299 const auto &numCollapse = loopOp.getCollapseNumLoops();
5301 loopInfos.begin(), loopInfos.begin() + (numCollapse));
5303 auto newTopLoopInfo =
5304 ompBuilder->collapseLoops(ompLoc.DL, collapseLoopInfos, {});
5306 assert(newTopLoopInfo &&
"New top loop information is missing");
5307 moduleTranslation.
stackWalk<OpenMPLoopInfoStackFrame>(
5308 [&](OpenMPLoopInfoStackFrame &frame) {
5309 frame.loopInfo = newTopLoopInfo;
5317 builder.restoreIP(afterIP);
5327 llvm::OpenMPIRBuilder::LocationDescription loopLoc(builder);
5328 Value loopIV = op.getInductionVar();
5329 Value loopTC = op.getTripCount();
5331 llvm::Value *llvmTC = moduleTranslation.
lookupValue(loopTC);
5334 ompBuilder->createCanonicalLoop(
5336 [&](llvm::OpenMPIRBuilder::InsertPointTy ip, llvm::Value *llvmIV) {
5339 moduleTranslation.
mapValue(loopIV, llvmIV);
5341 builder.restoreIP(ip);
5346 return bodyGenStatus.takeError();
5348 llvmTC,
"omp.loop");
5350 return op.emitError(llvm::toString(llvmOrError.takeError()));
5352 llvm::CanonicalLoopInfo *llvmCLI = *llvmOrError;
5353 llvm::IRBuilderBase::InsertPoint afterIP = llvmCLI->getAfterIP();
5354 builder.restoreIP(afterIP);
5357 if (
Value cli = op.getCli())
5370 Value applyee = op.getApplyee();
5371 assert(applyee &&
"Loop to apply unrolling on required");
5373 llvm::CanonicalLoopInfo *consBuilderCLI =
5375 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
5376 ompBuilder->unrollLoopHeuristic(loc.DL, consBuilderCLI);
5389 Value applyee = op.getApplyee();
5390 assert(applyee &&
"Loop to apply unrolling on required");
5392 llvm::CanonicalLoopInfo *consBuilderCLI =
5394 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
5398 int32_t factor =
static_cast<int32_t
>(op.getUnrollFactor());
5399 ompBuilder->unrollLoopPartial(loc.DL, consBuilderCLI, factor,
5408static LogicalResult
applyTile(omp::TileOp op, llvm::IRBuilderBase &builder,
5411 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
5416 for (
Value size : op.getSizes()) {
5417 llvm::Value *translatedSize = moduleTranslation.
lookupValue(size);
5418 assert(translatedSize &&
5419 "sizes clause arguments must already be translated");
5420 translatedSizes.push_back(translatedSize);
5423 for (
Value applyee : op.getApplyees()) {
5424 llvm::CanonicalLoopInfo *consBuilderCLI =
5426 assert(applyee &&
"Canonical loop must already been translated");
5427 translatedLoops.push_back(consBuilderCLI);
5430 auto generatedLoops =
5431 ompBuilder->tileLoops(loc.DL, translatedLoops, translatedSizes);
5432 if (!op.getGeneratees().empty()) {
5433 for (
auto [mlirLoop,
genLoop] :
5434 zip_equal(op.getGeneratees(), generatedLoops))
5439 for (
Value applyee : op.getApplyees())
5447static LogicalResult
applyFuse(omp::FuseOp op, llvm::IRBuilderBase &builder,
5450 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
5454 for (
size_t i = 0; i < op.getApplyees().size(); i++) {
5455 Value applyee = op.getApplyees()[i];
5456 llvm::CanonicalLoopInfo *consBuilderCLI =
5458 assert(applyee &&
"Canonical loop must already been translated");
5459 if (op.getFirst().has_value() && i < op.getFirst().value() - 1)
5460 beforeFuse.push_back(consBuilderCLI);
5461 else if (op.getCount().has_value() &&
5462 i >= op.getFirst().value() + op.getCount().value() - 1)
5463 afterFuse.push_back(consBuilderCLI);
5465 toFuse.push_back(consBuilderCLI);
5468 (op.getGeneratees().empty() ||
5469 beforeFuse.size() + afterFuse.size() + 1 == op.getGeneratees().size()) &&
5470 "Wrong number of generatees");
5473 auto generatedLoop = ompBuilder->fuseLoops(loc.DL, toFuse);
5474 if (!op.getGeneratees().empty()) {
5476 for (; i < beforeFuse.size(); i++)
5477 moduleTranslation.
mapOmpLoop(op.getGeneratees()[i], beforeFuse[i]);
5478 moduleTranslation.
mapOmpLoop(op.getGeneratees()[i++], generatedLoop);
5479 for (; i < afterFuse.size(); i++)
5480 moduleTranslation.
mapOmpLoop(op.getGeneratees()[i], afterFuse[i]);
5484 for (
Value applyee : op.getApplyees())
5491static llvm::AtomicOrdering
5494 return llvm::AtomicOrdering::Monotonic;
5497 case omp::ClauseMemoryOrderKind::Seq_cst:
5498 return llvm::AtomicOrdering::SequentiallyConsistent;
5499 case omp::ClauseMemoryOrderKind::Acq_rel:
5500 return llvm::AtomicOrdering::AcquireRelease;
5501 case omp::ClauseMemoryOrderKind::Acquire:
5502 return llvm::AtomicOrdering::Acquire;
5503 case omp::ClauseMemoryOrderKind::Release:
5504 return llvm::AtomicOrdering::Release;
5505 case omp::ClauseMemoryOrderKind::Relaxed:
5506 return llvm::AtomicOrdering::Monotonic;
5508 llvm_unreachable(
"Unknown ClauseMemoryOrderKind kind");
5515 auto readOp = cast<omp::AtomicReadOp>(opInst);
5520 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
5523 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5526 llvm::Value *x = moduleTranslation.
lookupValue(readOp.getX());
5527 llvm::Value *v = moduleTranslation.
lookupValue(readOp.getV());
5529 llvm::Type *elementType =
5530 moduleTranslation.
convertType(readOp.getElementType());
5532 llvm::OpenMPIRBuilder::AtomicOpValue V = {v, elementType,
false,
false};
5533 llvm::OpenMPIRBuilder::AtomicOpValue X = {x, elementType,
false,
false};
5534 builder.restoreIP(ompBuilder->createAtomicRead(ompLoc, X, V, AO, allocaIP));
5542 auto writeOp = cast<omp::AtomicWriteOp>(opInst);
5547 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
5550 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5552 llvm::Value *expr = moduleTranslation.
lookupValue(writeOp.getExpr());
5553 llvm::Value *dest = moduleTranslation.
lookupValue(writeOp.getX());
5554 llvm::Type *ty = moduleTranslation.
convertType(writeOp.getExpr().getType());
5555 llvm::OpenMPIRBuilder::AtomicOpValue x = {dest, ty,
false,
5558 ompBuilder->createAtomicWrite(ompLoc, x, expr, ao, allocaIP));
5566 .Case([&](LLVM::AddOp) {
return llvm::AtomicRMWInst::BinOp::Add; })
5567 .Case([&](LLVM::SubOp) {
return llvm::AtomicRMWInst::BinOp::Sub; })
5568 .Case([&](LLVM::AndOp) {
return llvm::AtomicRMWInst::BinOp::And; })
5569 .Case([&](LLVM::OrOp) {
return llvm::AtomicRMWInst::BinOp::Or; })
5570 .Case([&](LLVM::XOrOp) {
return llvm::AtomicRMWInst::BinOp::Xor; })
5571 .Case([&](LLVM::UMaxOp) {
return llvm::AtomicRMWInst::BinOp::UMax; })
5572 .Case([&](LLVM::UMinOp) {
return llvm::AtomicRMWInst::BinOp::UMin; })
5573 .Case([&](LLVM::FAddOp) {
return llvm::AtomicRMWInst::BinOp::FAdd; })
5574 .Case([&](LLVM::FSubOp) {
return llvm::AtomicRMWInst::BinOp::FSub; })
5575 .Default(llvm::AtomicRMWInst::BinOp::BAD_BINOP);
5579 bool &isIgnoreDenormalMode,
5580 bool &isFineGrainedMemory,
5581 bool &isRemoteMemory) {
5582 isIgnoreDenormalMode =
false;
5583 isFineGrainedMemory =
false;
5584 isRemoteMemory =
false;
5585 if (atomicUpdateOp &&
5586 atomicUpdateOp->hasAttr(atomicUpdateOp.getAtomicControlAttrName())) {
5587 mlir::omp::AtomicControlAttr atomicControlAttr =
5588 atomicUpdateOp.getAtomicControlAttr();
5589 isIgnoreDenormalMode = atomicControlAttr.getIgnoreDenormalMode();
5590 isFineGrainedMemory = atomicControlAttr.getFineGrainedMemory();
5591 isRemoteMemory = atomicControlAttr.getRemoteMemory();
5598 llvm::IRBuilderBase &builder,
5605 auto &innerOpList = opInst.getRegion().front().getOperations();
5606 bool isXBinopExpr{
false};
5607 llvm::AtomicRMWInst::BinOp binop;
5609 llvm::Value *llvmExpr =
nullptr;
5610 llvm::Value *llvmX =
nullptr;
5611 llvm::Type *llvmXElementType =
nullptr;
5612 if (innerOpList.size() == 2) {
5618 opInst.getRegion().getArgument(0))) {
5619 return opInst.emitError(
"no atomic update operation with region argument"
5620 " as operand found inside atomic.update region");
5623 isXBinopExpr = innerOp.
getOperand(0) == opInst.getRegion().getArgument(0);
5625 llvmExpr = moduleTranslation.
lookupValue(mlirExpr);
5629 binop = llvm::AtomicRMWInst::BinOp::BAD_BINOP;
5631 llvmX = moduleTranslation.
lookupValue(opInst.getX());
5633 opInst.getRegion().getArgument(0).getType());
5634 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {llvmX, llvmXElementType,
5638 llvm::AtomicOrdering atomicOrdering =
5643 [&opInst, &moduleTranslation](
5644 llvm::Value *atomicx,
5647 moduleTranslation.
mapValue(*opInst.getRegion().args_begin(), atomicx);
5648 moduleTranslation.
mapBlock(&bb, builder.GetInsertBlock());
5649 if (failed(moduleTranslation.
convertBlock(bb,
true, builder)))
5650 return llvm::make_error<PreviouslyReportedError>();
5652 omp::YieldOp yieldop = dyn_cast<omp::YieldOp>(bb.
getTerminator());
5653 assert(yieldop && yieldop.getResults().size() == 1 &&
5654 "terminator must be omp.yield op and it must have exactly one "
5656 return moduleTranslation.
lookupValue(yieldop.getResults()[0]);
5659 bool isIgnoreDenormalMode;
5660 bool isFineGrainedMemory;
5661 bool isRemoteMemory;
5666 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5667 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
5668 ompBuilder->createAtomicUpdate(ompLoc, allocaIP, llvmAtomicX, llvmExpr,
5669 atomicOrdering, binop, updateFn,
5670 isXBinopExpr, isIgnoreDenormalMode,
5671 isFineGrainedMemory, isRemoteMemory);
5676 builder.restoreIP(*afterIP);
5682 llvm::IRBuilderBase &builder,
5689 bool isXBinopExpr =
false, isPostfixUpdate =
false;
5690 llvm::AtomicRMWInst::BinOp binop = llvm::AtomicRMWInst::BinOp::BAD_BINOP;
5692 omp::AtomicUpdateOp atomicUpdateOp = atomicCaptureOp.getAtomicUpdateOp();
5693 omp::AtomicWriteOp atomicWriteOp = atomicCaptureOp.getAtomicWriteOp();
5695 assert((atomicUpdateOp || atomicWriteOp) &&
5696 "internal op must be an atomic.update or atomic.write op");
5698 if (atomicWriteOp) {
5699 isPostfixUpdate =
true;
5700 mlirExpr = atomicWriteOp.getExpr();
5702 isPostfixUpdate = atomicCaptureOp.getSecondOp() ==
5703 atomicCaptureOp.getAtomicUpdateOp().getOperation();
5704 auto &innerOpList = atomicUpdateOp.getRegion().front().getOperations();
5707 if (innerOpList.size() == 2) {
5710 atomicUpdateOp.getRegion().getArgument(0))) {
5711 return atomicUpdateOp.emitError(
5712 "no atomic update operation with region argument"
5713 " as operand found inside atomic.update region");
5717 innerOp.
getOperand(0) == atomicUpdateOp.getRegion().getArgument(0);
5720 binop = llvm::AtomicRMWInst::BinOp::BAD_BINOP;
5724 llvm::Value *llvmExpr = moduleTranslation.
lookupValue(mlirExpr);
5725 llvm::Value *llvmX =
5726 moduleTranslation.
lookupValue(atomicCaptureOp.getAtomicReadOp().getX());
5727 llvm::Value *llvmV =
5728 moduleTranslation.
lookupValue(atomicCaptureOp.getAtomicReadOp().getV());
5729 llvm::Type *llvmXElementType = moduleTranslation.
convertType(
5730 atomicCaptureOp.getAtomicReadOp().getElementType());
5731 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {llvmX, llvmXElementType,
5734 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicV = {llvmV, llvmXElementType,
5738 llvm::AtomicOrdering atomicOrdering =
5742 [&](llvm::Value *atomicx,
5745 return moduleTranslation.
lookupValue(atomicWriteOp.getExpr());
5746 Block &bb = *atomicUpdateOp.getRegion().
begin();
5747 moduleTranslation.
mapValue(*atomicUpdateOp.getRegion().args_begin(),
5749 moduleTranslation.
mapBlock(&bb, builder.GetInsertBlock());
5750 if (failed(moduleTranslation.
convertBlock(bb,
true, builder)))
5751 return llvm::make_error<PreviouslyReportedError>();
5753 omp::YieldOp yieldop = dyn_cast<omp::YieldOp>(bb.
getTerminator());
5754 assert(yieldop && yieldop.getResults().size() == 1 &&
5755 "terminator must be omp.yield op and it must have exactly one "
5757 return moduleTranslation.
lookupValue(yieldop.getResults()[0]);
5760 bool isIgnoreDenormalMode;
5761 bool isFineGrainedMemory;
5762 bool isRemoteMemory;
5764 isFineGrainedMemory, isRemoteMemory);
5767 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5768 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
5769 ompBuilder->createAtomicCapture(
5770 ompLoc, allocaIP, llvmAtomicX, llvmAtomicV, llvmExpr, atomicOrdering,
5771 binop, updateFn, atomicUpdateOp, isPostfixUpdate, isXBinopExpr,
5772 isIgnoreDenormalMode, isFineGrainedMemory, isRemoteMemory);
5774 if (failed(
handleError(afterIP, *atomicCaptureOp)))
5777 builder.restoreIP(*afterIP);
5783static std::optional<llvm::omp::OMPAtomicCompareOp>
5785 switch (predicate) {
5786 case LLVM::ICmpPredicate::eq:
5787 return llvm::omp::OMPAtomicCompareOp::EQ;
5788 case LLVM::ICmpPredicate::slt:
5789 case LLVM::ICmpPredicate::ult:
5790 return llvm::omp::OMPAtomicCompareOp::MIN;
5791 case LLVM::ICmpPredicate::sgt:
5792 case LLVM::ICmpPredicate::ugt:
5793 return llvm::omp::OMPAtomicCompareOp::MAX;
5795 return std::nullopt;
5801static std::optional<llvm::omp::OMPAtomicCompareOp>
5803 switch (predicate) {
5804 case LLVM::FCmpPredicate::oeq:
5805 case LLVM::FCmpPredicate::ueq:
5806 return llvm::omp::OMPAtomicCompareOp::EQ;
5807 case LLVM::FCmpPredicate::olt:
5808 case LLVM::FCmpPredicate::ult:
5809 return llvm::omp::OMPAtomicCompareOp::MIN;
5810 case LLVM::FCmpPredicate::ogt:
5811 case LLVM::FCmpPredicate::ugt:
5812 return llvm::omp::OMPAtomicCompareOp::MAX;
5814 return std::nullopt;
5836 llvm::IRBuilderBase &builder,
5842 Region ®ion = atomicCompareOp.getRegion();
5846 llvm::Type *llvmXElementType =
5848 if (!llvmXElementType)
5849 return atomicCompareOp.emitError(
5850 "unable to determine element type for atomic compare");
5852 llvm::Value *llvmX = moduleTranslation.
lookupValue(atomicCompareOp.getX());
5857 bool isSigned =
false;
5858 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {llvmX, llvmXElementType,
5862 llvm::AtomicOrdering atomicOrdering =
5865 auto isAtomicComparePatternOp = [](
Operation &op) {
5866 return llvm::isa<LLVM::ICmpOp, LLVM::FCmpOp, LLVM::SelectOp, LLVM::AndOp,
5887 if (isAtomicComparePatternOp(op))
5892 return moduleTranslation.lookupValue(v) != nullptr;
5894 if (!allOperandsMapped)
5898 return atomicCompareOp.emitError(
5899 "failed to translate operation inside atomic compare region");
5904 auto materializeValue = [&](
mlir::Value val) -> llvm::Value * {
5906 if (llvm::Value *existing = moduleTranslation.
lookupValue(val))
5911 if (loadOp->getParentRegion() == ®ion) {
5912 llvm::Value *loadAddr = moduleTranslation.
lookupValue(loadOp.getAddr());
5915 llvm::Type *loadType =
5916 moduleTranslation.
convertType(loadOp.getResult().getType());
5917 return builder.CreateLoad(loadType, loadAddr);
5925 llvm::omp::OMPAtomicCompareOp compareOp = llvm::omp::OMPAtomicCompareOp::EQ;
5926 llvm::Value *eVal =
nullptr;
5927 llvm::Value *dVal =
nullptr;
5928 bool isXBinopExpr =
false;
5931 if (
auto extractOp = v.getDefiningOp<LLVM::ExtractValueOp>())
5932 return extractOp.getContainer();
5946 bool isComplexPattern =
false;
5948 if (!isa<LLVM::AndOp, LLVM::OrOp>(op))
5954 if (!lhsFcmp || !rhsFcmp)
5959 mlir::Value lhsAgg0 = traceToAggregate(lhsFcmp.getOperand(0));
5960 mlir::Value lhsAgg1 = traceToAggregate(lhsFcmp.getOperand(1));
5961 bool lhsXIsOp0 = (lhsAgg0 == block.
getArgument(0));
5962 bool lhsXIsOp1 = (lhsAgg1 == block.
getArgument(0));
5963 if (!lhsXIsOp0 && !lhsXIsOp1)
5965 mlir::Value eAggregate = lhsXIsOp0 ? lhsAgg1 : lhsAgg0;
5969 if (isa<LLVM::AndOp>(op))
5970 compareOp = llvm::omp::OMPAtomicCompareOp::EQ;
5973 return atomicCompareOp.emitError(
5974 "unsupported comparison predicate (NE) for complex atomic compare");
5976 isXBinopExpr = lhsXIsOp0;
5977 eVal = materializeValue(eAggregate);
5978 isComplexPattern =
true;
5982 if (isComplexPattern) {
5985 if (
auto selectOp = dyn_cast<LLVM::SelectOp>(op)) {
5986 dVal = materializeValue(selectOp.getTrueValue());
5992 if (yieldOp.getResults().empty())
5993 return atomicCompareOp.emitError(
5994 "failed to extract desired value (d) from atomic compare region");
5995 dVal = materializeValue(yieldOp.getResults()[0]);
5998 const llvm::DataLayout &DL =
5999 builder.GetInsertBlock()->getModule()->getDataLayout();
6000 unsigned totalBits =
6001 DL.getTypeStoreSizeInBits(llvmXElementType).getFixedValue();
6003 llvm::IntegerType *intTy =
6004 llvm::IntegerType::get(builder.getContext(), totalBits);
6006 llvm::Align complexAlign = DL.getABITypeAlign(llvmXElementType);
6007 llvm::Align intAlign = DL.getABITypeAlign(intTy);
6008 llvm::Align maxAlign = std::max(complexAlign, intAlign);
6010 llvm::AllocaInst *eAlloca =
6011 builder.CreateAlloca(llvmXElementType,
nullptr,
"cmplx.e");
6012 eAlloca->setAlignment(maxAlign);
6013 llvm::AllocaInst *dAlloca =
6014 builder.CreateAlloca(llvmXElementType,
nullptr,
"cmplx.d");
6015 dAlloca->setAlignment(maxAlign);
6017 builder.CreateAlignedStore(eVal, eAlloca, maxAlign);
6019 builder.CreateAlignedLoad(intTy, eAlloca, maxAlign,
"cmplx.e.int");
6020 builder.CreateAlignedStore(dVal, dAlloca, maxAlign);
6022 builder.CreateAlignedLoad(intTy, dAlloca, maxAlign,
"cmplx.d.int");
6024 llvm::AtomicOrdering failOrdering =
6025 llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(atomicOrdering);
6026 auto *cmpXchg = builder.CreateAtomicCmpXchg(llvmX, eInt, dInt, maxAlign,
6027 atomicOrdering, failOrdering);
6028 cmpXchg->setWeak(atomicCompareOp.getWeak());
6032 if (atomicOrdering == llvm::AtomicOrdering::Release ||
6033 atomicOrdering == llvm::AtomicOrdering::AcquireRelease ||
6034 atomicOrdering == llvm::AtomicOrdering::SequentiallyConsistent) {
6035 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6036 ompBuilder->createFlush(ompLoc);
6042 if (
auto icmpOp = dyn_cast<LLVM::ICmpOp>(op)) {
6046 return atomicCompareOp.emitError(
6047 "unsupported comparison predicate in atomic compare");
6048 compareOp = *maybeOp;
6050 LLVM::ICmpPredicate pred = icmpOp.getPredicate();
6051 isSigned = (pred == LLVM::ICmpPredicate::slt ||
6052 pred == LLVM::ICmpPredicate::sgt ||
6053 pred == LLVM::ICmpPredicate::sle ||
6054 pred == LLVM::ICmpPredicate::sge);
6057 isXBinopExpr = (icmpOp.getOperand(0) == block.
getArgument(0));
6059 isXBinopExpr ? icmpOp.getOperand(1) : icmpOp.getOperand(0);
6060 eVal = materializeValue(eOperand);
6061 }
else if (
auto fcmpOp = dyn_cast<LLVM::FCmpOp>(op)) {
6065 return atomicCompareOp.emitError(
6066 "unsupported comparison predicate in atomic compare");
6067 compareOp = *maybeOp;
6069 isXBinopExpr = (fcmpOp.getOperand(0) == block.
getArgument(0));
6071 isXBinopExpr ? fcmpOp.getOperand(1) : fcmpOp.getOperand(0);
6072 eVal = materializeValue(eOperand);
6073 }
else if (
auto selectOp = dyn_cast<LLVM::SelectOp>(op)) {
6075 dVal = materializeValue(selectOp.getTrueValue());
6083 if (
auto selectOp = dyn_cast<LLVM::SelectOp>(op)) {
6084 dVal = materializeValue(selectOp.getTrueValue());
6091 return atomicCompareOp.emitError(
6092 "failed to extract expected value (e) from atomic compare region");
6096 if (yieldOp.getResults().empty())
6097 return atomicCompareOp.emitError(
6098 "failed to extract desired value (d) from atomic compare region");
6099 dVal = materializeValue(yieldOp.getResults()[0]);
6102 llvmAtomicX.IsSigned = isSigned;
6104 llvm::OpenMPIRBuilder::AtomicOpValue vOpVal = {
nullptr,
nullptr,
false,
6106 llvm::OpenMPIRBuilder::AtomicOpValue rOpVal = {
nullptr,
nullptr,
false,
6108 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6110 bool isWeak = atomicCompareOp.getWeak();
6112 bool savedHandleFPNegZero = ompBuilder->setHandleFPNegZero(
true);
6113 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
6114 ompBuilder->createAtomicCompare(ompLoc, llvmAtomicX, vOpVal, rOpVal, eVal,
6115 dVal, atomicOrdering, compareOp,
6116 isXBinopExpr,
false,
false, isWeak);
6117 ompBuilder->setHandleFPNegZero(savedHandleFPNegZero);
6119 if (failed(
handleError(afterIP, *atomicCompareOp)))
6122 builder.restoreIP(*afterIP);
6127 omp::ClauseCancellationConstructType directive) {
6128 switch (directive) {
6129 case omp::ClauseCancellationConstructType::Loop:
6130 return llvm::omp::Directive::OMPD_for;
6131 case omp::ClauseCancellationConstructType::Parallel:
6132 return llvm::omp::Directive::OMPD_parallel;
6133 case omp::ClauseCancellationConstructType::Sections:
6134 return llvm::omp::Directive::OMPD_sections;
6135 case omp::ClauseCancellationConstructType::Taskgroup:
6136 return llvm::omp::Directive::OMPD_taskgroup;
6138 llvm_unreachable(
"Unhandled cancellation construct type");
6147 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6150 llvm::Value *ifCond =
nullptr;
6151 if (
Value ifVar = op.getIfExpr())
6154 llvm::omp::Directive cancelledDirective =
6157 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
6158 ompBuilder->createCancel(ompLoc, ifCond, cancelledDirective);
6160 if (failed(
handleError(afterIP, *op.getOperation())))
6163 builder.restoreIP(afterIP.get());
6170 llvm::IRBuilderBase &builder,
6175 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6178 llvm::omp::Directive cancelledDirective =
6181 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
6182 ompBuilder->createCancellationPoint(ompLoc, cancelledDirective);
6184 if (failed(
handleError(afterIP, *op.getOperation())))
6187 builder.restoreIP(afterIP.get());
6197 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6199 auto threadprivateOp = cast<omp::ThreadprivateOp>(opInst);
6204 Value symAddr = threadprivateOp.getSymAddr();
6207 if (
auto asCast = dyn_cast<LLVM::AddrSpaceCastOp>(symOp))
6210 if (!isa<LLVM::AddressOfOp>(symOp))
6211 return opInst.
emitError(
"Addressing symbol not found");
6212 LLVM::AddressOfOp addressOfOp = dyn_cast<LLVM::AddressOfOp>(symOp);
6214 LLVM::GlobalOp global =
6215 addressOfOp.getGlobal(moduleTranslation.
symbolTable());
6216 llvm::GlobalValue *globalValue = moduleTranslation.
lookupGlobal(global);
6217 llvm::Type *type = globalValue->getValueType();
6218 llvm::TypeSize typeSize =
6219 builder.GetInsertBlock()->getModule()->getDataLayout().getTypeStoreSize(
6221 llvm::ConstantInt *size = builder.getInt64(typeSize.getFixedValue());
6222 llvm::Value *callInst = ompBuilder->createCachedThreadPrivate(
6223 ompLoc, globalValue, size, global.getSymName() +
".cache");
6229static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind
6231 switch (deviceClause) {
6232 case mlir::omp::DeclareTargetDeviceType::host:
6233 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseHost;
6235 case mlir::omp::DeclareTargetDeviceType::nohost:
6236 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNoHost;
6238 case mlir::omp::DeclareTargetDeviceType::any:
6239 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny;
6242 llvm_unreachable(
"unhandled device clause");
6245static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind
6247 mlir::omp::DeclareTargetCaptureClause captureClause) {
6248 switch (captureClause) {
6249 case mlir::omp::DeclareTargetCaptureClause::to:
6250 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo;
6251 case mlir::omp::DeclareTargetCaptureClause::link:
6252 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink;
6253 case mlir::omp::DeclareTargetCaptureClause::enter:
6254 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter;
6255 case mlir::omp::DeclareTargetCaptureClause::none:
6256 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
6258 llvm_unreachable(
"unhandled capture clause");
6263 if (
auto addrCast = dyn_cast_if_present<LLVM::AddrSpaceCastOp>(op))
6265 if (
auto addressOfOp = dyn_cast_if_present<LLVM::AddressOfOp>(op)) {
6266 auto modOp = addressOfOp->getParentOfType<mlir::ModuleOp>();
6267 return modOp.lookupSymbol(addressOfOp.getGlobalName());
6274 if (
auto addrCast = dyn_cast_if_present<LLVM::AddrSpaceCastOp>(op))
6275 value = addrCast.getOperand();
6292static llvm::SmallString<64>
6294 llvm::OpenMPIRBuilder &ompBuilder,
6295 llvm::vfs::FileSystem &vfs) {
6297 llvm::raw_svector_ostream os(suffix);
6300 auto fileInfoCallBack = [&loc]() {
6301 return std::pair<std::string, uint64_t>(
6302 llvm::StringRef(loc.getFilename()), loc.getLine());
6307 ompBuilder.getTargetEntryUniqueInfo(fileInfoCallBack, vfs).FileID);
6309 os <<
"_decl_tgt_ref_ptr";
6315 if (
auto declareTargetGlobal =
6316 dyn_cast_if_present<omp::DeclareTargetInterface>(
6318 if (declareTargetGlobal.getDeclareTargetCaptureClause() ==
6319 omp::DeclareTargetCaptureClause::link)
6325 if (
auto declareTargetGlobal =
6326 dyn_cast_if_present<omp::DeclareTargetInterface>(
6328 if (declareTargetGlobal.getDeclareTargetCaptureClause() ==
6329 omp::DeclareTargetCaptureClause::to ||
6330 declareTargetGlobal.getDeclareTargetCaptureClause() ==
6331 omp::DeclareTargetCaptureClause::enter)
6349 ompBuilder->Config.hasRequiresUnifiedSharedMemory())) {
6353 if (gOp.getSymName().contains(suffix))
6358 (gOp.getSymName().str() + suffix.str()).str());
6366struct MapInfosTy : llvm::OpenMPIRBuilder::MapInfosTy {
6367 SmallVector<Operation *, 4> Mappers;
6370 void append(MapInfosTy &curInfo) {
6371 Mappers.append(curInfo.Mappers.begin(), curInfo.Mappers.end());
6372 llvm::OpenMPIRBuilder::MapInfosTy::append(curInfo);
6381struct MapInfoData : MapInfosTy {
6382 llvm::SmallVector<bool, 4> IsDeclareTarget;
6383 llvm::SmallVector<bool, 4> IsAMember;
6385 llvm::SmallVector<bool, 4> IsAMapping;
6386 llvm::SmallVector<mlir::Operation *, 4> MapClause;
6387 llvm::SmallVector<llvm::Value *, 4> OriginalValue;
6390 llvm::SmallVector<llvm::Type *, 4> BaseType;
6393 void append(MapInfoData &CurInfo) {
6394 IsDeclareTarget.append(CurInfo.IsDeclareTarget.begin(),
6395 CurInfo.IsDeclareTarget.end());
6396 MapClause.append(CurInfo.MapClause.begin(), CurInfo.MapClause.end());
6397 OriginalValue.append(CurInfo.OriginalValue.begin(),
6398 CurInfo.OriginalValue.end());
6399 BaseType.append(CurInfo.BaseType.begin(), CurInfo.BaseType.end());
6400 MapInfosTy::append(CurInfo);
6404enum class TargetDirectiveEnumTy : uint32_t {
6408 TargetEnterData = 3,
6413static TargetDirectiveEnumTy getTargetDirectiveEnumTyFromOp(Operation *op) {
6414 return llvm::TypeSwitch<Operation *, TargetDirectiveEnumTy>(op)
6415 .Case([](omp::TargetDataOp) {
return TargetDirectiveEnumTy::TargetData; })
6416 .Case([](omp::TargetEnterDataOp) {
6417 return TargetDirectiveEnumTy::TargetEnterData;
6419 .Case([&](omp::TargetExitDataOp) {
6420 return TargetDirectiveEnumTy::TargetExitData;
6422 .Case([&](omp::TargetUpdateOp) {
6423 return TargetDirectiveEnumTy::TargetUpdate;
6425 .Case([&](omp::TargetOp) {
return TargetDirectiveEnumTy::Target; })
6426 .Default([&](Operation *op) {
return TargetDirectiveEnumTy::None; });
6433 if (
auto nestedArrTy = llvm::dyn_cast_if_present<LLVM::LLVMArrayType>(
6434 arrTy.getElementType()))
6448 if (mapOp.getVarPtrPtr())
6472 llvm::Value *basePointer,
6473 llvm::Type *baseType,
6474 llvm::IRBuilderBase &builder,
6476 if (
auto memberClause =
6477 mlir::dyn_cast_if_present<mlir::omp::MapInfoOp>(clauseOp)) {
6482 if (!memberClause.getBounds().empty()) {
6483 llvm::Value *elementCount = builder.getInt64(1);
6484 for (
auto bounds : memberClause.getBounds()) {
6485 if (
auto boundOp = mlir::dyn_cast_if_present<mlir::omp::MapBoundsOp>(
6486 bounds.getDefiningOp())) {
6491 elementCount = builder.CreateMul(
6495 moduleTranslation.
lookupValue(boundOp.getUpperBound()),
6496 moduleTranslation.
lookupValue(boundOp.getLowerBound())),
6497 builder.getInt64(1)));
6504 if (
auto arrTy = llvm::dyn_cast_if_present<LLVM::LLVMArrayType>(type))
6512 llvm::Value *sizeCalc = builder.CreateMul(
6513 elementCount, builder.getInt64(underlyingTypeSzInBits / 8),
6551 return builder.CreateSelect(
6552 builder.CreateICmpEQ(sizeCalc, builder.getInt64(0)),
6553 builder.getInt64(1), sizeCalc);
6567static llvm::omp::OpenMPOffloadMappingFlags
6569 const bool hasExplicitMap =
6570 (mlirFlags &
~omp::ClauseMapFlags::is_device_ptr) !=
6571 omp::ClauseMapFlags::none;
6573 llvm::omp::OpenMPOffloadMappingFlags mapType =
6574 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE;
6576 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::to))
6577 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
6579 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::from))
6580 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
6582 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::always))
6583 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
6585 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::del))
6586 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
6588 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::return_param))
6589 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
6591 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::priv))
6592 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRIVATE;
6594 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::literal))
6595 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL;
6597 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::implicit))
6598 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
6600 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::close))
6601 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
6603 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::present))
6604 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
6606 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::ompx_hold))
6607 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
6609 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::attach))
6610 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH;
6612 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::is_device_ptr)) {
6613 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
6614 if (!hasExplicitMap)
6615 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL;
6625 ArrayRef<Value> useDevAddrOperands = {},
6626 ArrayRef<Value> hasDevAddrOperands = {}) {
6628 auto checkRefPtrOrPteeMapWithAttach = [](omp::ClauseMapFlags mapType) {
6630 bitEnumContainsAll(mapType, omp::ClauseMapFlags::ref_ptr) ||
6631 bitEnumContainsAll(mapType, omp::ClauseMapFlags::ref_ptee);
6632 return hasRefType &&
6633 bitEnumContainsAll(mapType, omp::ClauseMapFlags::attach);
6636 auto checkIsAMember = [](
const auto &mapVars,
auto mapOp) {
6644 for (Value mapValue : mapVars) {
6645 auto map = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
6646 for (
auto member : map.getMembers())
6647 if (member == mapOp)
6654 for (Value mapValue : mapVars) {
6655 auto mapOp = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
6656 bool isRefPtrOrPteeMapWithAttach =
6657 checkRefPtrOrPteeMapWithAttach(mapOp.getMapType());
6658 Value offloadPtr = (mapOp.getVarPtrPtr() && !isRefPtrOrPteeMapWithAttach)
6659 ? mapOp.getVarPtrPtr()
6660 : mapOp.getVarPtr();
6661 mapData.OriginalValue.push_back(moduleTranslation.
lookupValue(offloadPtr));
6662 mapData.Pointers.push_back(
6663 isRefPtrOrPteeMapWithAttach
6664 ? moduleTranslation.
lookupValue(mapOp.getVarPtrPtr())
6665 : mapData.OriginalValue.back());
6667 if (llvm::Value *refPtr =
6669 mapData.IsDeclareTarget.push_back(
true);
6670 mapData.BasePointers.push_back(refPtr);
6672 mapData.IsDeclareTarget.push_back(
true);
6673 mapData.BasePointers.push_back(mapData.OriginalValue.back());
6675 mapData.IsDeclareTarget.push_back(
false);
6676 mapData.BasePointers.push_back(mapData.OriginalValue.back());
6682 mapData.BaseType.push_back(moduleTranslation.
convertType(
6683 mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtrType().value()
6684 : mapOp.getVarPtrType()));
6691 mlir::Type sizeType = (isRefPtrOrPteeMapWithAttach || !mapOp.getVarPtrPtr())
6692 ? mapOp.getVarPtrType()
6693 : mapOp.getVarPtrPtrType().value();
6695 dl, sizeType, isRefPtrOrPteeMapWithAttach ?
nullptr : mapOp,
6696 mapData.Pointers.back(), moduleTranslation.
convertType(sizeType),
6697 builder, moduleTranslation));
6698 mapData.MapClause.push_back(mapOp.getOperation());
6700 mapData.Names.push_back(LLVM::createMappingInformation(
6702 mapData.DevicePointers.push_back(llvm::OpenMPIRBuilder::DeviceInfoTy::None);
6703 if (mapOp.getMapperId())
6704 mapData.Mappers.push_back(
6706 mapOp, mapOp.getMapperIdAttr()));
6708 mapData.Mappers.push_back(
nullptr);
6709 mapData.IsAMapping.push_back(
true);
6710 mapData.IsAMember.push_back(checkIsAMember(mapVars, mapOp));
6713 auto findMapInfo = [&mapData](llvm::Value *val,
6714 llvm::OpenMPIRBuilder::DeviceInfoTy devInfoTy,
6715 size_t memberCount) {
6718 for (llvm::Value *basePtr : mapData.OriginalValue) {
6719 auto mapOp = cast<omp::MapInfoOp>(mapData.MapClause[index]);
6730 (mapData.Types[index] &
6731 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH) ==
6732 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH;
6733 if (!isAttachMap && basePtr == val && mapData.IsAMapping[index] &&
6734 memberCount == mapOp.getMembers().size()) {
6736 mapData.Types[index] |=
6737 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
6738 mapData.DevicePointers[index] = devInfoTy;
6746 auto addDevInfos = [&](
const llvm::ArrayRef<Value> &useDevOperands,
6747 llvm::OpenMPIRBuilder::DeviceInfoTy devInfoTy) {
6748 for (Value mapValue : useDevOperands) {
6749 auto mapOp = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
6751 mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtr() : mapOp.getVarPtr();
6752 llvm::Value *origValue = moduleTranslation.
lookupValue(offloadPtr);
6755 if (!findMapInfo(origValue, devInfoTy, mapOp.getMembers().size())) {
6756 mapData.OriginalValue.push_back(origValue);
6757 mapData.Pointers.push_back(mapData.OriginalValue.back());
6758 mapData.IsDeclareTarget.push_back(
false);
6759 mapData.BasePointers.push_back(mapData.OriginalValue.back());
6760 mlir::Type baseTy = mapOp.getVarPtrPtr()
6761 ? mapOp.getVarPtrPtrType().value()
6762 : mapOp.getVarPtrType();
6763 mapData.BaseType.push_back(moduleTranslation.
convertType(baseTy));
6764 mapData.Sizes.push_back(builder.getInt64(0));
6765 mapData.MapClause.push_back(mapOp.getOperation());
6766 mapData.Types.push_back(
6767 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM);
6768 mapData.Names.push_back(LLVM::createMappingInformation(
6770 mapData.DevicePointers.push_back(devInfoTy);
6771 mapData.Mappers.push_back(
nullptr);
6772 mapData.IsAMapping.push_back(
false);
6773 mapData.IsAMember.push_back(checkIsAMember(useDevOperands, mapOp));
6778 addDevInfos(useDevAddrOperands, llvm::OpenMPIRBuilder::DeviceInfoTy::Address);
6779 addDevInfos(useDevPtrOperands, llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer);
6781 for (Value mapValue : hasDevAddrOperands) {
6782 auto mapOp = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
6784 mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtr() : mapOp.getVarPtr();
6785 llvm::Value *origValue = moduleTranslation.
lookupValue(offloadPtr);
6787 auto mapTypeAlways = llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
6789 (mapOp.getMapType() & omp::ClauseMapFlags::is_device_ptr) !=
6790 omp::ClauseMapFlags::none;
6792 mapData.OriginalValue.push_back(origValue);
6793 mapData.BasePointers.push_back(origValue);
6794 mapData.Pointers.push_back(origValue);
6795 mapData.IsDeclareTarget.push_back(
false);
6797 mlir::Type baseTy = mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtrType().value()
6798 : mapOp.getVarPtrType();
6799 mapData.BaseType.push_back(moduleTranslation.
convertType(baseTy));
6800 mapData.Sizes.push_back(builder.getInt64(dl.
getTypeSize(baseTy)));
6802 mapData.MapClause.push_back(mapOp.getOperation());
6803 if (llvm::to_underlying(mapType & mapTypeAlways)) {
6807 mapData.Types.push_back(mapType);
6811 if (mapOp.getMapperId()) {
6812 mapData.Mappers.push_back(
6814 mapOp, mapOp.getMapperIdAttr()));
6816 mapData.Mappers.push_back(
nullptr);
6821 mapData.Types.push_back(
6822 isDevicePtr ? mapType
6823 : llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
6824 mapData.Mappers.push_back(
nullptr);
6826 mapData.Names.push_back(LLVM::createMappingInformation(
6828 mapData.DevicePointers.push_back(
6829 isDevicePtr ? llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer
6830 : llvm::OpenMPIRBuilder::DeviceInfoTy::Address);
6831 mapData.IsAMapping.push_back(
false);
6832 mapData.IsAMember.push_back(checkIsAMember(hasDevAddrOperands, mapOp));
6837 auto *res = llvm::find(mapData.MapClause, memberOp);
6838 assert(res != mapData.MapClause.end() &&
6839 "MapInfoOp for member not found in MapData, cannot return index");
6840 return std::distance(mapData.MapClause.begin(), res);
6844 omp::MapInfoOp mapInfo,
bool first =
true) {
6845 ArrayAttr indexAttr = mapInfo.getMembersIndexAttr();
6855 auto memberIndicesA = cast<ArrayAttr>(indexAttr[a]);
6856 auto memberIndicesB = cast<ArrayAttr>(indexAttr[b]);
6858 for (auto it : llvm::zip(memberIndicesA, memberIndicesB)) {
6859 int64_t aIndex = mlir::cast<IntegerAttr>(std::get<0>(it)).getInt();
6860 int64_t bIndex = mlir::cast<IntegerAttr>(std::get<1>(it)).getInt();
6862 if (aIndex == bIndex)
6865 if (aIndex < bIndex)
6868 if (aIndex > bIndex)
6875 bool memberAParent = memberIndicesA.size() < memberIndicesB.size();
6877 occludedChildren.push_back(
b);
6879 occludedChildren.push_back(a);
6880 return memberAParent;
6883 for (
auto v : occludedChildren)
6890 ArrayAttr indexAttr = mapInfo.getMembersIndexAttr();
6892 if (indexAttr.size() == 1)
6893 return cast<omp::MapInfoOp>(mapInfo.getMembers()[0].getDefiningOp());
6897 return llvm::cast<omp::MapInfoOp>(
6898 mapInfo.getMembers()[
indices.front()].getDefiningOp());
6921static std::vector<llvm::Value *>
6923 llvm::IRBuilderBase &builder,
bool isArrayTy,
6925 std::vector<llvm::Value *> idx;
6936 idx.push_back(builder.getInt64(0));
6937 for (
int i = bounds.size() - 1; i >= 0; --i) {
6938 if (
auto boundOp = dyn_cast_if_present<omp::MapBoundsOp>(
6939 bounds[i].getDefiningOp())) {
6940 idx.push_back(moduleTranslation.
lookupValue(boundOp.getLowerBound()));
6958 for (
int i = bounds.size() - 1; i >= 0; --i) {
6959 if (
auto boundOp = dyn_cast_if_present<omp::MapBoundsOp>(
6960 bounds[i].getDefiningOp())) {
6961 if (i == ((
int)bounds.size() - 1))
6963 moduleTranslation.
lookupValue(boundOp.getLowerBound()));
6965 idx.back() = builder.CreateAdd(
6966 builder.CreateMul(idx.back(), moduleTranslation.
lookupValue(
6967 boundOp.getExtent())),
6968 moduleTranslation.
lookupValue(boundOp.getLowerBound()));
6977 llvm::transform(values, std::back_inserter(ints), [](
Attribute value) {
6978 return cast<IntegerAttr>(value).getInt();
6986 omp::MapInfoOp parentOp) {
6988 if (parentOp.getMembers().empty())
6992 if (parentOp.getMembers().size() == 1) {
6993 overlapMapDataIdxs.push_back(0);
6997 ArrayAttr indexAttr = parentOp.getMembersIndexAttr();
6998 size_t numMembers = indexAttr.size();
7002 for (
auto [i, indicesAttr] : llvm::enumerate(indexAttr))
7003 getAsIntegers(cast<ArrayAttr>(indicesAttr), memberIndices[i]);
7009 llvm::SmallDenseSet<size_t> skipIndices;
7010 for (
size_t i = 0; i < numMembers; ++i) {
7011 const auto &iIndices = memberIndices[i];
7012 for (
size_t j = 0;
j < numMembers; ++
j) {
7015 const auto &jIndices = memberIndices[
j];
7017 if (jIndices.size() < iIndices.size() &&
7018 std::equal(jIndices.begin(), jIndices.end(), iIndices.begin())) {
7019 skipIndices.insert(i);
7026 for (
size_t i = 0; i < numMembers; ++i)
7027 if (!skipIndices.contains(i))
7028 overlapMapDataIdxs.push_back(i);
7042 llvm::OpenMPIRBuilder &ompBuilder, MapInfoData &mapData,
7043 size_t mapDataIdx, MapInfosTy &combinedInfo,
7044 TargetDirectiveEnumTy targetDirective,
7045 llvm::omp::OpenMPOffloadMappingFlags memberOfFlag =
7046 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE,
7047 bool isTargetParam =
true,
int mapDataParentIdx = -1) {
7048 auto mapFlag = mapData.Types[mapDataIdx];
7049 auto mapInfoOp = llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIdx]);
7053 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH) ==
7054 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
7060 if (isTargetParam &&
7061 (targetDirective == TargetDirectiveEnumTy::Target &&
7062 !mapData.IsDeclareTarget[mapDataIdx]) &&
7064 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7066 if (mapInfoOp.getMapCaptureType() == omp::VariableCaptureKind::ByCopy &&
7068 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL;
7077 if (memberOfFlag != llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE) {
7078 if (!isPtrTy && !isAttachMap)
7079 ompBuilder.setCorrectMemberOfFlag(mapFlag, memberOfFlag);
7086 mapFlag &=
~llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
7096 if (isPtrTy && !isAttachMap && mapData.IsDeclareTarget[mapDataIdx])
7097 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
7106 !bitEnumContainsAll(mapInfoOp.getMapType(),
7107 omp::ClauseMapFlags::ref_ptr) &&
7108 bitEnumContainsAll(mapInfoOp.getMapType(), omp::ClauseMapFlags::ref_ptee);
7109 bool isRefPtrPtee = bitEnumContainsAll(mapInfoOp.getMapType(),
7110 omp::ClauseMapFlags::ref_ptr |
7111 omp::ClauseMapFlags::ref_ptee);
7113 if (!mapInfoOp->getParentOfType<omp::DeclareMapperOp>() &&
7114 mapDataParentIdx >= 0 && !(isRefPtee || (isRefPtrPtee && isPtrTy))) {
7115 combinedInfo.BasePointers.emplace_back(
7116 mapData.BasePointers[mapDataParentIdx]);
7118 combinedInfo.BasePointers.emplace_back(mapData.BasePointers[mapDataIdx]);
7121 combinedInfo.Pointers.emplace_back(mapData.Pointers[mapDataIdx]);
7122 combinedInfo.DevicePointers.emplace_back(
7123 memberOfFlag != llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE
7124 ? llvm::OpenMPIRBuilder::DeviceInfoTy::None
7125 : mapData.DevicePointers[mapDataIdx]);
7126 combinedInfo.Mappers.emplace_back(mapData.Mappers[mapDataIdx]);
7127 combinedInfo.Names.emplace_back(mapData.Names[mapDataIdx]);
7128 combinedInfo.Types.emplace_back(mapFlag);
7129 combinedInfo.Sizes.emplace_back(
7130 isPtrTy ? builder.CreateSelect(
7131 builder.CreateIsNull(mapData.Pointers[mapDataIdx]),
7132 builder.getInt64(0), mapData.Sizes[mapDataIdx])
7133 : mapData.Sizes[mapDataIdx]);
7153 llvm::OpenMPIRBuilder &ompBuilder,
DataLayout &dl, MapInfosTy &combinedInfo,
7154 MapInfoData &mapData, uint64_t mapDataIndex,
7155 llvm::omp::OpenMPOffloadMappingFlags memberOfFlag,
7156 TargetDirectiveEnumTy targetDirective) {
7157 using MapFlags = llvm::omp::OpenMPOffloadMappingFlags;
7158 assert(!ompBuilder.Config.isTargetDevice() &&
7159 "function only supported for host device codegen");
7161 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
7162 auto *parentMapper = mapData.Mappers[mapDataIndex];
7168 MapFlags baseFlag = (targetDirective == TargetDirectiveEnumTy::Target &&
7169 !mapData.IsDeclareTarget[mapDataIndex])
7170 ? MapFlags::OMP_MAP_TARGET_PARAM
7171 : MapFlags::OMP_MAP_NONE;
7177 MapFlags parentFlags = mapData.Types[mapDataIndex];
7178 MapFlags preserve = MapFlags::OMP_MAP_TO | MapFlags::OMP_MAP_FROM |
7179 MapFlags::OMP_MAP_ALWAYS | MapFlags::OMP_MAP_CLOSE |
7180 MapFlags::OMP_MAP_PRESENT |
7181 MapFlags::OMP_MAP_OMPX_HOLD |
7182 MapFlags::OMP_MAP_IMPLICIT;
7183 baseFlag |= (parentFlags & preserve);
7185 MapFlags parentFlags = mapData.Types[mapDataIndex];
7187 MapFlags::OMP_MAP_PRESENT | MapFlags::OMP_MAP_RETURN_PARAM;
7188 baseFlag |= (parentFlags & preserve);
7191 combinedInfo.Types.emplace_back(baseFlag);
7192 combinedInfo.DevicePointers.emplace_back(
7193 mapData.DevicePointers[mapDataIndex]);
7197 combinedInfo.Mappers.emplace_back(
7198 parentMapper && !parentClause.getPartialMap() ? parentMapper :
nullptr);
7200 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder));
7201 combinedInfo.BasePointers.emplace_back(mapData.BasePointers[mapDataIndex]);
7210 llvm::Value *lowAddr, *highAddr;
7211 if (!parentClause.getPartialMap()) {
7212 lowAddr = builder.CreatePointerCast(mapData.Pointers[mapDataIndex],
7213 builder.getPtrTy());
7214 highAddr = builder.CreatePointerCast(
7215 builder.CreateConstGEP1_32(mapData.BaseType[mapDataIndex],
7216 mapData.Pointers[mapDataIndex], 1),
7217 builder.getPtrTy());
7218 combinedInfo.Pointers.emplace_back(mapData.Pointers[mapDataIndex]);
7220 auto mapOp = dyn_cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
7223 lowAddr = builder.CreatePointerCast(mapData.BasePointers[firstMemberIdx],
7224 builder.getPtrTy());
7228 auto lastMemberMapInfo =
7229 cast<omp::MapInfoOp>(mapData.MapClause[lastMemberIdx]);
7238 bool isRefPteeMap = bitEnumContainsAll(lastMemberMapInfo.getMapType(),
7239 omp::ClauseMapFlags::ref_ptee) &&
7240 !bitEnumContainsAll(lastMemberMapInfo.getMapType(),
7241 omp::ClauseMapFlags::ref_ptr);
7242 llvm::Type *castType = mapData.BaseType[lastMemberIdx];
7245 moduleTranslation.
convertType(lastMemberMapInfo.getVarPtrType());
7246 highAddr = builder.CreatePointerCast(
7247 builder.CreateGEP(castType, mapData.BasePointers[lastMemberIdx],
7248 builder.getInt64(1)),
7249 builder.getPtrTy());
7250 combinedInfo.Pointers.emplace_back(mapData.BasePointers[firstMemberIdx]);
7253 llvm::Value *size = builder.CreateIntCast(
7254 builder.CreatePtrDiff(builder.getInt8Ty(), highAddr, lowAddr),
7255 builder.getInt64Ty(),
7257 combinedInfo.Sizes.push_back(size);
7265 if (!parentClause.getPartialMap()) {
7270 MapFlags mapFlag = mapData.Types[mapDataIndex];
7271 bool hasMapClose = (MapFlags(mapFlag) & MapFlags::OMP_MAP_CLOSE) ==
7272 MapFlags::OMP_MAP_CLOSE;
7273 ompBuilder.setCorrectMemberOfFlag(mapFlag, memberOfFlag);
7289 if (targetDirective == TargetDirectiveEnumTy::TargetUpdate || hasMapClose ||
7290 overlapIdxs.size() == 1) {
7291 combinedInfo.Types.emplace_back(mapFlag);
7292 combinedInfo.DevicePointers.emplace_back(
7293 mapData.DevicePointers[mapDataIndex]);
7295 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder));
7296 combinedInfo.BasePointers.emplace_back(
7297 mapData.BasePointers[mapDataIndex]);
7298 combinedInfo.Pointers.emplace_back(mapData.Pointers[mapDataIndex]);
7299 combinedInfo.Sizes.emplace_back(mapData.Sizes[mapDataIndex]);
7300 combinedInfo.Mappers.emplace_back(
nullptr);
7306 lowAddr = builder.CreatePointerCast(mapData.Pointers[mapDataIndex],
7307 builder.getPtrTy());
7308 highAddr = builder.CreatePointerCast(
7309 builder.CreateConstGEP1_32(mapData.BaseType[mapDataIndex],
7310 mapData.Pointers[mapDataIndex], 1),
7311 builder.getPtrTy());
7318 mapFlag &=
~llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
7325 for (
auto v : overlapIdxs) {
7328 cast<omp::MapInfoOp>(parentClause.getMembers()[v].getDefiningOp()));
7330 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataOverlapIdx]));
7331 combinedInfo.Types.emplace_back(mapFlag);
7332 combinedInfo.DevicePointers.emplace_back(
7333 llvm::OpenMPIRBuilder::DeviceInfoTy::None);
7335 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder));
7336 combinedInfo.BasePointers.emplace_back(
7337 mapData.BasePointers[mapDataIndex]);
7338 combinedInfo.Mappers.emplace_back(
nullptr);
7339 combinedInfo.Pointers.emplace_back(lowAddr);
7340 auto sizeCalc = builder.CreateIntCast(
7341 builder.CreatePtrDiff(builder.getInt8Ty(),
7342 mapData.OriginalValue[mapDataOverlapIdx],
7344 builder.getInt64Ty(),
true);
7349 auto sizeSel = builder.CreateSelect(
7350 builder.CreateICmpNE(builder.getInt64(0), sizeCalc), sizeCalc,
7351 isPtrMap ? llvm::ConstantExpr::getSizeOf(builder.getPtrTy())
7352 : mapData.Sizes[mapDataOverlapIdx]);
7353 combinedInfo.Sizes.emplace_back(sizeSel);
7354 lowAddr = builder.CreateConstGEP1_32(
7355 isPtrMap ? builder.getPtrTy() : mapData.BaseType[mapDataOverlapIdx],
7356 mapData.BasePointers[mapDataOverlapIdx], 1);
7359 combinedInfo.Types.emplace_back(mapFlag);
7360 combinedInfo.DevicePointers.emplace_back(
7361 llvm::OpenMPIRBuilder::DeviceInfoTy::None);
7363 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder));
7364 combinedInfo.BasePointers.emplace_back(
7365 mapData.BasePointers[mapDataIndex]);
7366 combinedInfo.Mappers.emplace_back(
nullptr);
7367 combinedInfo.Pointers.emplace_back(lowAddr);
7368 combinedInfo.Sizes.emplace_back(builder.CreateIntCast(
7369 builder.CreatePtrDiff(builder.getInt8Ty(), highAddr, lowAddr),
7370 builder.getInt64Ty(),
true));
7376 llvm::IRBuilderBase &builder,
7377 llvm::OpenMPIRBuilder &ompBuilder,
7379 MapInfoData &mapData, uint64_t mapDataIndex,
7380 TargetDirectiveEnumTy targetDirective) {
7381 assert(!ompBuilder.Config.isTargetDevice() &&
7382 "function only supported for host device codegen");
7385 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
7390 if (parentClause.getMembers().size() == 1 && parentClause.getPartialMap()) {
7391 auto memberClause = llvm::cast<omp::MapInfoOp>(
7392 parentClause.getMembers()[0].getDefiningOp());
7405 builder, ompBuilder, mapData, memberDataIdx, combinedInfo,
7407 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE,
7408 true, mapDataIndex);
7412 auto collectMapInfoIdxs =
7415 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
7417 for (
auto member : parentClause.getMembers())
7419 mapData, llvm::cast<omp::MapInfoOp>(member.getDefiningOp())));
7423 collectMapInfoIdxs(mapInfoIdx);
7425 llvm::omp::OpenMPOffloadMappingFlags memberOfFlag =
7426 ompBuilder.getMemberOfFlag(combinedInfo.Types.size());
7427 for (
size_t i = 0; i < mapInfoIdx.size(); i++) {
7432 combinedInfo, mapData, mapInfoIdx[i], memberOfFlag,
7436 combinedInfo, targetDirective, memberOfFlag,
7437 false, mapDataIndex);
7449 llvm::IRBuilderBase &builder) {
7451 "function only supported for host device codegen");
7452 for (
size_t i = 0; i < mapData.MapClause.size(); ++i) {
7453 auto mapOp = cast<omp::MapInfoOp>(mapData.MapClause[i]);
7456 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH) ==
7457 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
7462 if (!mapData.IsDeclareTarget[i] ||
7463 (mapData.IsDeclareTarget[i] && isAttachMap)) {
7464 omp::VariableCaptureKind captureKind = mapOp.getMapCaptureType();
7474 switch (captureKind) {
7475 case omp::VariableCaptureKind::ByRef: {
7476 llvm::Value *newV = mapData.Pointers[i];
7478 moduleTranslation, builder, mapData.BaseType[i]->isArrayTy(),
7481 newV = builder.CreateLoad(builder.getPtrTy(), newV);
7483 if (!offsetIdx.empty())
7484 newV = builder.CreateInBoundsGEP(mapData.BaseType[i], newV, offsetIdx,
7486 mapData.Pointers[i] = newV;
7488 case omp::VariableCaptureKind::ByCopy: {
7489 llvm::Type *type = mapData.BaseType[i];
7491 if (mapData.Pointers[i]->getType()->isPointerTy())
7492 newV = builder.CreateLoad(type, mapData.Pointers[i]);
7494 newV = mapData.Pointers[i];
7497 auto curInsert = builder.saveIP();
7498 llvm::DebugLoc DbgLoc = builder.getCurrentDebugLocation();
7500 auto *memTempAlloc =
7501 builder.CreateAlloca(builder.getPtrTy(),
nullptr,
".casted");
7502 builder.SetCurrentDebugLocation(DbgLoc);
7503 builder.restoreIP(curInsert);
7505 builder.CreateStore(newV, memTempAlloc);
7506 newV = builder.CreateLoad(builder.getPtrTy(), memTempAlloc);
7509 mapData.Pointers[i] = newV;
7510 mapData.BasePointers[i] = newV;
7512 case omp::VariableCaptureKind::This:
7513 case omp::VariableCaptureKind::VLAType:
7514 mapData.MapClause[i]->emitOpError(
"Unhandled capture kind");
7525 MapInfoData &mapData,
7526 TargetDirectiveEnumTy targetDirective) {
7528 "function only supported for host device codegen");
7549 for (
size_t i = 0; i < mapData.MapClause.size(); ++i) {
7550 if (mapData.IsAMember[i])
7553 auto mapInfoOp = dyn_cast<omp::MapInfoOp>(mapData.MapClause[i]);
7554 if (!mapInfoOp.getMembers().empty()) {
7556 combinedInfo, mapData, i, targetDirective);
7565static llvm::Expected<llvm::Function *>
7567 LLVM::ModuleTranslation &moduleTranslation,
7568 llvm::StringRef mapperFuncName,
7569 TargetDirectiveEnumTy targetDirective);
7571static llvm::Expected<llvm::Function *>
7574 TargetDirectiveEnumTy targetDirective) {
7576 "function only supported for host device codegen");
7577 auto declMapperOp = cast<omp::DeclareMapperOp>(op);
7578 std::string mapperFuncName =
7580 {
"omp_mapper", declMapperOp.getSymName()});
7582 if (
auto *lookupFunc = moduleTranslation.
lookupFunction(mapperFuncName))
7590 if (llvm::Function *existingFunc =
7591 moduleTranslation.
getLLVMModule()->getFunction(mapperFuncName)) {
7592 moduleTranslation.
mapFunction(mapperFuncName, existingFunc);
7593 return existingFunc;
7597 mapperFuncName, targetDirective);
7600static llvm::Expected<llvm::Function *>
7603 llvm::StringRef mapperFuncName,
7604 TargetDirectiveEnumTy targetDirective) {
7606 "function only supported for host device codegen");
7607 auto declMapperOp = cast<omp::DeclareMapperOp>(op);
7608 auto declMapperInfoOp = declMapperOp.getDeclareMapperInfo();
7610 return llvm::make_error<PreviouslyReportedError>();
7614 llvm::Type *varType = moduleTranslation.
convertType(declMapperOp.getType());
7617 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
7620 MapInfosTy combinedInfo;
7622 [&](InsertPointTy codeGenIP, llvm::Value *ptrPHI,
7623 llvm::Value *unused2) -> llvm::OpenMPIRBuilder::MapInfosOrErrorTy {
7624 builder.restoreIP(codeGenIP);
7625 moduleTranslation.
mapValue(declMapperOp.getSymVal(), ptrPHI);
7626 moduleTranslation.
mapBlock(&declMapperOp.getRegion().front(),
7627 builder.GetInsertBlock());
7628 if (failed(moduleTranslation.
convertBlock(declMapperOp.getRegion().front(),
7631 return llvm::make_error<PreviouslyReportedError>();
7632 MapInfoData mapData;
7635 genMapInfos(builder, moduleTranslation, dl, combinedInfo, mapData,
7641 return combinedInfo;
7645 if (!combinedInfo.Mappers[i])
7648 moduleTranslation, targetDirective);
7652 genMapInfoCB, varType, mapperFuncName, customMapperCB,
7655 return newFn.takeError();
7656 if ([[maybe_unused]] llvm::Function *mappedFunc =
7658 assert(mappedFunc == *newFn &&
7659 "mapper function mapping disagrees with emitted function");
7661 moduleTranslation.
mapFunction(mapperFuncName, *newFn);
7669 llvm::Value *ifCond =
nullptr;
7670 llvm::Value *deviceID = builder.getInt64(llvm::omp::OMP_DEVICEID_UNDEF);
7674 llvm::omp::RuntimeFunction RTLFn;
7676 TargetDirectiveEnumTy targetDirective = getTargetDirectiveEnumTyFromOp(op);
7679 llvm::OpenMPIRBuilder::TargetDataInfo info(
7682 assert(!ompBuilder->Config.isTargetDevice() &&
7683 "target data/enter/exit/update are host ops");
7684 bool isOffloadEntry = !ompBuilder->Config.TargetTriples.empty();
7686 auto getDeviceID = [&](
mlir::Value dev) -> llvm::Value * {
7687 llvm::Value *v = moduleTranslation.
lookupValue(dev);
7688 return builder.CreateIntCast(v, builder.getInt64Ty(),
true);
7693 .Case([&](omp::TargetDataOp dataOp) {
7697 if (
auto ifVar = dataOp.getIfExpr())
7701 deviceID = getDeviceID(devId);
7703 mapVars = dataOp.getMapVars();
7704 useDevicePtrVars = dataOp.getUseDevicePtrVars();
7705 useDeviceAddrVars = dataOp.getUseDeviceAddrVars();
7708 .Case([&](omp::TargetEnterDataOp enterDataOp) -> LogicalResult {
7712 if (
auto ifVar = enterDataOp.getIfExpr())
7716 deviceID = getDeviceID(devId);
7719 enterDataOp.getNowait()
7720 ? llvm::omp::OMPRTL___tgt_target_data_begin_nowait_mapper
7721 : llvm::omp::OMPRTL___tgt_target_data_begin_mapper;
7722 mapVars = enterDataOp.getMapVars();
7723 info.HasNoWait = enterDataOp.getNowait();
7726 .Case([&](omp::TargetExitDataOp exitDataOp) -> LogicalResult {
7730 if (
auto ifVar = exitDataOp.getIfExpr())
7734 deviceID = getDeviceID(devId);
7736 RTLFn = exitDataOp.getNowait()
7737 ? llvm::omp::OMPRTL___tgt_target_data_end_nowait_mapper
7738 : llvm::omp::OMPRTL___tgt_target_data_end_mapper;
7739 mapVars = exitDataOp.getMapVars();
7740 info.HasNoWait = exitDataOp.getNowait();
7743 .Case([&](omp::TargetUpdateOp updateDataOp) -> LogicalResult {
7747 if (
auto ifVar = updateDataOp.getIfExpr())
7751 deviceID = getDeviceID(devId);
7754 updateDataOp.getNowait()
7755 ? llvm::omp::OMPRTL___tgt_target_data_update_nowait_mapper
7756 : llvm::omp::OMPRTL___tgt_target_data_update_mapper;
7757 mapVars = updateDataOp.getMapVars();
7758 info.HasNoWait = updateDataOp.getNowait();
7761 .DefaultUnreachable(
"unexpected operation");
7766 if (!isOffloadEntry)
7767 ifCond = builder.getFalse();
7769 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
7770 MapInfoData mapData;
7772 builder, useDevicePtrVars, useDeviceAddrVars);
7775 MapInfosTy combinedInfo;
7776 auto genMapInfoCB = [&](InsertPointTy codeGenIP) -> MapInfosTy & {
7777 builder.restoreIP(codeGenIP);
7778 genMapInfos(builder, moduleTranslation, DL, combinedInfo, mapData,
7780 return combinedInfo;
7786 [&moduleTranslation](
7787 llvm::OpenMPIRBuilder::DeviceInfoTy type,
7791 for (
auto [arg, useDevVar] :
7792 llvm::zip_equal(blockArgs, useDeviceVars)) {
7794 auto getMapBasePtr = [](omp::MapInfoOp mapInfoOp) {
7795 return mapInfoOp.getVarPtrPtr() ? mapInfoOp.getVarPtrPtr()
7796 : mapInfoOp.getVarPtr();
7799 auto useDevMap = cast<omp::MapInfoOp>(useDevVar.getDefiningOp());
7800 for (
auto [mapClause, devicePointer, basePointer] : llvm::zip_equal(
7801 mapInfoData.MapClause, mapInfoData.DevicePointers,
7802 mapInfoData.BasePointers)) {
7803 auto mapOp = cast<omp::MapInfoOp>(mapClause);
7804 if (getMapBasePtr(mapOp) != getMapBasePtr(useDevMap) ||
7805 devicePointer != type)
7808 if (llvm::Value *devPtrInfoMap =
7809 mapper ? mapper(basePointer) : basePointer) {
7810 moduleTranslation.
mapValue(arg, devPtrInfoMap);
7817 using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy;
7818 auto bodyGenCB = [&](InsertPointTy codeGenIP, BodyGenTy bodyGenType)
7819 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
7822 builder.restoreIP(codeGenIP);
7823 assert(isa<omp::TargetDataOp>(op) &&
7824 "BodyGen requested for non TargetDataOp");
7825 auto blockArgIface = cast<omp::BlockArgOpenMPOpInterface>(op);
7826 Region ®ion = cast<omp::TargetDataOp>(op).getRegion();
7827 switch (bodyGenType) {
7828 case BodyGenTy::Priv:
7830 if (!info.DevicePtrInfoMap.empty()) {
7831 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Address,
7832 blockArgIface.getUseDeviceAddrBlockArgs(),
7833 useDeviceAddrVars, mapData,
7834 [&](llvm::Value *basePointer) -> llvm::Value * {
7835 if (!info.DevicePtrInfoMap[basePointer].second)
7837 return builder.CreateLoad(
7839 info.DevicePtrInfoMap[basePointer].second);
7841 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer,
7842 blockArgIface.getUseDevicePtrBlockArgs(), useDevicePtrVars,
7843 mapData, [&](llvm::Value *basePointer) {
7844 return info.DevicePtrInfoMap[basePointer].second;
7848 moduleTranslation)))
7849 return llvm::make_error<PreviouslyReportedError>();
7852 case BodyGenTy::DupNoPriv:
7853 if (info.DevicePtrInfoMap.empty()) {
7856 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Address,
7857 blockArgIface.getUseDeviceAddrBlockArgs(),
7858 useDeviceAddrVars, mapData);
7859 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer,
7860 blockArgIface.getUseDevicePtrBlockArgs(), useDevicePtrVars,
7864 case BodyGenTy::NoPriv:
7866 if (info.DevicePtrInfoMap.empty()) {
7868 moduleTranslation)))
7869 return llvm::make_error<PreviouslyReportedError>();
7873 return builder.saveIP();
7876 auto customMapperCB =
7878 if (!combinedInfo.Mappers[i])
7880 info.HasMapper =
true;
7882 moduleTranslation, targetDirective);
7885 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
7887 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
7889 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP = [&]() {
7890 if (isa<omp::TargetDataOp>(op))
7891 return ompBuilder->createTargetData(ompLoc, allocaIP, builder.saveIP(),
7892 deallocBlocks, deviceID, ifCond, info,
7893 genMapInfoCB, customMapperCB,
7896 return ompBuilder->createTargetData(ompLoc, allocaIP, builder.saveIP(),
7897 deallocBlocks, deviceID, ifCond, info,
7898 genMapInfoCB, customMapperCB, &RTLFn);
7904 builder.restoreIP(*afterIP);
7912 auto distributeOp = cast<omp::DistributeOp>(opInst);
7919 bool doDistributeReduction =
7923 unsigned numReductionVars = teamsOp ? teamsOp.getNumReductionVars() : 0;
7928 if (doDistributeReduction) {
7929 isByRef =
getIsByRef(teamsOp.getReductionByref());
7930 assert(isByRef.size() == teamsOp.getNumReductionVars());
7933 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
7937 llvm::cast<omp::BlockArgOpenMPOpInterface>(*teamsOp)
7938 .getReductionBlockArgs();
7941 teamsOp, reductionArgs, builder, moduleTranslation, allocaIP,
7942 reductionDecls, privateReductionVariables, reductionVariableMap,
7947 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
7949 [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
7954 moduleTranslation, allocaIP, deallocBlocks);
7957 builder.restoreIP(codeGenIP);
7961 distributeOp, builder, moduleTranslation, privVarsInfo, allocaIP);
7963 return llvm::make_error<PreviouslyReportedError>();
7968 return llvm::make_error<PreviouslyReportedError>();
7971 distributeOp, builder, moduleTranslation, privVarsInfo.
mlirVars,
7973 distributeOp.getPrivateNeedsBarrier())))
7974 return llvm::make_error<PreviouslyReportedError>();
7977 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
7980 builder, moduleTranslation);
7982 return regionBlock.takeError();
7983 builder.SetInsertPoint(*regionBlock, (*regionBlock)->begin());
7988 if (!isa_and_present<omp::WsloopOp>(distributeOp.getNestedWrapper())) {
7991 bool hasDistSchedule = distributeOp.getDistScheduleStatic();
7992 auto schedule = hasDistSchedule ? omp::ClauseScheduleKind::Distribute
7993 : omp::ClauseScheduleKind::Static;
7995 bool isOrdered = hasDistSchedule;
7996 std::optional<omp::ScheduleModifier> scheduleMod;
7997 bool isSimd =
false;
7998 llvm::omp::WorksharingLoopType workshareLoopType =
7999 llvm::omp::WorksharingLoopType::DistributeStaticLoop;
8000 bool loopNeedsBarrier =
false;
8001 llvm::Value *chunk = moduleTranslation.
lookupValue(
8002 distributeOp.getDistScheduleChunkSize());
8003 llvm::CanonicalLoopInfo *loopInfo =
8005 llvm::OpenMPIRBuilder::InsertPointOrErrorTy wsloopIP =
8006 ompBuilder->applyWorkshareLoop(
8007 ompLoc.DL, loopInfo, allocaIP, loopNeedsBarrier,
8008 convertToScheduleKind(schedule), chunk, isSimd,
8009 scheduleMod == omp::ScheduleModifier::monotonic,
8010 scheduleMod == omp::ScheduleModifier::nonmonotonic, isOrdered,
8011 workshareLoopType,
false, hasDistSchedule, chunk);
8014 return wsloopIP.takeError();
8017 distributeOp.getLoc(), privVarsInfo)))
8018 return llvm::make_error<PreviouslyReportedError>();
8020 return llvm::Error::success();
8024 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
8026 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
8027 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
8028 ompBuilder->createDistribute(ompLoc, allocaIP, deallocBlocks, bodyGenCB);
8033 builder.restoreIP(*afterIP);
8035 if (doDistributeReduction) {
8038 teamsOp, builder, moduleTranslation, allocaIP, reductionDecls,
8039 privateReductionVariables, isByRef,
8051 auto offloadMod = dyn_cast<omp::OffloadModuleInterface>(op);
8053 return op->
emitOpError() <<
"omp flags attached to non offload module op";
8057 if (offloadMod.getIsTargetDevice())
8058 ompBuilder->M.addModuleFlag(llvm::Module::Max,
"openmp-device",
8059 attribute.getOpenmpDeviceVersion());
8062 if (!offloadMod.getIsGPU())
8065 if (attribute.getNoGpuLib())
8068 ompBuilder->createGlobalFlag(
8069 attribute.getDebugKind() ,
8070 "__omp_rtl_debug_kind");
8071 ompBuilder->createGlobalFlag(
8073 .getAssumeTeamsOversubscription()
8075 "__omp_rtl_assume_teams_oversubscription");
8076 ompBuilder->createGlobalFlag(
8078 .getAssumeThreadsOversubscription()
8080 "__omp_rtl_assume_threads_oversubscription");
8081 ompBuilder->createGlobalFlag(
8082 attribute.getAssumeNoThreadState() ,
8083 "__omp_rtl_assume_no_thread_state");
8084 ompBuilder->createGlobalFlag(
8086 .getAssumeNoNestedParallelism()
8088 "__omp_rtl_assume_no_nested_parallelism");
8093 omp::TargetOp targetOp,
8094 llvm::OpenMPIRBuilder &ompBuilder,
8095 llvm::vfs::FileSystem &vfs,
8096 llvm::StringRef parentName =
"") {
8097 auto fileLoc = targetOp.getLoc()->findInstanceOf<
FileLineColLoc>();
8098 assert(fileLoc &&
"No file found from location");
8100 auto fileInfoCallBack = [&fileLoc]() {
8101 return std::pair<std::string, uint64_t>(
8102 llvm::StringRef(fileLoc.getFilename()), fileLoc.getLine());
8106 ompBuilder.getTargetEntryUniqueInfo(fileInfoCallBack, vfs, parentName);
8112 llvm::IRBuilderBase &builder, llvm::Function *
func) {
8114 "function only supported for target device codegen");
8115 llvm::IRBuilderBase::InsertPointGuard guard(builder);
8116 for (
size_t i = 0; i < mapData.MapClause.size(); ++i) {
8129 if (!mapData.IsDeclareTarget[i])
8137 if (
auto *constant = dyn_cast<llvm::Constant>(mapData.OriginalValue[i]))
8138 convertUsersOfConstantsToInstructions(constant,
func,
false);
8145 for (llvm::User *user : mapData.OriginalValue[i]->users())
8146 userVec.push_back(user);
8148 for (llvm::User *user : userVec) {
8149 auto *insn = dyn_cast<llvm::Instruction>(user);
8150 if (!insn || insn->getFunction() !=
func)
8152 auto mapOp = cast<omp::MapInfoOp>(mapData.MapClause[i]);
8153 llvm::Value *substitute = mapData.BasePointers[i];
8155 mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtr() : mapOp.getVarPtr();
8159 ->Config.hasRequiresUnifiedSharedMemory())) {
8160 builder.SetCurrentDebugLocation(insn->getDebugLoc());
8161 substitute = builder.CreateLoad(mapData.BasePointers[i]->getType(),
8162 mapData.BasePointers[i]);
8163 cast<llvm::LoadInst>(substitute)->moveBefore(insn->getIterator());
8165 user->replaceUsesOfWith(mapData.OriginalValue[i], substitute);
8210 omp::TargetOp targetOp, MapInfoData &mapData, llvm::Argument &arg,
8211 llvm::Value *input, llvm::Value *&retVal, llvm::IRBuilderBase &builder,
8212 llvm::OpenMPIRBuilder &ompBuilder,
8214 llvm::IRBuilderBase::InsertPoint allocaIP,
8215 llvm::IRBuilderBase::InsertPoint codeGenIP,
8217 assert(ompBuilder.Config.isTargetDevice() &&
8218 "function only supported for target device codegen");
8219 builder.restoreIP(allocaIP);
8221 omp::VariableCaptureKind capture = omp::VariableCaptureKind::ByRef;
8223 ompBuilder.M.getContext());
8224 unsigned alignmentValue = 0;
8227 cast<omp::BlockArgOpenMPOpInterface>(*targetOp).getBlockArgsPairs(
8230 for (
size_t i = 0; i < mapData.MapClause.size(); ++i) {
8231 if (mapData.OriginalValue[i] == input) {
8232 auto mapOp = cast<omp::MapInfoOp>(mapData.MapClause[i]);
8233 capture = mapOp.getMapCaptureType();
8236 mapOp.getVarPtrType(), ompBuilder.M.getDataLayout());
8240 for (
auto &[val, arg] : blockArgsPairs) {
8241 if (mapOp.getResult() == val) {
8246 assert(mlirArg &&
"expected to find entry block argument for map clause");
8251 unsigned int allocaAS = ompBuilder.M.getDataLayout().getAllocaAddrSpace();
8252 unsigned int defaultAS =
8253 ompBuilder.M.getDataLayout().getProgramAddressSpace();
8256 llvm::Value *v =
nullptr;
8264 builder.SetInsertPoint(codeGenIP.getBlock()->getFirstInsertionPt());
8265 v = ompBuilder.createOMPAllocShared(builder, arg.getType());
8269 llvm::IRBuilderBase::InsertPointGuard guard(builder);
8270 for (
auto deallocIP : deallocIPs) {
8271 builder.SetInsertPoint(deallocIP.getBlock(), deallocIP.getPoint());
8272 ompBuilder.createOMPFreeShared(builder, v, arg.getType());
8276 v = builder.CreateAlloca(arg.getType(), allocaAS);
8278 if (allocaAS != defaultAS && arg.getType()->isPointerTy())
8279 v = builder.CreateAddrSpaceCast(v, builder.getPtrTy(defaultAS));
8282 builder.CreateStore(&arg, v);
8284 builder.restoreIP(codeGenIP);
8287 case omp::VariableCaptureKind::ByCopy: {
8291 case omp::VariableCaptureKind::ByRef: {
8292 llvm::LoadInst *loadInst = builder.CreateAlignedLoad(
8294 ompBuilder.M.getDataLayout().getPrefTypeAlign(v->getType()));
8309 if (v->getType()->isPointerTy() && alignmentValue) {
8310 llvm::MDBuilder MDB(builder.getContext());
8311 loadInst->setMetadata(
8312 llvm::LLVMContext::MD_align,
8313 llvm::MDNode::get(builder.getContext(),
8314 MDB.createConstant(llvm::ConstantInt::get(
8315 llvm::Type::getInt64Ty(builder.getContext()),
8322 case omp::VariableCaptureKind::This:
8323 case omp::VariableCaptureKind::VLAType:
8326 assert(
false &&
"Currently unsupported capture kind");
8330 return builder.saveIP();
8347 auto blockArgIface = llvm::cast<omp::BlockArgOpenMPOpInterface>(*targetOp);
8348 for (
auto item : llvm::zip_equal(targetOp.getHostEvalVars(),
8349 blockArgIface.getHostEvalBlockArgs())) {
8350 Value hostEvalVar = std::get<0>(item), blockArg = std::get<1>(item);
8354 .Case([&](omp::TeamsOp teamsOp) {
8355 if (teamsOp.getNumTeamsLower() == blockArg)
8356 numTeamsLower = hostEvalVar;
8357 else if (llvm::is_contained(teamsOp.getNumTeamsUpperVars(),
8359 numTeamsUpper = hostEvalVar;
8360 else if (!teamsOp.getThreadLimitVars().empty() &&
8361 teamsOp.getThreadLimit(0) == blockArg)
8362 threadLimit = hostEvalVar;
8364 llvm_unreachable(
"unsupported host_eval use");
8366 .Case([&](omp::ParallelOp parallelOp) {
8367 if (!parallelOp.getNumThreadsVars().empty() &&
8368 parallelOp.getNumThreads(0) == blockArg)
8369 numThreads = hostEvalVar;
8371 llvm_unreachable(
"unsupported host_eval use");
8373 .Case([&](omp::LoopNestOp loopOp) {
8374 auto processBounds =
8378 for (
auto [i, lb] : llvm::enumerate(opBounds)) {
8379 if (lb == blockArg) {
8382 (*outBounds)[i] = hostEvalVar;
8388 processBounds(loopOp.getLoopLowerBounds(), lowerBounds);
8389 found = processBounds(loopOp.getLoopUpperBounds(), upperBounds) ||
8391 found = processBounds(loopOp.getLoopSteps(), steps) || found;
8393 assert(found &&
"unsupported host_eval use");
8395 .DefaultUnreachable(
"unsupported host_eval use");
8407template <
typename OpTy>
8412 if (OpTy casted = dyn_cast<OpTy>(op))
8415 if (immediateParent)
8416 return dyn_cast_if_present<OpTy>(op->
getParentOp());
8425 return std::nullopt;
8428 if (
auto constAttr = dyn_cast<IntegerAttr>(constOp.getValue()))
8429 return constAttr.getInt();
8431 return std::nullopt;
8436 uint64_t sizeInBytes = sizeInBits / 8;
8440template <
typename OpTy>
8442 if (op.getNumReductionVars() > 0) {
8447 members.reserve(reductions.size());
8448 for (omp::DeclareReductionOp &red : reductions) {
8452 if (red.getByrefElementType())
8453 members.push_back(*red.getByrefElementType());
8455 members.push_back(red.getType());
8458 auto structType = mlir::LLVM::LLVMStructType::getLiteral(
8474 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &attrs,
8475 bool isTargetDevice,
bool isGPU) {
8478 Value numThreads, numTeamsLower, numTeamsUpper, threadLimit;
8479 if (!isTargetDevice) {
8487 numTeamsLower = teamsOp.getNumTeamsLower();
8489 if (!teamsOp.getNumTeamsUpperVars().empty())
8490 numTeamsUpper = teamsOp.getNumTeams(0);
8491 if (!teamsOp.getThreadLimitVars().empty())
8492 threadLimit = teamsOp.getThreadLimit(0);
8496 if (!parallelOp.getNumThreadsVars().empty())
8497 numThreads = parallelOp.getNumThreads(0);
8503 int32_t minTeamsVal = 1, maxTeamsVal = -1;
8507 if (numTeamsUpper) {
8509 minTeamsVal = maxTeamsVal = *val;
8511 minTeamsVal = maxTeamsVal = 0;
8517 minTeamsVal = maxTeamsVal = 1;
8519 minTeamsVal = maxTeamsVal = -1;
8524 auto setMaxValueFromClause = [](
Value clauseValue, int32_t &
result) {
8538 int32_t targetThreadLimitVal = -1, teamsThreadLimitVal = -1;
8539 if (!targetOp.getThreadLimitVars().empty())
8540 setMaxValueFromClause(targetOp.getThreadLimit(0), targetThreadLimitVal);
8541 setMaxValueFromClause(threadLimit, teamsThreadLimitVal);
8544 int32_t maxThreadsVal = -1;
8546 setMaxValueFromClause(numThreads, maxThreadsVal);
8554 int32_t combinedMaxThreadsVal = targetThreadLimitVal;
8555 if (combinedMaxThreadsVal < 0 ||
8556 (teamsThreadLimitVal >= 0 && teamsThreadLimitVal < combinedMaxThreadsVal))
8557 combinedMaxThreadsVal = teamsThreadLimitVal;
8559 if (combinedMaxThreadsVal < 0 ||
8560 (maxThreadsVal >= 0 && maxThreadsVal < combinedMaxThreadsVal))
8561 combinedMaxThreadsVal = maxThreadsVal;
8563 int32_t reductionDataSize = 0;
8564 if (isGPU && capturedOp) {
8571 omp::TargetExecMode execMode = targetOp.getKernelType();
8573 case omp::TargetExecMode::bare:
8574 attrs.ExecFlags = llvm::omp::OMP_TGT_EXEC_MODE_BARE;
8576 case omp::TargetExecMode::generic:
8577 attrs.ExecFlags = llvm::omp::OMP_TGT_EXEC_MODE_GENERIC;
8579 case omp::TargetExecMode::spmd:
8580 attrs.ExecFlags = llvm::omp::OMP_TGT_EXEC_MODE_SPMD;
8582 case omp::TargetExecMode::spmd_no_loop:
8583 attrs.ExecFlags = llvm::omp::OMP_TGT_EXEC_MODE_SPMD_NO_LOOP;
8586 attrs.MinTeams = minTeamsVal;
8587 attrs.MaxTeams.front() = maxTeamsVal;
8588 attrs.MinThreads = 1;
8589 attrs.MaxThreads.front() = combinedMaxThreadsVal;
8590 attrs.ReductionDataSize = reductionDataSize;
8602 omp::TargetOp targetOp,
Operation *capturedOp,
8603 llvm::OpenMPIRBuilder::TargetKernelRuntimeAttrs &attrs) {
8605 unsigned numLoops = loopOp ? loopOp.getNumLoops() : 0;
8607 Value numThreads, numTeamsLower, numTeamsUpper, teamsThreadLimit;
8611 teamsThreadLimit, &lowerBounds, &upperBounds, &steps);
8614 if (!targetOp.getThreadLimitVars().empty()) {
8615 Value targetThreadLimit = targetOp.getThreadLimit(0);
8616 attrs.TargetThreadLimit.front() =
8624 attrs.MinTeams = builder.CreateSExtOrTrunc(
8625 moduleTranslation.
lookupValue(numTeamsLower), builder.getInt32Ty());
8628 attrs.MaxTeams.front() = builder.CreateSExtOrTrunc(
8629 moduleTranslation.
lookupValue(numTeamsUpper), builder.getInt32Ty());
8631 if (teamsThreadLimit)
8632 attrs.TeamsThreadLimit.front() = builder.CreateSExtOrTrunc(
8633 moduleTranslation.
lookupValue(teamsThreadLimit), builder.getInt32Ty());
8636 attrs.MaxThreads = moduleTranslation.
lookupValue(numThreads);
8638 if (targetOp.hasHostEvalTripCount()) {
8640 attrs.LoopTripCount =
nullptr;
8645 for (
auto [loopLower, loopUpper, loopStep] :
8646 llvm::zip_equal(lowerBounds, upperBounds, steps)) {
8647 llvm::Value *lowerBound = moduleTranslation.
lookupValue(loopLower);
8648 llvm::Value *upperBound = moduleTranslation.
lookupValue(loopUpper);
8649 llvm::Value *step = moduleTranslation.
lookupValue(loopStep);
8651 if (!lowerBound || !upperBound || !step) {
8652 attrs.LoopTripCount =
nullptr;
8656 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
8657 llvm::Value *tripCount = ompBuilder->calculateCanonicalLoopTripCount(
8658 loc, lowerBound, upperBound, step,
true,
8659 loopOp.getLoopInclusive());
8661 if (!attrs.LoopTripCount) {
8662 attrs.LoopTripCount = tripCount;
8667 attrs.LoopTripCount = builder.CreateMul(attrs.LoopTripCount, tripCount,
8672 attrs.DeviceID = builder.getInt64(llvm::omp::OMP_DEVICEID_UNDEF);
8674 attrs.DeviceID = moduleTranslation.
lookupValue(devId);
8676 builder.CreateSExtOrTrunc(attrs.DeviceID, builder.getInt64Ty());
8680static llvm::omp::OMPDynGroupprivateFallbackType
8682 omp::FallbackModifier fb = fallbackAttr ? fallbackAttr.getValue()
8683 : omp::FallbackModifier::default_mem;
8685 case omp::FallbackModifier::abort:
8686 return llvm::omp::OMPDynGroupprivateFallbackType::Abort;
8687 case omp::FallbackModifier::null:
8688 return llvm::omp::OMPDynGroupprivateFallbackType::Null;
8689 case omp::FallbackModifier::default_mem:
8690 return llvm::omp::OMPDynGroupprivateFallbackType::DefaultMem;
8693 llvm_unreachable(
"unexpected dyn_groupprivate fallback type");
8699 auto targetOp = cast<omp::TargetOp>(opInst);
8704 llvm::DebugLoc outlinedFnLoc = builder.getCurrentDebugLocation();
8713 llvm::BasicBlock *parentBB = builder.GetInsertBlock();
8714 assert(parentBB &&
"No insert block is set for the builder");
8715 llvm::Function *parentLLVMFn = parentBB->getParent();
8716 assert(parentLLVMFn &&
"Parent Function must be valid");
8717 if (llvm::DISubprogram *SP = parentLLVMFn->getSubprogram())
8718 builder.SetCurrentDebugLocation(llvm::DILocation::get(
8719 parentLLVMFn->getContext(), outlinedFnLoc.getLine(),
8720 outlinedFnLoc.getCol(), SP, outlinedFnLoc.getInlinedAt()));
8723 bool isTargetDevice = ompBuilder->Config.isTargetDevice();
8724 bool isGPU = ompBuilder->Config.isGPU();
8727 auto argIface = cast<omp::BlockArgOpenMPOpInterface>(opInst);
8728 auto &targetRegion = targetOp.getRegion();
8745 llvm::Function *llvmOutlinedFn =
nullptr;
8746 TargetDirectiveEnumTy targetDirective =
8747 getTargetDirectiveEnumTyFromOp(&opInst);
8751 bool isOffloadEntry =
8752 isTargetDevice || !ompBuilder->Config.TargetTriples.empty();
8772 if (!targetOp.getInReductionVars().empty() && !isTargetDevice) {
8773 inRedOrigPtrs.reserve(targetOp.getInReductionVars().size());
8774 inRedMapArgIdx.reserve(targetOp.getInReductionVars().size());
8775 for (
Value v : targetOp.getInReductionVars()) {
8780 std::optional<unsigned> matchIdx;
8781 for (
auto [idx, mapV] : llvm::enumerate(targetOp.getMapVars())) {
8782 auto mapInfo = mapV.getDefiningOp<omp::MapInfoOp>();
8783 if (v != mapInfo.getVarPtr())
8786 return targetOp.emitError()
8787 <<
"in_reduction variable on omp.target has multiple matching "
8788 "map_entries entries; the redirect target is ambiguous";
8794 "TargetOp verifier guarantees a matching map_entries entry for "
8795 "each in_reduction variable");
8796 inRedMapArgIdx.push_back(*matchIdx);
8799 inRedOrigPtrs.push_back(moduleTranslation.
lookupValue(v));
8808 if (!targetOp.getPrivateVars().empty() && !targetOp.getMapVars().empty()) {
8810 std::optional<ArrayAttr> privateSyms = targetOp.getPrivateSyms();
8811 std::optional<DenseI64ArrayAttr> privateMapIndices =
8812 targetOp.getPrivateMapsAttr();
8814 for (
auto [privVarIdx, privVarSymPair] :
8815 llvm::enumerate(llvm::zip_equal(privateVars, *privateSyms))) {
8816 auto privVar = std::get<0>(privVarSymPair);
8817 auto privSym = std::get<1>(privVarSymPair);
8819 SymbolRefAttr privatizerName = llvm::cast<SymbolRefAttr>(privSym);
8820 omp::PrivateClauseOp privatizer =
8823 if (!privatizer.needsMap())
8827 targetOp.getMappedValueForPrivateVar(privVarIdx);
8828 assert(mappedValue &&
"Expected to find mapped value for a privatized "
8829 "variable that needs mapping");
8834 auto mapInfoOp = mappedValue.
getDefiningOp<omp::MapInfoOp>();
8835 [[maybe_unused]]
Type varType = mapInfoOp.getVarPtrType();
8839 if (!isa<LLVM::LLVMPointerType>(privVar.getType()))
8841 varType == privVar.getType() &&
8842 "Type of private var doesn't match the type of the mapped value");
8846 mappedPrivateVars.insert(
8848 targetRegion.getArgument(argIface.getMapBlockArgsStart() +
8849 (*privateMapIndices)[privVarIdx])});
8853 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
8854 auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
8856 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
8857 llvm::IRBuilderBase::InsertPointGuard guard(builder);
8858 builder.SetCurrentDebugLocation(llvm::DebugLoc());
8861 llvm::Function *llvmParentFn =
8863 llvmOutlinedFn = codeGenIP.getBlock()->getParent();
8864 assert(llvmParentFn && llvmOutlinedFn &&
8865 "Both parent and outlined functions must exist at this point");
8867 if (outlinedFnLoc && llvmParentFn->getSubprogram())
8868 llvmOutlinedFn->setSubprogram(outlinedFnLoc->getScope()->getSubprogram());
8870 if (
auto attr = llvmParentFn->getFnAttribute(
"target-cpu");
8871 attr.isStringAttribute())
8872 llvmOutlinedFn->addFnAttr(attr);
8874 if (
auto attr = llvmParentFn->getFnAttribute(
"target-features");
8875 attr.isStringAttribute())
8876 llvmOutlinedFn->addFnAttr(attr);
8878 for (
auto [idx, arg] : llvm::enumerate(mapBlockArgs)) {
8884 if (llvm::is_contained(inRedMapArgIdx, idx))
8886 auto mapInfoOp = cast<omp::MapInfoOp>(mapVars[idx].getDefiningOp());
8887 llvm::Value *mapOpValue =
8888 moduleTranslation.
lookupValue(mapInfoOp.getVarPtr());
8889 moduleTranslation.
mapValue(arg, mapOpValue);
8891 for (
auto [arg, mapOp] : llvm::zip_equal(hdaBlockArgs, hdaVars)) {
8892 auto mapInfoOp = cast<omp::MapInfoOp>(mapOp.getDefiningOp());
8893 llvm::Value *mapOpValue =
8894 moduleTranslation.
lookupValue(mapInfoOp.getVarPtr());
8895 moduleTranslation.
mapValue(arg, mapOpValue);
8904 privateVarsInfo, allocaIP, &mappedPrivateVars);
8907 return llvm::make_error<PreviouslyReportedError>();
8909 builder.restoreIP(codeGenIP);
8911 &mappedPrivateVars),
8914 return llvm::make_error<PreviouslyReportedError>();
8917 targetOp, builder, moduleTranslation, privateVarsInfo.
mlirVars,
8919 targetOp.getPrivateNeedsBarrier(), &mappedPrivateVars)))
8920 return llvm::make_error<PreviouslyReportedError>();
8931 if (!inRedOrigPtrs.empty()) {
8937 inRedResultPtrTys.reserve(inRedMapArgIdx.size());
8938 for (
unsigned mapArgIdx : inRedMapArgIdx)
8939 inRedResultPtrTys.push_back(
8940 moduleTranslation.
convertType(mapBlockArgs[mapArgIdx].getType()));
8942 llvm::OpenMPIRBuilder::LocationDescription bodyLoc(builder);
8943 llvm::OpenMPIRBuilder::InsertPointTy redIP =
8944 ompBuilder->createTargetInReduction(
8945 bodyLoc, inRedOrigPtrs, inRedResultPtrTys,
8946 [&](
unsigned idx, llvm::Value *priv) {
8947 moduleTranslation.
mapValue(mapBlockArgs[inRedMapArgIdx[idx]],
8950 builder.restoreIP(redIP);
8954 moduleTranslation, allocaIP, deallocBlocks);
8956 targetRegion,
"omp.target", builder, moduleTranslation);
8959 return llvm::make_error<PreviouslyReportedError>();
8961 builder.SetInsertPoint(exitBlock.get()->getTerminator());
8964 targetOp.getLoc(), privateVarsInfo)))
8965 return llvm::make_error<PreviouslyReportedError>();
8967 return builder.saveIP();
8970 StringRef parentName = parentFn.getName();
8972 llvm::TargetRegionEntryInfo entryInfo;
8978 MapInfoData mapData;
8983 MapInfosTy combinedInfos;
8985 [&](llvm::OpenMPIRBuilder::InsertPointTy codeGenIP) -> MapInfosTy & {
8986 builder.restoreIP(codeGenIP);
8987 genMapInfos(builder, moduleTranslation, dl, combinedInfos, mapData,
8992 auto *nullPtr = llvm::Constant::getNullValue(builder.getPtrTy());
8993 combinedInfos.BasePointers.push_back(nullPtr);
8994 combinedInfos.Pointers.push_back(nullPtr);
8995 combinedInfos.DevicePointers.push_back(
8996 llvm::OpenMPIRBuilder::DeviceInfoTy::None);
8997 combinedInfos.Sizes.push_back(builder.getInt64(0));
8998 combinedInfos.Types.push_back(
8999 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
9000 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
9001 if (!combinedInfos.Names.empty())
9002 combinedInfos.Names.push_back(nullPtr);
9003 combinedInfos.Mappers.push_back(
nullptr);
9005 return combinedInfos;
9008 auto argAccessorCB = [&](llvm::Argument &arg, llvm::Value *input,
9009 llvm::Value *&retVal, InsertPointTy allocaIP,
9010 InsertPointTy codeGenIP,
9012 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
9013 llvm::IRBuilderBase::InsertPointGuard guard(builder);
9014 builder.SetCurrentDebugLocation(llvm::DebugLoc());
9020 if (!isTargetDevice) {
9021 retVal = cast<llvm::Value>(&arg);
9026 builder, *ompBuilder, moduleTranslation,
9027 allocaIP, codeGenIP, deallocIPs);
9030 llvm::OpenMPIRBuilder::TargetKernelRuntimeAttrs runtimeAttrs;
9031 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs defaultAttrs;
9033 cast<omp::ComposableOpInterface>(*targetOp).findCapturedOp();
9035 isTargetDevice, isGPU);
9039 if (!isTargetDevice)
9041 targetCapturedOp, runtimeAttrs);
9049 for (
auto [arg, var] : llvm::zip_equal(hostEvalBlockArgs, hostEvalVars)) {
9050 llvm::Value *value = moduleTranslation.
lookupValue(var);
9051 moduleTranslation.
mapValue(arg, value);
9053 if (!llvm::isa<llvm::Constant>(value))
9054 kernelInput.push_back(value);
9057 for (
size_t i = 0, e = mapData.OriginalValue.size(); i != e; ++i) {
9066 bool isAttachMap = (mapData.Types[i] &
9067 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH) ==
9068 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH;
9069 if (!mapData.IsDeclareTarget[i] && !mapData.IsAMember[i] && !isAttachMap)
9070 kernelInput.push_back(mapData.OriginalValue[i]);
9074 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
9077 llvm::OpenMPIRBuilder::DependenciesInfo dds;
9079 targetOp.getDependVars(), targetOp.getDependKinds(),
9080 targetOp.getDependIterated(), targetOp.getDependIteratedKinds(),
9081 builder, moduleTranslation, dds)))
9084 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
9086 llvm::OpenMPIRBuilder::TargetDataInfo info(
9090 auto customMapperCB =
9092 if (!combinedInfos.Mappers[i])
9094 info.HasMapper =
true;
9096 moduleTranslation, targetDirective);
9099 llvm::Value *ifCond =
nullptr;
9100 if (
Value targetIfCond = targetOp.getIfExpr())
9101 ifCond = moduleTranslation.
lookupValue(targetIfCond);
9103 Value dynGroupPrivateSize = targetOp.getDynGroupprivateSize();
9104 llvm::Value *dynSizeVal =
nullptr;
9105 if (dynGroupPrivateSize) {
9106 dynSizeVal = moduleTranslation.
lookupValue(dynGroupPrivateSize);
9107 dynSizeVal = builder.CreateIntCast(dynSizeVal, builder.getInt32Ty(),
9111 llvm::omp::OMPDynGroupprivateFallbackType fallbackType =
9114 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
9116 ompLoc, isOffloadEntry, allocaIP, builder.saveIP(), deallocBlocks,
9117 info, entryInfo, defaultAttrs, runtimeAttrs, ifCond, kernelInput,
9118 genMapInfoCB, bodyCB, argAccessorCB, customMapperCB, dds,
9119 targetOp.getNowait(), dynSizeVal, fallbackType);
9124 builder.restoreIP(*afterIP);
9127 builder.CreateFree(dds.DepArray);
9140 llvm::OpenMPIRBuilder *ompBuilder,
9149 if (FunctionOpInterface funcOp = dyn_cast<FunctionOpInterface>(op)) {
9150 if (
auto offloadMod = dyn_cast<omp::OffloadModuleInterface>(
9152 if (!offloadMod.getIsTargetDevice())
9155 omp::DeclareTargetDeviceType declareType =
9156 attribute.getDeviceType().getValue();
9158 if (declareType == omp::DeclareTargetDeviceType::host) {
9159 llvm::Function *llvmFunc =
9161 llvmFunc->dropAllReferences();
9162 llvmFunc->eraseFromParent();
9166 ompBuilder->Builder.ClearInsertionPoint();
9167 ompBuilder->Builder.SetCurrentDebugLocation(llvm::DebugLoc());
9168 }
else if (llvm::Function *llvmFunc =
9180 if (!llvmFunc->isDeclaration() && llvmFunc->hasExternalLinkage() &&
9181 llvmFunc->getVisibility() == llvm::GlobalValue::DefaultVisibility)
9182 llvmFunc->setVisibility(llvm::GlobalValue::HiddenVisibility);
9188 if (LLVM::GlobalOp gOp = dyn_cast<LLVM::GlobalOp>(op)) {
9189 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
9190 if (
auto *gVal = llvmModule->getNamedValue(gOp.getSymName())) {
9191 auto *gVar = cast<llvm::GlobalVariable>(gVal);
9193 bool isDeclaration = gOp.isDeclaration();
9194 bool isExternallyVisible =
9197 llvm::StringRef mangledName = gOp.getSymName();
9198 mlir::omp::DeclareTargetCaptureClause captureClause =
9199 attribute.getCaptureClause().getValue();
9203 llvm::StringRef entryMangledName = mangledName;
9204 llvm::Constant *entryAddr = llvm::cast<llvm::Constant>(gVal);
9205 std::function<llvm::GlobalValue::LinkageTypes()> variableLinkage;
9207 bool requiresUSM = ompBuilder->Config.hasRequiresUnifiedSharedMemory();
9209 captureClause == omp::DeclareTargetCaptureClause::to ||
9210 captureClause == omp::DeclareTargetCaptureClause::enter;
9211 bool isHostOnly = attribute.getDeviceType().getValue() ==
9212 omp::DeclareTargetDeviceType::host;
9217 if (isToOrEnter && !isHostOnly && !requiresUSM &&
9218 gVar->hasLocalLinkage()) {
9219 gVar->setLinkage(llvm::GlobalValue::ExternalLinkage);
9220 isExternallyVisible =
true;
9224 if (ompBuilder->Config.isTargetDevice())
9225 gVar->setDSOLocal(
false);
9230 llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny &&
9231 !requiresUSM && !isDeclaration &&
9232 (gVal->hasLocalLinkage() || gVal->hasHiddenVisibility())) {
9236 entryNameStorage = (mangledName + llvm::Twine(
"_decl_tgt_entry")).str();
9237 entryMangledName = entryNameStorage;
9238 if (llvm::GlobalValue *existing =
9239 llvmModule->getNamedValue(entryMangledName)) {
9240 entryAddr = llvm::cast<llvm::Constant>(existing);
9242 entryAddr = llvm::GlobalAlias::create(
9243 gVal->getValueType(), gVal->getAddressSpace(),
9244 llvm::GlobalValue::WeakAnyLinkage, entryMangledName, entryAddr,
9246 llvm::cast<llvm::GlobalAlias>(entryAddr)->setVisibility(
9247 llvm::GlobalValue::DefaultVisibility);
9249 variableLinkage = [] {
return llvm::GlobalValue::WeakAnyLinkage; };
9253 std::vector<llvm::GlobalVariable *> generatedRefs;
9255 std::vector<llvm::Triple> targetTriple;
9256 auto targetTripleAttr = dyn_cast_or_null<mlir::StringAttr>(
9258 LLVM::LLVMDialect::getTargetTripleAttrName()));
9259 if (targetTripleAttr)
9260 targetTriple.emplace_back(targetTripleAttr.data());
9262 auto fileInfoCallBack = [&loc]() {
9263 std::string filename =
"";
9264 std::uint64_t lineNo = 0;
9267 filename = loc.getFilename().str();
9268 lineNo = loc.getLine();
9271 return std::pair<std::string, std::uint64_t>(llvm::StringRef(filename),
9275 llvm::vfs::FileSystem &vfs = moduleTranslation.
getFileSystem();
9276 ompBuilder->registerTargetGlobalVariable(
9277 captureClauseKind, deviceClause, isDeclaration, isExternallyVisible,
9278 ompBuilder->getTargetEntryUniqueInfo(fileInfoCallBack, vfs),
9279 entryMangledName, generatedRefs,
false, targetTriple,
9280 nullptr, variableLinkage, gVal->getType(),
9283 if (ompBuilder->Config.isTargetDevice() &&
9284 (captureClause == omp::DeclareTargetCaptureClause::link ||
9286 llvm::Type *ptrTy = gVal->getType();
9290 ptrTy = llvm::PointerType::get(llvmModule->getContext(), 0);
9291 bool addrGlobalCreated = ompBuilder->getAddrOfDeclareTargetVar(
9292 captureClauseKind, deviceClause, isDeclaration, isExternallyVisible,
9293 ompBuilder->getTargetEntryUniqueInfo(fileInfoCallBack, vfs),
9294 mangledName, generatedRefs,
false, targetTriple,
9302 if (addrGlobalCreated)
9303 gVar->setLinkage(llvm::GlobalValue::InternalLinkage);
9309 if (ompBuilder->Config.isTargetDevice() && isHostOnly && isToOrEnter) {
9310 gVar->setLinkage(llvm::GlobalValue::ExternalLinkage);
9311 gVar->setInitializer(
nullptr);
9323class OpenMPDialectLLVMIRTranslationInterface
9324 :
public LLVMTranslationDialectInterface {
9326 using LLVMTranslationDialectInterface::LLVMTranslationDialectInterface;
9331 convertOperation(Operation *op, llvm::IRBuilderBase &builder,
9332 LLVM::ModuleTranslation &moduleTranslation)
const final;
9337 amendOperation(Operation *op, ArrayRef<llvm::Instruction *> instructions,
9338 NamedAttribute attribute,
9339 LLVM::ModuleTranslation &moduleTranslation)
const final;
9344 void registerAllocatedPtr(Value var, llvm::Value *ptr)
const {
9345 ompAllocatedPtrs[var] = ptr;
9350 llvm::Value *lookupAllocatedPtr(Value var)
const {
9351 auto it = ompAllocatedPtrs.find(var);
9352 return it != ompAllocatedPtrs.end() ? it->second :
nullptr;
9364LogicalResult OpenMPDialectLLVMIRTranslationInterface::amendOperation(
9365 Operation *op, ArrayRef<llvm::Instruction *> instructions,
9366 NamedAttribute attribute,
9367 LLVM::ModuleTranslation &moduleTranslation)
const {
9368 return llvm::StringSwitch<llvm::function_ref<LogicalResult(Attribute)>>(
9370 .Case(
"omp.is_target_device",
9371 [&](Attribute attr) {
9372 if (
auto deviceAttr = dyn_cast<BoolAttr>(attr)) {
9373 llvm::OpenMPIRBuilderConfig &config =
9375 config.setIsTargetDevice(deviceAttr.getValue());
9381 [&](Attribute attr) {
9382 if (
auto gpuAttr = dyn_cast<BoolAttr>(attr)) {
9383 llvm::OpenMPIRBuilderConfig &config =
9385 config.setIsGPU(gpuAttr.getValue());
9390 .Case(
"omp.host_ir_filepath",
9391 [&](Attribute attr) {
9392 if (
auto filepathAttr = dyn_cast<StringAttr>(attr)) {
9393 llvm::OpenMPIRBuilder *ompBuilder =
9395 ompBuilder->loadOffloadInfoMetadata(
9396 moduleTranslation.
getFileSystem(), filepathAttr.getValue());
9402 [&](Attribute attr) {
9403 if (
auto rtlAttr = dyn_cast<omp::FlagsAttr>(attr))
9407 .Case(
"omp.version",
9408 [&](Attribute attr) {
9409 if (
auto versionAttr = dyn_cast<omp::VersionAttr>(attr)) {
9410 llvm::OpenMPIRBuilder *ompBuilder =
9412 ompBuilder->M.addModuleFlag(llvm::Module::Max,
"openmp",
9413 versionAttr.getVersion());
9418 .Case(
"omp.declare_target",
9419 [&](Attribute attr) {
9420 if (
auto declareTargetAttr =
9421 dyn_cast<omp::DeclareTargetAttr>(attr)) {
9422 llvm::OpenMPIRBuilder *ompBuilder =
9425 ompBuilder, moduleTranslation);
9429 .Case(
"omp.requires",
9430 [&](Attribute attr) {
9431 if (
auto requiresAttr = dyn_cast<omp::ClauseRequiresAttr>(attr)) {
9432 using Requires = omp::ClauseRequires;
9433 Requires flags = requiresAttr.getValue();
9434 llvm::OpenMPIRBuilderConfig &config =
9436 config.setHasRequiresReverseOffload(
9437 bitEnumContainsAll(flags, Requires::reverse_offload));
9438 config.setHasRequiresUnifiedAddress(
9439 bitEnumContainsAll(flags, Requires::unified_address));
9440 config.setHasRequiresUnifiedSharedMemory(
9441 bitEnumContainsAll(flags, Requires::unified_shared_memory));
9442 config.setHasRequiresDynamicAllocators(
9443 bitEnumContainsAll(flags, Requires::dynamic_allocators));
9448 .Case(
"omp.target_triples",
9449 [&](Attribute attr) {
9450 if (
auto triplesAttr = dyn_cast<ArrayAttr>(attr)) {
9451 llvm::OpenMPIRBuilderConfig &config =
9453 config.TargetTriples.clear();
9454 config.TargetTriples.reserve(triplesAttr.size());
9455 for (Attribute tripleAttr : triplesAttr) {
9456 if (
auto tripleStrAttr = dyn_cast<StringAttr>(tripleAttr))
9457 config.TargetTriples.emplace_back(tripleStrAttr.getValue());
9465 .Default([](Attribute) {
9481 if (
auto declareTargetIface =
9482 llvm::dyn_cast<mlir::omp::DeclareTargetInterface>(
9483 parentFn.getOperation()))
9484 if (declareTargetIface.isDeclareTarget() &&
9485 declareTargetIface.getDeclareTargetDeviceType() !=
9486 mlir::omp::DeclareTargetDeviceType::host)
9496 llvm::Module *llvmModule) {
9497 llvm::Type *i64Ty = builder.getInt64Ty();
9498 llvm::Type *i32Ty = builder.getInt32Ty();
9499 llvm::Type *returnType = builder.getPtrTy(0);
9500 llvm::FunctionType *fnType =
9501 llvm::FunctionType::get(returnType, {i64Ty, i32Ty},
false);
9502 llvm::Function *
func = cast<llvm::Function>(
9503 llvmModule->getOrInsertFunction(
"omp_target_alloc", fnType).getCallee());
9507template <
typename T>
9511 llvm::DataLayout dataLayout =
9513 llvm::Type *llvmHeapTy =
9514 moduleTranslation.
convertType(op.getMemElemTypeAttr().getValue());
9516 auto alignment = op.getMemAlignment();
9517 llvm::TypeSize typeSize = llvm::alignTo(
9518 dataLayout.getTypeStoreSize(llvmHeapTy),
9519 alignment ? *alignment : dataLayout.getABITypeAlign(llvmHeapTy).value());
9521 llvm::Value *allocSize = builder.getInt64(typeSize.getFixedValue());
9522 return builder.CreateMul(
9524 builder.CreateIntCast(moduleTranslation.
lookupValue(op.getMemArraySize()),
9525 builder.getInt64Ty(),
9532 omp::TargetAllocMemOp op) {
9533 llvm::DataLayout dataLayout =
9535 llvm::Type *llvmHeapTy = moduleTranslation.
convertType(op.getAllocatedType());
9536 llvm::TypeSize typeSize = dataLayout.getTypeAllocSize(llvmHeapTy);
9537 llvm::Value *allocSize = builder.getInt64(typeSize.getFixedValue());
9538 for (
auto typeParam : op.getTypeparams()) {
9539 allocSize = builder.CreateMul(
9541 builder.CreateIntCast(moduleTranslation.
lookupValue(typeParam),
9542 builder.getInt64Ty(),
9551 auto allocMemOp = cast<omp::TargetAllocMemOp>(opInst);
9556 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
9560 llvm::Value *llvmDeviceNum = moduleTranslation.
lookupValue(deviceNum);
9562 llvm::Value *allocSize =
9565 llvm::CallInst *call =
9566 builder.CreateCall(ompTargetAllocFunc, {allocSize, llvmDeviceNum});
9567 llvm::Value *resultI64 = builder.CreatePtrToInt(call, builder.getInt64Ty());
9570 moduleTranslation.
mapValue(allocMemOp.getResult(), resultI64);
9576 llvm::IRBuilderBase &builder,
9580 moduleTranslation.
mapValue(allocMemOp.getResult(),
9581 ompBuilder->createOMPAllocShared(builder, size));
9588 const OpenMPDialectLLVMIRTranslationInterface &ompIface) {
9589 auto allocateDirOp = cast<omp::AllocateDirOp>(opInst);
9592 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
9593 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
9594 llvm::DataLayout dataLayout = llvmModule->getDataLayout();
9596 std::optional<int64_t> alignAttr = allocateDirOp.getAlign();
9598 llvm::Value *allocator;
9599 if (
auto allocatorVar = allocateDirOp.getAllocator()) {
9600 allocator = moduleTranslation.
lookupValue(allocatorVar);
9601 if (allocator->getType()->isIntegerTy())
9602 allocator = builder.CreateIntToPtr(allocator, builder.getPtrTy());
9603 else if (allocator->getType()->isPointerTy())
9604 allocator = builder.CreatePointerBitCastOrAddrSpaceCast(
9605 allocator, builder.getPtrTy());
9607 allocator = llvm::ConstantPointerNull::get(builder.getPtrTy());
9610 for (
Value var : vars) {
9611 llvm::Type *llvmVarTy = moduleTranslation.
convertType(var.getType());
9615 llvm::Type *typeToInspect = llvmVarTy;
9616 if (llvmVarTy->isPointerTy()) {
9619 if (
auto gop = dyn_cast<LLVM::GlobalOp>(globalOp))
9620 typeToInspect = moduleTranslation.
convertType(gop.getGlobalType());
9625 if (
auto arrTy = llvm::dyn_cast<llvm::ArrayType>(typeToInspect)) {
9626 llvm::Value *elementCount = builder.getInt64(1);
9627 llvm::Type *currentType = arrTy;
9628 while (
auto nestedArrTy = llvm::dyn_cast<llvm::ArrayType>(currentType)) {
9629 elementCount = builder.CreateMul(
9630 elementCount, builder.getInt64(nestedArrTy->getNumElements()));
9631 currentType = nestedArrTy->getElementType();
9633 uint64_t elemSizeInBits = dataLayout.getTypeSizeInBits(currentType);
9635 builder.CreateMul(elementCount, builder.getInt64(elemSizeInBits / 8));
9637 size = builder.getInt64(
9638 dataLayout.getTypeStoreSize(typeToInspect).getFixedValue());
9641 uint64_t alignValue =
9642 alignAttr ? alignAttr.value()
9643 : dataLayout.getABITypeAlign(typeToInspect).value();
9644 llvm::Value *alignConst = builder.getInt64(alignValue);
9646 size = builder.CreateAdd(size, builder.getInt64(alignValue - 1),
"",
true);
9647 size = builder.CreateUDiv(size, alignConst);
9648 size = builder.CreateMul(size, alignConst,
"",
true);
9650 std::string allocName =
9651 ompBuilder->createPlatformSpecificName({
".void.addr"});
9652 llvm::CallInst *allocCall;
9653 if (alignAttr.has_value()) {
9654 allocCall = ompBuilder->createOMPAlignedAlloc(
9655 ompLoc, builder.getInt64(alignAttr.value()), size, allocator,
9659 ompBuilder->createOMPAlloc(ompLoc, size, allocator, allocName);
9662 ompIface.registerAllocatedPtr(var, allocCall);
9671 const OpenMPDialectLLVMIRTranslationInterface &ompIface) {
9672 auto freeOp = cast<omp::AllocateFreeOp>(opInst);
9674 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
9676 llvm::Value *allocator;
9677 if (
auto allocatorVar = freeOp.getAllocator()) {
9678 allocator = moduleTranslation.
lookupValue(allocatorVar);
9679 if (allocator->getType()->isIntegerTy())
9680 allocator = builder.CreateIntToPtr(allocator, builder.getPtrTy());
9681 else if (allocator->getType()->isPointerTy())
9682 allocator = builder.CreatePointerBitCastOrAddrSpaceCast(
9683 allocator, builder.getPtrTy());
9685 allocator = llvm::ConstantPointerNull::get(builder.getPtrTy());
9690 for (
Value var : llvm::reverse(vars)) {
9691 llvm::Value *allocPtr = ompIface.lookupAllocatedPtr(var);
9693 return opInst.
emitError(
"omp.allocate_free: no allocation recorded");
9694 ompBuilder->createOMPFree(ompLoc, allocPtr, allocator,
"");
9701 llvm::Module *llvmModule) {
9702 llvm::Type *ptrTy = builder.getPtrTy(0);
9703 llvm::Type *i32Ty = builder.getInt32Ty();
9704 llvm::Type *voidTy = builder.getVoidTy();
9705 llvm::FunctionType *fnType =
9706 llvm::FunctionType::get(voidTy, {ptrTy, i32Ty},
false);
9707 llvm::Function *
func = dyn_cast<llvm::Function>(
9708 llvmModule->getOrInsertFunction(
"omp_target_free", fnType).getCallee());
9715 auto freeMemOp = cast<omp::TargetFreeMemOp>(opInst);
9720 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
9724 llvm::Value *llvmDeviceNum = moduleTranslation.
lookupValue(deviceNum);
9727 llvm::Value *llvmHeapref = moduleTranslation.
lookupValue(heapref);
9729 llvm::Value *intToPtr =
9730 builder.CreateIntToPtr(llvmHeapref, builder.getPtrTy(0));
9731 builder.CreateCall(ompTragetFreeFunc, {intToPtr, llvmDeviceNum});
9737 llvm::IRBuilderBase &builder,
9741 ompBuilder->createOMPFreeShared(
9742 builder, moduleTranslation.
lookupValue(freeMemOp.getHeapref()), size);
9751 auto groupprivateOp = cast<omp::GroupprivateOp>(opInst);
9756 bool isTargetDevice = ompBuilder->Config.isTargetDevice();
9760 bool shouldAllocate =
true;
9761 switch (groupprivateOp.getDeviceType().value_or(
9762 mlir::omp::DeclareTargetDeviceType::any)) {
9763 case mlir::omp::DeclareTargetDeviceType::host:
9764 shouldAllocate = !isTargetDevice;
9766 case mlir::omp::DeclareTargetDeviceType::nohost:
9767 shouldAllocate = isTargetDevice;
9769 case mlir::omp::DeclareTargetDeviceType::any:
9770 shouldAllocate =
true;
9776 &opInst, groupprivateOp.getSymNameAttr());
9779 <<
"expected symbol '" << groupprivateOp.getSymName()
9780 <<
"' to reference an LLVM global variable";
9782 llvm::GlobalValue *globalValue = moduleTranslation.
lookupGlobal(global);
9783 llvm::Type *varType = moduleTranslation.
convertType(global.getType());
9784 std::string varName = globalValue->getName().str();
9786 llvm::Value *resultPtr;
9787 if (shouldAllocate && isTargetDevice) {
9788 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
9789 llvm::Triple targetTriple(llvmModule->getTargetTriple());
9790 unsigned sharedAddressSpace;
9791 if (targetTriple.isAMDGCN())
9792 sharedAddressSpace = llvm::AMDGPUAS::LOCAL_ADDRESS;
9793 else if (targetTriple.isNVPTX())
9794 sharedAddressSpace = llvm::NVPTXAS::ADDRESS_SPACE_SHARED;
9796 return opInst.
emitError() <<
"groupprivate is not supported for target: "
9797 << targetTriple.str();
9798 llvm::GlobalVariable *sharedVar =
new llvm::GlobalVariable(
9799 *llvmModule, varType,
false,
9800 llvm::GlobalValue::InternalLinkage, llvm::PoisonValue::get(varType),
9801 varName,
nullptr, llvm::GlobalValue::NotThreadLocal,
9804 resultPtr = sharedVar;
9806 if (shouldAllocate && !isTargetDevice)
9807 opInst.
emitWarning(
"groupprivate directive is currently ignored on the "
9808 "host, using original global");
9809 resultPtr = globalValue;
9818LogicalResult OpenMPDialectLLVMIRTranslationInterface::convertOperation(
9819 Operation *op, llvm::IRBuilderBase &builder,
9820 LLVM::ModuleTranslation &moduleTranslation)
const {
9823 if (ompBuilder->Config.isTargetDevice() &&
9824 !isa<omp::TargetOp, omp::MapInfoOp, omp::TerminatorOp, omp::YieldOp>(
9827 return op->
emitOpError() <<
"unsupported host op found in device";
9835 bool isOutermostLoopWrapper =
9836 isa_and_present<omp::LoopWrapperInterface>(op) &&
9837 !dyn_cast_if_present<omp::LoopWrapperInterface>(op->
getParentOp());
9846 if (isa<omp::TaskloopContextOp>(op))
9847 isOutermostLoopWrapper =
true;
9848 else if (isa<omp::TaskloopWrapperOp>(op))
9849 isOutermostLoopWrapper =
false;
9851 if (isOutermostLoopWrapper)
9852 moduleTranslation.
stackPush<OpenMPLoopInfoStackFrame>();
9855 llvm::TypeSwitch<Operation *, LogicalResult>(op)
9856 .Case([&](omp::BarrierOp op) -> LogicalResult {
9860 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
9861 ompBuilder->createBarrier(builder, llvm::omp::OMPD_barrier);
9863 if (res.succeeded()) {
9866 builder.restoreIP(*afterIP);
9870 .Case([&](omp::TaskyieldOp op) {
9874 ompBuilder->createTaskyield(builder);
9877 .Case([&](omp::FlushOp op) {
9889 ompBuilder->createFlush(builder);
9892 .Case([&](omp::ErrorOp op) {
9896 llvm::Value *message =
nullptr;
9897 if (mlir::Value messageExpr = op.getMessageExpr())
9898 message = moduleTranslation.
lookupValue(messageExpr);
9899 else if (std::optional<StringRef> msg = op.getMessage();
9900 msg && !msg->empty())
9901 message = builder.CreateGlobalString(*msg);
9902 ompBuilder->createError(
9903 llvm::OpenMPIRBuilder::LocationDescription(builder),
9904 op.getSeverity() == omp::ClauseSeverity::fatal, message);
9907 .Case([&](omp::ParallelOp op) {
9910 .Case([&](omp::MaskedOp) {
9913 .Case([&](omp::MasterOp) {
9916 .Case([&](omp::CriticalOp) {
9919 .Case([&](omp::OrderedRegionOp) {
9922 .Case([&](omp::OrderedOp) {
9925 .Case([&](omp::WsloopOp) {
9928 .Case([&](omp::SimdOp) {
9931 .Case([&](omp::AtomicReadOp) {
9934 .Case([&](omp::AtomicWriteOp) {
9937 .Case([&](omp::AtomicUpdateOp op) {
9940 .Case([&](omp::AtomicCaptureOp op) {
9943 .Case([&](omp::AtomicCompareOp op) {
9946 .Case([&](omp::CancelOp op) {
9949 .Case([&](omp::CancellationPointOp op) {
9952 .Case([&](omp::SectionsOp) {
9955 .Case([&](omp::ScopeOp op) {
9958 .Case([&](omp::SingleOp op) {
9961 .Case([&](omp::TeamsOp op) {
9964 .Case([&](omp::TaskOp op) {
9967 .Case([&](omp::TaskloopWrapperOp op) {
9970 .Case([&](omp::TaskloopContextOp op) {
9973 .Case([&](omp::TaskgroupOp op) {
9976 .Case([&](omp::TaskwaitOp op) {
9979 .Case([&](omp::InteropInitOp op) {
9982 .Case([&](omp::InteropDestroyOp op) {
9985 .Case([&](omp::InteropUseOp op) {
9988 .Case<omp::YieldOp, omp::TerminatorOp, omp::DeclareMapperOp,
9989 omp::DeclareMapperInfoOp, omp::DeclareReductionOp,
9990 omp::CriticalDeclareOp>([](
auto op) {
10003 .Case([&](omp::ThreadprivateOp) {
10006 .Case<omp::TargetDataOp, omp::TargetEnterDataOp,
10007 omp::TargetExitDataOp, omp::TargetUpdateOp>([&](
auto op) {
10010 .Case([&](omp::TargetOp) {
10013 .Case([&](omp::DistributeOp) {
10016 .Case([&](omp::LoopNestOp) {
10019 .Case<omp::MapInfoOp, omp::MapBoundsOp, omp::PrivateClauseOp,
10020 omp::AffinityEntryOp, omp::IteratorOp>([&](
auto op) {
10026 .Case([&](omp::NewCliOp op) {
10031 .Case([&](omp::CanonicalLoopOp op) {
10034 .Case([&](omp::UnrollHeuristicOp op) {
10043 .Case([&](omp::UnrollPartialOp op) {
10046 .Case([&](omp::TileOp op) {
10047 return applyTile(op, builder, moduleTranslation);
10049 .Case([&](omp::FuseOp op) {
10050 return applyFuse(op, builder, moduleTranslation);
10052 .Case([&](omp::TargetAllocMemOp) {
10055 .Case([&](omp::TargetFreeMemOp) {
10058 .Case([&](omp::AllocateDirOp) {
10061 .Case([&](omp::AllocateFreeOp) {
10065 .Case([&](omp::AllocSharedMemOp op) {
10068 .Case([&](omp::FreeSharedMemOp op) {
10071 .Case([&](omp::GroupprivateOp) {
10074 .Default([&](Operation *inst) {
10076 <<
"not yet implemented: " << inst->
getName();
10079 if (isOutermostLoopWrapper)
10086 registry.
insert<omp::OpenMPDialect>();
10088 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 convertOmpInteropUseOp(omp::InteropUseOp useOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
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 LogicalResult convertOmpInteropInitOp(omp::InteropInitOp initOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
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 applyUnrollPartial(omp::UnrollPartialOp op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Apply a #pragma omp unroll partial / !$omp unroll partial transformation using the OpenMPIRBuilder.
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 convertOmpInteropDestroyOp(omp::InteropDestroyOp destroyOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
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.
user_range getUsers() const
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.