27#include "llvm/ADT/ArrayRef.h"
28#include "llvm/ADT/SmallVector.h"
29#include "llvm/ADT/TypeSwitch.h"
30#include "llvm/Frontend/OpenMP/OMPConstants.h"
31#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
32#include "llvm/IR/Constants.h"
33#include "llvm/IR/DebugInfoMetadata.h"
34#include "llvm/IR/DerivedTypes.h"
35#include "llvm/IR/IRBuilder.h"
36#include "llvm/IR/MDBuilder.h"
37#include "llvm/IR/ReplaceConstant.h"
38#include "llvm/Support/AMDGPUAddrSpace.h"
39#include "llvm/Support/FileSystem.h"
40#include "llvm/Support/MathExtras.h"
41#include "llvm/Support/NVPTXAddrSpace.h"
42#include "llvm/Support/VirtualFileSystem.h"
43#include "llvm/TargetParser/Triple.h"
44#include "llvm/Transforms/Utils/ModuleUtils.h"
55static llvm::omp::ScheduleKind
56convertToScheduleKind(std::optional<omp::ClauseScheduleKind> schedKind) {
57 if (!schedKind.has_value())
58 return llvm::omp::OMP_SCHEDULE_Default;
59 switch (schedKind.value()) {
60 case omp::ClauseScheduleKind::Static:
61 return llvm::omp::OMP_SCHEDULE_Static;
62 case omp::ClauseScheduleKind::Dynamic:
63 return llvm::omp::OMP_SCHEDULE_Dynamic;
64 case omp::ClauseScheduleKind::Guided:
65 return llvm::omp::OMP_SCHEDULE_Guided;
66 case omp::ClauseScheduleKind::Auto:
67 return llvm::omp::OMP_SCHEDULE_Auto;
68 case omp::ClauseScheduleKind::Runtime:
69 return llvm::omp::OMP_SCHEDULE_Runtime;
70 case omp::ClauseScheduleKind::Distribute:
71 return llvm::omp::OMP_SCHEDULE_Distribute;
73 llvm_unreachable(
"unhandled schedule clause argument");
78class OpenMPAllocStackFrame
83 explicit OpenMPAllocStackFrame(
84 llvm::OpenMPIRBuilder::InsertPointTy allocaIP,
85 llvm::ArrayRef<llvm::BasicBlock *> deallocBlocks)
86 : allocInsertPoint(allocaIP), deallocBlocks(deallocBlocks) {}
87 llvm::OpenMPIRBuilder::InsertPointTy allocInsertPoint;
88 llvm::SmallVector<llvm::BasicBlock *> deallocBlocks;
94class OpenMPLoopInfoStackFrame
98 llvm::CanonicalLoopInfo *loopInfo =
nullptr;
117class PreviouslyReportedError
118 :
public llvm::ErrorInfo<PreviouslyReportedError> {
120 void log(raw_ostream &)
const override {
124 std::error_code convertToErrorCode()
const override {
126 "PreviouslyReportedError doesn't support ECError conversion");
133char PreviouslyReportedError::ID = 0;
144class LinearClauseProcessor {
147 SmallVector<llvm::Value *> linearPreconditionVars;
148 SmallVector<llvm::Value *> linearLoopBodyTemps;
149 SmallVector<llvm::Value *> linearOrigVal;
150 SmallVector<llvm::Value *> linearSteps;
151 SmallVector<llvm::Type *> linearVarTypes;
152 llvm::BasicBlock *linearFinalizationBB;
153 llvm::BasicBlock *linearExitBB;
154 llvm::BasicBlock *linearLastIterExitBB;
159 void registerType(LLVM::ModuleTranslation &moduleTranslation,
160 mlir::Attribute &ty) {
161 linearVarTypes.push_back(moduleTranslation.
convertType(
162 mlir::cast<mlir::TypeAttr>(ty).getValue()));
166 void createLinearVar(llvm::IRBuilderBase &builder,
167 LLVM::ModuleTranslation &moduleTranslation,
168 llvm::Value *linearVar,
int idx) {
169 linearPreconditionVars.push_back(
170 builder.CreateAlloca(linearVarTypes[idx],
nullptr,
".linear_var"));
171 llvm::Value *linearLoopBodyTemp =
172 builder.CreateAlloca(linearVarTypes[idx],
nullptr,
".linear_result");
173 linearOrigVal.push_back(linearVar);
174 linearLoopBodyTemps.push_back(linearLoopBodyTemp);
178 inline void initLinearStep(LLVM::ModuleTranslation &moduleTranslation,
179 mlir::Value &linearStep) {
180 linearSteps.push_back(moduleTranslation.
lookupValue(linearStep));
184 void initLinearVar(llvm::IRBuilderBase &builder,
185 LLVM::ModuleTranslation &moduleTranslation,
186 llvm::BasicBlock *loopPreHeader) {
187 builder.SetInsertPoint(loopPreHeader->getTerminator());
188 for (
size_t index = 0; index < linearOrigVal.size(); index++) {
189 llvm::LoadInst *linearVarLoad =
190 builder.CreateLoad(linearVarTypes[index], linearOrigVal[index]);
191 builder.CreateStore(linearVarLoad, linearPreconditionVars[index]);
196 LogicalResult initLinearIV(omp::SimdOp simdOp) {
197 auto loopOp = cast<omp::LoopNestOp>(simdOp.getWrappedLoop());
199 if (loopOp.getIVs().size() != 1)
207 BlockArgument arg = loopOp.getIVs().front();
208 for (
const Operation *user : arg.
getUsers()) {
209 if (
auto storeOp = dyn_cast<LLVM::StoreOp>(user)) {
210 for (Value linearVar : simdOp.getLinearVars()) {
211 if (linearVar == storeOp.getAddr()) {
212 if (linearLoopIV && linearLoopIV != linearVar)
213 return simdOp.emitError(
214 "Could not determine the linear variable associated with the "
215 "loop nest induction variable");
216 linearLoopIV = linearVar;
225 void updateLinearVar(llvm::IRBuilderBase &builder, llvm::BasicBlock *loopBody,
226 llvm::Value *loopInductionVar) {
227 builder.SetInsertPoint(loopBody->getTerminator());
228 for (
size_t index = 0; index < linearPreconditionVars.size(); index++) {
229 llvm::Type *linearVarType = linearVarTypes[index];
230 llvm::Value *iv = loopInductionVar;
231 llvm::Value *step = linearSteps[index];
233 if (!iv->getType()->isIntegerTy())
234 llvm_unreachable(
"OpenMP loop induction variable must be an integer "
237 if (linearVarType->isIntegerTy()) {
239 iv = builder.CreateSExtOrTrunc(iv, linearVarType);
240 step = builder.CreateSExtOrTrunc(step, linearVarType);
242 llvm::LoadInst *linearVarStart =
243 builder.CreateLoad(linearVarType, linearPreconditionVars[index]);
244 llvm::Value *mulInst = builder.CreateMul(iv, step);
245 llvm::Value *addInst = builder.CreateAdd(linearVarStart, mulInst);
246 builder.CreateStore(addInst, linearLoopBodyTemps[index]);
247 }
else if (linearVarType->isFloatingPointTy()) {
249 step = builder.CreateSExtOrTrunc(step, iv->getType());
250 llvm::Value *mulInst = builder.CreateMul(iv, step);
252 llvm::LoadInst *linearVarStart =
253 builder.CreateLoad(linearVarType, linearPreconditionVars[index]);
254 llvm::Value *mulFp = builder.CreateSIToFP(mulInst, linearVarType);
255 llvm::Value *addInst = builder.CreateFAdd(linearVarStart, mulFp);
256 builder.CreateStore(addInst, linearLoopBodyTemps[index]);
259 "Linear variable must be of integer or floating-point type");
265 void updateLinearIV(llvm::IRBuilderBase &builder,
266 LLVM::ModuleTranslation &moduleTranslation) {
269 llvm::Value *linearIV = moduleTranslation.
lookupValue(linearLoopIV);
273 for (index = 0; index < linearOrigVal.size(); index++)
274 if (linearIV == linearOrigVal[index])
276 if (index == linearOrigVal.size())
280 llvm::Type *varType = linearVarTypes[index];
281 llvm::Value *var = linearLoopBodyTemps[index];
282 llvm::Value *step = linearSteps[index];
283 if (!varType->isIntegerTy())
284 llvm_unreachable(
"Linear iteration variable must be of integer type");
286 step = builder.CreateSExtOrTrunc(step, varType);
287 llvm::Value *val = builder.CreateLoad(varType, var);
288 llvm::Value *addInst = builder.CreateAdd(val, step);
289 builder.CreateStore(addInst, var);
294 void splitLinearFiniBB(llvm::IRBuilderBase &builder,
295 llvm::BasicBlock *loopExit) {
296 linearFinalizationBB = loopExit->splitBasicBlock(
297 loopExit->getTerminator(),
"omp_loop.linear_finalization");
298 linearExitBB = linearFinalizationBB->splitBasicBlock(
299 linearFinalizationBB->getTerminator(),
"omp_loop.linear_exit");
300 linearLastIterExitBB = linearFinalizationBB->splitBasicBlock(
301 linearFinalizationBB->getTerminator(),
"omp_loop.linear_lastiter_exit");
305 llvm::OpenMPIRBuilder::InsertPointOrErrorTy
306 finalizeLinearVar(llvm::IRBuilderBase &builder,
307 LLVM::ModuleTranslation &moduleTranslation,
308 llvm::Value *lastIter) {
310 builder.SetInsertPoint(linearFinalizationBB->getTerminator());
311 llvm::Value *loopLastIterLoad = builder.CreateLoad(
312 llvm::Type::getInt32Ty(builder.getContext()), lastIter);
313 llvm::Value *isLast =
314 builder.CreateCmp(llvm::CmpInst::ICMP_NE, loopLastIterLoad,
315 llvm::ConstantInt::get(
316 llvm::Type::getInt32Ty(builder.getContext()), 0));
318 builder.SetInsertPoint(linearLastIterExitBB->getTerminator());
319 for (
size_t index = 0; index < linearOrigVal.size(); index++) {
320 llvm::LoadInst *linearVarTemp =
321 builder.CreateLoad(linearVarTypes[index], linearLoopBodyTemps[index]);
322 builder.CreateStore(linearVarTemp, linearOrigVal[index]);
328 builder.SetInsertPoint(linearFinalizationBB->getTerminator());
329 builder.CreateCondBr(isLast, linearLastIterExitBB, linearExitBB);
330 linearFinalizationBB->getTerminator()->eraseFromParent();
332 builder.SetInsertPoint(linearExitBB->getTerminator());
334 builder, llvm::omp::OMPD_barrier);
339 void emitStoresForLinearVar(llvm::IRBuilderBase &builder) {
340 for (
size_t index = 0; index < linearOrigVal.size(); index++) {
341 llvm::LoadInst *linearVarTemp =
342 builder.CreateLoad(linearVarTypes[index], linearLoopBodyTemps[index]);
343 builder.CreateStore(linearVarTemp, linearOrigVal[index]);
349 void rewriteInPlace(llvm::IRBuilderBase &builder, llvm::BasicBlock *startBB,
350 llvm::BasicBlock *endBB,
size_t varIndex) {
351 llvm::SmallVector<llvm::BasicBlock *, 32> worklist;
352 llvm::SmallPtrSet<llvm::BasicBlock *, 32> collectedBBs;
354 assert(startBB && endBB &&
"Invalid startBB/endBB");
357 worklist.push_back(startBB);
358 collectedBBs.insert(startBB);
360 while (!worklist.empty()) {
361 llvm::BasicBlock *bb = worklist.pop_back_val();
366 for (llvm::BasicBlock *succ : llvm::successors(bb)) {
367 if (collectedBBs.insert(succ).second)
368 worklist.push_back(succ);
373 llvm::SmallVector<llvm::User *> users(linearOrigVal[varIndex]->users());
374 for (
auto *user : users) {
375 if (
auto *userInst = dyn_cast<llvm::Instruction>(user)) {
376 if (collectedBBs.contains(userInst->getParent()))
377 user->replaceUsesOfWith(linearOrigVal[varIndex],
378 linearLoopBodyTemps[varIndex]);
389 SymbolRefAttr symbolName) {
390 omp::PrivateClauseOp privatizer =
393 assert(privatizer &&
"privatizer not found in the symbol table");
404 auto todo = [&op](StringRef clauseName) {
405 return op.
emitError() <<
"not yet implemented: Unhandled clause "
406 << clauseName <<
" in " << op.
getName()
410 auto checkAllocate = [&todo](
auto op, LogicalResult &
result) {
411 if (!op.getAllocateVars().empty() || !op.getAllocatorVars().empty())
412 result = todo(
"allocate");
414 auto checkBare = [&todo](
auto op, LogicalResult &
result) {
415 if (op.getKernelType() == omp::TargetExecMode::bare)
416 result = todo(
"ompx_bare");
418 auto checkDepend = [&todo](
auto op, LogicalResult &
result) {
419 if (!op.getDependVars().empty() || op.getDependKinds())
422 auto checkHint = [](
auto op, LogicalResult &) {
426 auto checkInReduction = [&todo](
auto op, LogicalResult &
result) {
427 if (isa<omp::TargetOp, omp::TaskOp, omp::TaskloopContextOp>(
428 op.getOperation())) {
429 if (
auto byrefAttr = op.getInReductionByref()) {
430 for (
bool isByRef : *byrefAttr) {
432 result = todo(
"in_reduction with byref modifier");
437 if (isa<omp::TargetOp>(op.getOperation())) {
438 if (
auto inReductionSyms = op.getInReductionSyms()) {
440 (*inReductionSyms).template getAsRange<SymbolRefAttr>()) {
445 "symbol resolution should be guaranteed by the op verifier");
446 if (decl.getInitializerRegion().front().getNumArguments() != 1) {
447 result = todo(
"in_reduction with two-argument initializer");
450 if (!decl.getCleanupRegion().empty()) {
451 result = todo(
"in_reduction with cleanup region");
457 }
else if (!op.getInReductionVars().empty() || op.getInReductionByref() ||
458 op.getInReductionSyms()) {
459 result = todo(
"in_reduction");
462 auto checkNowait = [&todo](
auto op, LogicalResult &
result) {
466 auto checkOrder = [&todo](
auto op, LogicalResult &
result) {
467 if (op.getOrder() || op.getOrderMod())
470 auto checkPrivate = [&todo](
auto op, LogicalResult &
result) {
471 if (!op.getPrivateVars().empty() || op.getPrivateSyms())
472 result = todo(
"privatization");
474 auto checkReduction = [&todo](
auto op, LogicalResult &
result) {
475 if (isa<omp::TeamsOp>(op))
476 if (!op.getReductionVars().empty() || op.getReductionByref() ||
477 op.getReductionSyms())
478 result = todo(
"reduction");
479 if (op.getReductionMod() &&
480 op.getReductionMod().value() != omp::ReductionModifier::defaultmod) {
481 omp::ReductionModifier mod = op.getReductionMod().value();
485 bool taskModifierSupported =
486 mod == omp::ReductionModifier::task &&
487 isa<omp::ParallelOp, omp::WsloopOp, omp::SectionsOp>(op);
488 if (!taskModifierSupported) {
489 result = todo(
"reduction with modifier");
490 }
else if (
auto byref = op.getReductionByref()) {
493 for (
bool isByRef : *byref)
495 result = todo(
"task reduction modifier with by-ref reduction");
501 auto checkTaskReductionByref = [&todo](
auto op, LogicalResult &
result) {
502 if (
auto byrefAttr = op.getTaskReductionByref())
503 for (
bool isByRef : *byrefAttr)
505 result = todo(
"task_reduction with byref modifier");
509 auto checkReductionByref = [&todo](
auto op, LogicalResult &
result) {
510 if (
auto byrefAttr = op.getReductionByref())
511 for (
bool isByRef : *byrefAttr)
513 result = todo(
"reduction with byref modifier");
517 auto checkNumTeams = [&todo](
auto op, LogicalResult &
result) {
518 if (op.hasNumTeamsMultiDim())
519 result = todo(
"num_teams with multi-dimensional values");
521 auto checkNumThreads = [&todo](
auto op, LogicalResult &
result) {
522 if (op.hasNumThreadsMultiDim())
523 result = todo(
"num_threads with multi-dimensional values");
526 auto checkThreadLimit = [&todo](
auto op, LogicalResult &
result) {
527 if (op.hasThreadLimitMultiDim())
528 result = todo(
"thread_limit with multi-dimensional values");
530 auto checkMap = [&todo](
auto op, LogicalResult &
result) {
531 if (!op.getMapIterated().empty())
532 result = todo(
"map/motion clause with iterator modifier");
535 auto checkDynGroupprivate = [&todo](
auto op, LogicalResult &
result) {
536 if (op.getDynGroupprivateSize())
537 result = todo(
"dyn_groupprivate");
542 .Case([&](omp::DistributeOp op) {
543 checkAllocate(op,
result);
546 .Case([&](omp::SectionsOp op) {
547 checkAllocate(op,
result);
549 checkReduction(op,
result);
551 .Case([&](omp::ScopeOp op) {
552 checkAllocate(op,
result);
553 checkReduction(op,
result);
555 .Case([&](omp::SingleOp op) {
556 checkAllocate(op,
result);
559 .Case([&](omp::TeamsOp op) {
560 checkAllocate(op,
result);
562 checkNumTeams(op,
result);
563 checkThreadLimit(op,
result);
564 checkDynGroupprivate(op,
result);
566 .Case([&](omp::TaskOp op) {
567 checkAllocate(op,
result);
568 checkInReduction(op,
result);
570 .Case([&](omp::TaskgroupOp op) {
571 checkAllocate(op,
result);
572 checkTaskReductionByref(op,
result);
574 .Case([&](omp::TaskwaitOp op) { checkNowait(op,
result); })
575 .Case([&](omp::TaskloopContextOp op) {
576 checkAllocate(op,
result);
577 checkInReduction(op,
result);
578 checkReduction(op,
result);
579 checkReductionByref(op,
result);
581 .Case([&](omp::WsloopOp op) {
582 checkAllocate(op,
result);
584 checkReduction(op,
result);
586 .Case([&](omp::ParallelOp op) {
587 checkReduction(op,
result);
588 checkNumThreads(op,
result);
590 .Case([&](omp::SimdOp op) { checkReduction(op,
result); })
591 .Case<omp::AtomicReadOp, omp::AtomicWriteOp, omp::AtomicUpdateOp,
592 omp::AtomicCaptureOp>([&](
auto op) { checkHint(op,
result); })
593 .Case([&](omp::AtomicCompareOp op) {
599 auto structTy = dyn_cast<LLVM::LLVMStructType>(argType);
605 result = todo(
"compare for complex types wider than 128 bits");
607 .Case<omp::TargetEnterDataOp, omp::TargetExitDataOp>([&](
auto op) {
611 .Case([&](omp::TargetUpdateOp op) {
615 .Case([&](omp::TargetOp op) {
616 checkAllocate(op,
result);
618 checkInReduction(op,
result);
620 checkThreadLimit(op,
result);
622 .Case([&](omp::TargetDataOp op) { checkMap(op,
result); })
623 .Case([&](omp::DeclareMapperInfoOp op) { checkMap(op,
result); })
634 llvm::handleAllErrors(
636 [&](
const PreviouslyReportedError &) {
result = failure(); },
637 [&](
const llvm::ErrorInfoBase &err) {
660 llvm::OpenMPIRBuilder::InsertPointTy allocInsertPoint;
663 [&](OpenMPAllocStackFrame &frame) {
664 allocInsertPoint = frame.allocInsertPoint;
665 deallocInsertPoints = frame.deallocBlocks;
673 allocInsertPoint.getBlock()->getParent() ==
674 builder.GetInsertBlock()->getParent()) {
676 deallocBlocks->insert(deallocBlocks->end(), deallocInsertPoints.begin(),
677 deallocInsertPoints.end());
678 return allocInsertPoint;
688 if (builder.GetInsertBlock() ==
689 &builder.GetInsertBlock()->getParent()->getEntryBlock()) {
690 assert(builder.GetInsertPoint() == builder.GetInsertBlock()->end() &&
691 "Assuming end of basic block");
692 llvm::BasicBlock *entryBB = llvm::BasicBlock::Create(
693 builder.getContext(),
"entry", builder.GetInsertBlock()->getParent(),
694 builder.GetInsertBlock()->getNextNode());
695 builder.CreateBr(entryBB);
696 builder.SetInsertPoint(entryBB);
702 for (llvm::BasicBlock &block : *builder.GetInsertBlock()->getParent()) {
706 llvm::Instruction *terminator = block.getTerminatorOrNull();
707 if (isa_and_present<llvm::ReturnInst>(terminator))
708 deallocBlocks->emplace_back(&block);
712 llvm::BasicBlock &funcEntryBlock =
713 builder.GetInsertBlock()->getParent()->getEntryBlock();
714 return llvm::OpenMPIRBuilder::InsertPointTy(
715 &funcEntryBlock, funcEntryBlock.getFirstInsertionPt());
721static llvm::CanonicalLoopInfo *
723 llvm::CanonicalLoopInfo *loopInfo =
nullptr;
724 moduleTranslation.
stackWalk<OpenMPLoopInfoStackFrame>(
725 [&](OpenMPLoopInfoStackFrame &frame) {
726 loopInfo = frame.loopInfo;
738 Region ®ion, StringRef blockName, llvm::IRBuilderBase &builder,
741 bool isLoopWrapper = isa<omp::LoopWrapperInterface>(region.
getParentOp());
743 llvm::BasicBlock *continuationBlock =
744 splitBB(builder,
true,
"omp.region.cont");
745 llvm::BasicBlock *sourceBlock = builder.GetInsertBlock();
747 llvm::LLVMContext &llvmContext = builder.getContext();
748 for (
Block &bb : region) {
749 llvm::BasicBlock *llvmBB = llvm::BasicBlock::Create(
750 llvmContext, blockName, builder.GetInsertBlock()->getParent(),
751 builder.GetInsertBlock()->getNextNode());
752 moduleTranslation.
mapBlock(&bb, llvmBB);
755 llvm::Instruction *sourceTerminator = sourceBlock->getTerminator();
762 unsigned numYields = 0;
764 if (!isLoopWrapper) {
765 bool operandsProcessed =
false;
767 if (omp::YieldOp yield = dyn_cast<omp::YieldOp>(bb.getTerminator())) {
768 if (!operandsProcessed) {
769 for (
unsigned i = 0, e = yield->getNumOperands(); i < e; ++i) {
770 continuationBlockPHITypes.push_back(
771 moduleTranslation.
convertType(yield->getOperand(i).getType()));
773 operandsProcessed =
true;
775 assert(continuationBlockPHITypes.size() == yield->getNumOperands() &&
776 "mismatching number of values yielded from the region");
777 for (
unsigned i = 0, e = yield->getNumOperands(); i < e; ++i) {
778 llvm::Type *operandType =
779 moduleTranslation.
convertType(yield->getOperand(i).getType());
781 assert(continuationBlockPHITypes[i] == operandType &&
782 "values of mismatching types yielded from the region");
792 if (!continuationBlockPHITypes.empty())
794 continuationBlockPHIs &&
795 "expected continuation block PHIs if converted regions yield values");
796 if (continuationBlockPHIs) {
797 llvm::IRBuilderBase::InsertPointGuard guard(builder);
798 continuationBlockPHIs->reserve(continuationBlockPHITypes.size());
799 builder.SetInsertPoint(continuationBlock, continuationBlock->begin());
800 for (llvm::Type *ty : continuationBlockPHITypes)
801 continuationBlockPHIs->push_back(builder.CreatePHI(ty, numYields));
807 for (
Block *bb : blocks) {
808 llvm::BasicBlock *llvmBB = moduleTranslation.
lookupBlock(bb);
811 if (bb->isEntryBlock()) {
812 assert(sourceTerminator->getNumSuccessors() == 1 &&
813 "provided entry block has multiple successors");
814 assert(sourceTerminator->getSuccessor(0) == continuationBlock &&
815 "ContinuationBlock is not the successor of the entry block");
816 sourceTerminator->setSuccessor(0, llvmBB);
819 llvm::IRBuilderBase::InsertPointGuard guard(builder);
821 moduleTranslation.
convertBlock(*bb, bb->isEntryBlock(), builder)))
822 return llvm::make_error<PreviouslyReportedError>();
827 builder.CreateBr(continuationBlock);
838 Operation *terminator = bb->getTerminator();
839 if (isa<omp::TerminatorOp, omp::YieldOp>(terminator)) {
840 builder.CreateBr(continuationBlock);
842 for (
unsigned i = 0, e = terminator->
getNumOperands(); i < e; ++i)
843 (*continuationBlockPHIs)[i]->addIncoming(
857 return continuationBlock;
863 case omp::ClauseProcBindKind::Close:
864 return llvm::omp::ProcBindKind::OMP_PROC_BIND_close;
865 case omp::ClauseProcBindKind::Master:
866 return llvm::omp::ProcBindKind::OMP_PROC_BIND_master;
867 case omp::ClauseProcBindKind::Primary:
868 return llvm::omp::ProcBindKind::OMP_PROC_BIND_primary;
869 case omp::ClauseProcBindKind::Spread:
870 return llvm::omp::ProcBindKind::OMP_PROC_BIND_spread;
872 llvm_unreachable(
"Unknown ClauseProcBindKind kind");
879 auto maskedOp = cast<omp::MaskedOp>(opInst);
880 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
885 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
888 auto ®ion = maskedOp.getRegion();
889 builder.restoreIP(codeGenIP);
897 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
899 llvm::Value *filterVal =
nullptr;
900 if (
auto filterVar = maskedOp.getFilteredThreadId()) {
901 filterVal = moduleTranslation.
lookupValue(filterVar);
903 llvm::LLVMContext &llvmContext = builder.getContext();
905 llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvmContext), 0);
907 assert(filterVal !=
nullptr);
908 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
909 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
916 builder.restoreIP(*afterIP);
924 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
925 auto masterOp = cast<omp::MasterOp>(opInst);
930 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
933 auto ®ion = masterOp.getRegion();
934 builder.restoreIP(codeGenIP);
942 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
944 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
945 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
952 builder.restoreIP(*afterIP);
960 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
961 auto criticalOp = cast<omp::CriticalOp>(opInst);
966 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
969 auto ®ion = cast<omp::CriticalOp>(opInst).getRegion();
970 builder.restoreIP(codeGenIP);
978 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
980 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
981 llvm::LLVMContext &llvmContext = moduleTranslation.
getLLVMContext();
982 llvm::Constant *hint =
nullptr;
985 if (criticalOp.getNameAttr()) {
988 auto symbolRef = cast<SymbolRefAttr>(criticalOp.getNameAttr());
989 auto criticalDeclareOp =
993 llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvmContext),
994 static_cast<int>(criticalDeclareOp.getHint()));
996 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
998 ompLoc, bodyGenCB, finiCB, criticalOp.getName().value_or(
""), hint);
1003 builder.restoreIP(*afterIP);
1015 template <
typename OP>
1018 cast<
omp::BlockArgOpenMPOpInterface>(*op).getPrivateBlockArgs()) {
1021 collectPrivatizationDecls<OP>(op);
1038 void collectPrivatizationDecls(OP op) {
1039 std::optional<ArrayAttr> attr = op.getPrivateSyms();
1044 for (
auto symbolRef : attr->getAsRange<SymbolRefAttr>()) {
1051template <
typename T>
1055 std::optional<ArrayAttr> attr = op.getReductionSyms();
1059 reductions.reserve(reductions.size() + op.getNumReductionVars());
1060 for (
auto symbolRef : attr->getAsRange<SymbolRefAttr>()) {
1061 reductions.push_back(
1076 Operation *contextOp, std::optional<ArrayAttr> syms, StringRef opName,
1080 out.reserve(out.size() + syms->size());
1081 for (
auto sym : syms->getAsRange<SymbolRefAttr>()) {
1086 <<
"failed to resolve " << clauseName
1087 <<
" declare_reduction symbol " << sym.getRootReference() <<
" in "
1089 if (decl.getInitializerRegion().front().getNumArguments() != 1)
1091 <<
"not yet implemented: " << clauseName
1092 <<
" with two-argument initializer in " << opName;
1093 if (!decl.getCleanupRegion().empty())
1094 return contextOp->
emitError() <<
"not yet implemented: " << clauseName
1095 <<
" with cleanup region in " << opName;
1096 if (decl.getReductionRegion().empty())
1098 << clauseName <<
" declare_reduction is missing a combiner region";
1099 out.push_back(decl);
1110 Region ®ion, StringRef blockName, llvm::IRBuilderBase &builder,
1119 llvm::Instruction *potentialTerminator =
1120 builder.GetInsertBlock()->empty() ?
nullptr
1121 : &builder.GetInsertBlock()->back();
1123 if (potentialTerminator && potentialTerminator->isTerminator())
1124 potentialTerminator->removeFromParent();
1125 moduleTranslation.
mapBlock(®ion.
front(), builder.GetInsertBlock());
1128 region.
front(),
true, builder)))
1132 if (continuationBlockArgs)
1134 *continuationBlockArgs,
1141 if (potentialTerminator && potentialTerminator->isTerminator()) {
1142 llvm::BasicBlock *block = builder.GetInsertBlock();
1143 if (block->empty()) {
1149 potentialTerminator->insertInto(block, block->begin());
1151 potentialTerminator->insertAfter(&block->back());
1165 if (continuationBlockArgs)
1166 llvm::append_range(*continuationBlockArgs, phis);
1167 builder.SetInsertPoint(*continuationBlock,
1168 (*continuationBlock)->getFirstInsertionPt());
1175using OwningReductionGen =
1176 std::function<llvm::OpenMPIRBuilder::InsertPointOrErrorTy(
1177 llvm::OpenMPIRBuilder::InsertPointTy, llvm::Value *, llvm::Value *,
1179using OwningAtomicReductionGen =
1180 std::function<llvm::OpenMPIRBuilder::InsertPointOrErrorTy(
1181 llvm::OpenMPIRBuilder::InsertPointTy, llvm::Type *, llvm::Value *,
1183using OwningDataPtrPtrReductionGen =
1184 std::function<llvm::OpenMPIRBuilder::InsertPointOrErrorTy(
1185 llvm::OpenMPIRBuilder::InsertPointTy, llvm::Value *, llvm::Value *&)>;
1191static OwningReductionGen
1197 OwningReductionGen gen =
1198 [&, decl](llvm::OpenMPIRBuilder::InsertPointTy insertPoint,
1199 llvm::Value *lhs, llvm::Value *rhs,
1200 llvm::Value *&
result)
mutable
1201 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
1202 moduleTranslation.
mapValue(decl.getReductionLhsArg(), lhs);
1203 moduleTranslation.
mapValue(decl.getReductionRhsArg(), rhs);
1204 builder.restoreIP(insertPoint);
1207 "omp.reduction.nonatomic.body", builder,
1208 moduleTranslation, &phis)))
1209 return llvm::createStringError(
1210 "failed to inline `combiner` region of `omp.declare_reduction`");
1211 result = llvm::getSingleElement(phis);
1212 return builder.saveIP();
1221static OwningAtomicReductionGen
1223 llvm::IRBuilderBase &builder,
1225 if (decl.getAtomicReductionRegion().empty())
1226 return OwningAtomicReductionGen();
1232 [&, decl](llvm::OpenMPIRBuilder::InsertPointTy insertPoint, llvm::Type *,
1233 llvm::Value *lhs, llvm::Value *rhs)
mutable
1234 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
1235 moduleTranslation.
mapValue(decl.getAtomicReductionLhsArg(), lhs);
1236 moduleTranslation.
mapValue(decl.getAtomicReductionRhsArg(), rhs);
1237 builder.restoreIP(insertPoint);
1240 "omp.reduction.atomic.body", builder,
1241 moduleTranslation, &phis)))
1242 return llvm::createStringError(
1243 "failed to inline `atomic` region of `omp.declare_reduction`");
1244 assert(phis.empty());
1245 return builder.saveIP();
1254static OwningDataPtrPtrReductionGen
1257 if (!isByRef || decl.getDataPtrPtrRegion().empty())
1258 return OwningDataPtrPtrReductionGen();
1260 OwningDataPtrPtrReductionGen refDataPtrGen =
1261 [&, decl](llvm::OpenMPIRBuilder::InsertPointTy insertPoint,
1262 llvm::Value *byRefVal, llvm::Value *&
result)
mutable
1263 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
1264 moduleTranslation.
mapValue(decl.getDataPtrPtrRegionArg(), byRefVal);
1265 builder.restoreIP(insertPoint);
1268 "omp.data_ptr_ptr.body", builder,
1269 moduleTranslation, &phis)))
1270 return llvm::createStringError(
1271 "failed to inline `data_ptr_ptr` region of `omp.declare_reduction`");
1272 result = llvm::getSingleElement(phis);
1273 return builder.saveIP();
1276 return refDataPtrGen;
1283 auto orderedOp = cast<omp::OrderedOp>(opInst);
1288 omp::ClauseDepend dependType = *orderedOp.getDoacrossDependType();
1289 bool isDependSource = dependType == omp::ClauseDepend::dependsource;
1290 unsigned numLoops = *orderedOp.getDoacrossNumLoops();
1292 moduleTranslation.
lookupValues(orderedOp.getDoacrossDependVars());
1294 size_t indexVecValues = 0;
1295 while (indexVecValues < vecValues.size()) {
1297 storeValues.reserve(numLoops);
1298 for (
unsigned i = 0; i < numLoops; i++) {
1299 storeValues.push_back(vecValues[indexVecValues]);
1302 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
1304 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
1305 builder.restoreIP(moduleTranslation.
getOpenMPBuilder()->createOrderedDepend(
1306 ompLoc, allocaIP, numLoops, storeValues,
".cnt.addr", isDependSource));
1316 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1317 auto orderedRegionOp = cast<omp::OrderedRegionOp>(opInst);
1322 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
1325 auto ®ion = cast<omp::OrderedRegionOp>(opInst).getRegion();
1326 builder.restoreIP(codeGenIP);
1334 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
1336 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
1337 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
1339 ompLoc, bodyGenCB, finiCB, !orderedRegionOp.getParLevelSimd());
1344 builder.restoreIP(*afterIP);
1350struct DeferredStore {
1351 DeferredStore(llvm::Value *value, llvm::Value *address)
1352 : value(value), address(address) {}
1355 llvm::Value *address;
1362template <
typename T>
1365 llvm::IRBuilderBase &builder,
1367 const llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
1373 llvm::IRBuilderBase::InsertPointGuard guard(builder);
1374 builder.SetInsertPoint(allocaIP.getBlock()->getTerminator());
1380 deferredStores.reserve(op.getNumReductionVars());
1382 for (std::size_t i = 0; i < op.getNumReductionVars(); ++i) {
1383 Region &allocRegion = reductionDecls[i].getAllocRegion();
1385 if (allocRegion.
empty())
1390 builder, moduleTranslation, &phis)))
1391 return op.emitError(
1392 "failed to inline `alloc` region of `omp.declare_reduction`");
1394 assert(phis.size() == 1 &&
"expected one allocation to be yielded");
1395 builder.SetInsertPoint(allocaIP.getBlock()->getTerminator());
1399 llvm::Type *ptrTy = builder.getPtrTy();
1403 if (useDeviceSharedMem) {
1404 var = ompBuilder->createOMPAllocShared(builder, varTy);
1406 var = builder.CreateAlloca(varTy);
1407 var = builder.CreatePointerBitCastOrAddrSpaceCast(var, ptrTy);
1410 llvm::Value *castPhi =
1411 builder.CreatePointerBitCastOrAddrSpaceCast(phis[0], ptrTy);
1413 deferredStores.emplace_back(castPhi, var);
1415 privateReductionVariables[i] = var;
1416 moduleTranslation.
mapValue(reductionArgs[i], castPhi);
1417 reductionVariableMap.try_emplace(op.getReductionVars()[i], castPhi);
1419 assert(allocRegion.
empty() &&
1420 "allocaction is implicit for by-val reduction");
1422 llvm::Type *ptrTy = builder.getPtrTy();
1426 if (useDeviceSharedMem) {
1427 var = ompBuilder->createOMPAllocShared(builder, varTy);
1429 var = builder.CreateAlloca(varTy);
1430 var = builder.CreatePointerBitCastOrAddrSpaceCast(var, ptrTy);
1433 moduleTranslation.
mapValue(reductionArgs[i], var);
1434 privateReductionVariables[i] = var;
1435 reductionVariableMap.try_emplace(op.getReductionVars()[i], var);
1443template <
typename T>
1446 llvm::IRBuilderBase &builder,
1451 mlir::omp::DeclareReductionOp &reduction = reductionDecls[i];
1452 Region &initializerRegion = reduction.getInitializerRegion();
1455 mlir::Value mlirSource = loop.getReductionVars()[i];
1456 llvm::Value *llvmSource = moduleTranslation.
lookupValue(mlirSource);
1457 llvm::Value *origVal = llvmSource;
1459 if (!isa<LLVM::LLVMPointerType>(
1460 reduction.getInitializerMoldArg().getType()) &&
1461 isa<LLVM::LLVMPointerType>(mlirSource.
getType())) {
1464 reduction.getInitializerMoldArg().getType()),
1465 llvmSource,
"omp_orig");
1467 moduleTranslation.
mapValue(reduction.getInitializerMoldArg(), origVal);
1470 llvm::Value *allocation =
1471 reductionVariableMap.lookup(loop.getReductionVars()[i]);
1472 moduleTranslation.
mapValue(reduction.getInitializerAllocArg(), allocation);
1478 llvm::BasicBlock *block =
nullptr) {
1479 if (block ==
nullptr)
1480 block = builder.GetInsertBlock();
1482 if (!block->hasTerminator())
1483 builder.SetInsertPoint(block);
1485 builder.SetInsertPoint(block->getTerminator());
1493template <
typename OP>
1496 llvm::IRBuilderBase &builder,
1498 llvm::BasicBlock *latestAllocaBlock,
1504 if (op.getNumReductionVars() == 0)
1510 llvm::BasicBlock *initBlock = splitBB(builder,
true,
"omp.reduction.init");
1511 auto allocaIP = llvm::IRBuilderBase::InsertPoint(
1512 latestAllocaBlock, latestAllocaBlock->getTerminator()->getIterator());
1513 builder.restoreIP(allocaIP);
1516 for (
unsigned i = 0; i < op.getNumReductionVars(); ++i) {
1518 if (!reductionDecls[i].getAllocRegion().empty())
1526 if (useDeviceSharedMem)
1527 byRefVars[i] = ompBuilder->createOMPAllocShared(builder, varTy);
1529 byRefVars[i] = builder.CreateAlloca(varTy);
1537 for (
auto [data, addr] : deferredStores)
1538 builder.CreateStore(data, addr);
1543 for (
unsigned i = 0; i < op.getNumReductionVars(); ++i) {
1548 reductionVariableMap, i);
1556 "omp.reduction.neutral", builder,
1557 moduleTranslation, &phis)))
1560 assert(phis.size() == 1 &&
"expected one value to be yielded from the "
1561 "reduction neutral element declaration region");
1566 if (!reductionDecls[i].getAllocRegion().empty())
1575 builder.CreateStore(phis[0], byRefVars[i]);
1577 privateReductionVariables[i] = byRefVars[i];
1578 moduleTranslation.
mapValue(reductionArgs[i], phis[0]);
1579 reductionVariableMap.try_emplace(op.getReductionVars()[i], phis[0]);
1582 builder.CreateStore(phis[0], privateReductionVariables[i]);
1589 moduleTranslation.
forgetMapping(reductionDecls[i].getInitializerRegion());
1596template <
typename T>
1597static void collectReductionInfo(
1598 T loop, llvm::IRBuilderBase &builder,
1607 unsigned numReductions = loop.getNumReductionVars();
1609 for (
unsigned i = 0; i < numReductions; ++i) {
1612 owningAtomicReductionGens.push_back(
1615 reductionDecls[i], builder, moduleTranslation, isByRef[i]));
1619 reductionInfos.reserve(numReductions);
1620 for (
unsigned i = 0; i < numReductions; ++i) {
1621 llvm::OpenMPIRBuilder::ReductionGenAtomicCBTy
atomicGen =
nullptr;
1622 if (owningAtomicReductionGens[i])
1623 atomicGen = owningAtomicReductionGens[i];
1624 llvm::Value *variable =
1625 moduleTranslation.
lookupValue(loop.getReductionVars()[i]);
1628 if (
auto alloca = mlir::dyn_cast<LLVM::AllocaOp>(op)) {
1629 allocatedType = alloca.getElemType();
1636 reductionInfos.push_back(
1638 privateReductionVariables[i],
1639 llvm::OpenMPIRBuilder::EvalKind::Scalar,
1643 allocatedType ? moduleTranslation.
convertType(allocatedType) :
nullptr,
1644 reductionDecls[i].getByrefElementType()
1646 *reductionDecls[i].getByrefElementType())
1656 llvm::IRBuilderBase &builder, StringRef regionName,
1657 bool shouldLoadCleanupRegionArg =
true) {
1658 for (
auto [i, cleanupRegion] : llvm::enumerate(cleanupRegions)) {
1659 if (cleanupRegion->empty())
1665 llvm::Instruction *potentialTerminator =
1666 builder.GetInsertBlock()->empty() ?
nullptr
1667 : &builder.GetInsertBlock()->back();
1668 if (potentialTerminator && potentialTerminator->isTerminator())
1669 builder.SetInsertPoint(potentialTerminator);
1670 llvm::Value *privateVarValue =
1671 shouldLoadCleanupRegionArg
1672 ? builder.CreateLoad(
1674 privateVariables[i])
1675 : privateVariables[i];
1680 moduleTranslation)))
1693 OP op, llvm::IRBuilderBase &builder,
1695 llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
1698 bool isNowait =
false,
bool isTeamsReduction =
false) {
1700 if (op.getNumReductionVars() == 0)
1712 collectReductionInfo(op, builder, moduleTranslation, reductionDecls,
1714 owningReductionGenRefDataPtrGens,
1715 privateReductionVariables, reductionInfos, isByRef);
1720 llvm::UnreachableInst *tempTerminator = builder.CreateUnreachable();
1721 builder.SetInsertPoint(tempTerminator);
1722 llvm::DebugLoc reductionLoc = builder.getCurrentDebugLocation();
1723 llvm::OpenMPIRBuilder::InsertPointOrErrorTy contInsertPoint =
1724 ompBuilder->createReductions(builder, allocaIP, reductionInfos, isByRef,
1725 isNowait, isTeamsReduction);
1730 if (!contInsertPoint->getBlock())
1731 return op->emitOpError() <<
"failed to convert reductions";
1733 llvm::OpenMPIRBuilder::InsertPointTy afterIP = *contInsertPoint;
1734 if (!isTeamsReduction) {
1735 llvm::OpenMPIRBuilder::InsertPointOrErrorTy barrierIP =
1736 ompBuilder->createBarrier({*contInsertPoint, reductionLoc},
1737 llvm::omp::OMPD_for);
1741 afterIP = *barrierIP;
1744 tempTerminator->eraseFromParent();
1745 builder.restoreIP(afterIP);
1749 llvm::transform(reductionDecls, std::back_inserter(reductionRegions),
1750 [](omp::DeclareReductionOp reductionDecl) {
1751 return &reductionDecl.getCleanupRegion();
1754 reductionRegions, privateReductionVariables, moduleTranslation, builder,
1755 "omp.reduction.cleanup");
1758 if (useDeviceSharedMem) {
1759 for (
auto [var, reductionDecl] :
1760 llvm::zip_equal(privateReductionVariables, reductionDecls))
1761 ompBuilder->createOMPFreeShared(
1762 builder, var, moduleTranslation.
convertType(reductionDecl.getType()));
1775template <
typename OP>
1779 llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
1784 if (op.getNumReductionVars() == 0)
1790 allocaIP, reductionDecls,
1791 privateReductionVariables, reductionVariableMap,
1792 deferredStores, isByRef)))
1795 return initReductionVars(op, reductionArgs, builder, moduleTranslation,
1796 allocaIP.getBlock(), reductionDecls,
1797 privateReductionVariables, reductionVariableMap,
1798 isByRef, deferredStores);
1812 if (mappedPrivateVars ==
nullptr || !mappedPrivateVars->contains(privateVar))
1815 Value blockArg = (*mappedPrivateVars)[privateVar];
1818 assert(isa<LLVM::LLVMPointerType>(blockArgType) &&
1819 "A block argument corresponding to a mapped var should have "
1822 if (privVarType == blockArgType)
1829 if (!isa<LLVM::LLVMPointerType>(privVarType))
1830 return builder.CreateLoad(moduleTranslation.
convertType(privVarType),
1847 llvm::Type *regionArgType =
1849 if (regionArgType->isPointerTy() || !value->getType()->isPointerTy())
1852 return builder.CreateLoad(regionArgType, value);
1862 omp::PrivateClauseOp &privDecl, llvm::Value *nonPrivateVar,
1864 llvm::BasicBlock *privInitBlock,
1866 Region &initRegion = privDecl.getInitRegion();
1867 if (initRegion.
empty())
1868 return llvmPrivateVar;
1870 assert(nonPrivateVar);
1871 moduleTranslation.
mapValue(privDecl.getInitMoldArg(), nonPrivateVar);
1872 moduleTranslation.
mapValue(privDecl.getInitPrivateArg(), llvmPrivateVar);
1877 moduleTranslation, &phis)))
1878 return llvm::createStringError(
1879 "failed to inline `init` region of `omp.private`");
1881 assert(phis.size() == 1 &&
"expected one allocation to be yielded");
1898 llvm::Value *llvmPrivateVar, llvm::BasicBlock *privInitBlock,
1901 builder, moduleTranslation, privDecl,
1904 blockArg, llvmPrivateVar, privInitBlock, mappedPrivateVars);
1913 return llvm::Error::success();
1915 llvm::BasicBlock *privInitBlock = splitBB(builder,
true,
"omp.private.init");
1918 for (
auto [idx, zip] : llvm::enumerate(llvm::zip_equal(
1921 auto [privDecl, mlirPrivVar, blockArg, llvmPrivateVar] = zip;
1923 builder, moduleTranslation, privDecl, mlirPrivVar, blockArg,
1924 llvmPrivateVar, privInitBlock, mappedPrivateVars);
1927 return privVarOrErr.takeError();
1929 llvmPrivateVar = privVarOrErr.get();
1930 moduleTranslation.
mapValue(blockArg, llvmPrivateVar);
1935 return llvm::Error::success();
1941template <
typename T>
1946 const llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
1949 llvm::Instruction *allocaTerminator = allocaIP.getBlock()->getTerminator();
1950 splitBB(llvm::OpenMPIRBuilder::InsertPointTy(allocaIP.getBlock(),
1951 allocaTerminator->getIterator()),
1952 true, allocaTerminator->getStableDebugLoc(),
1953 "omp.region.after_alloca");
1955 llvm::IRBuilderBase::InsertPointGuard guard(builder);
1957 allocaTerminator = allocaIP.getBlock()->getTerminator();
1958 builder.SetInsertPoint(allocaTerminator);
1960 assert(allocaTerminator->getNumSuccessors() == 1 &&
1961 "This is an unconditional branch created by splitBB");
1963 llvm::DataLayout dataLayout = builder.GetInsertBlock()->getDataLayout();
1964 llvm::BasicBlock *afterAllocas = allocaTerminator->getSuccessor(0);
1968 unsigned int allocaAS =
1969 moduleTranslation.
getLLVMModule()->getDataLayout().getAllocaAddrSpace();
1972 .getProgramAddressSpace();
1978 if constexpr (std::is_same_v<T, omp::ParallelOp>) {
1979 allocatorVars = op.getAllocatorVars();
1980 allocateAlignments = op.getAllocateAlignmentsAttr();
1981 if (
auto privateIndices = op.getAllocatePrivateIndicesAttr())
1982 for (
auto [allocateIndex, privateIndex] :
1983 llvm::enumerate(privateIndices.asArrayRef()))
1984 allocateItemForPrivate[privateIndex] = allocateIndex;
1987 for (
auto [privateIndex, tuple] : llvm::enumerate(llvm::zip_equal(
1990 auto [privDecl, mlirPrivVar, blockArg] = tuple;
1991 llvm::Type *llvmAllocType =
1992 moduleTranslation.
convertType(privDecl.getType());
1993 builder.SetInsertPoint(allocaIP.getBlock()->getTerminator());
1994 llvm::Value *llvmPrivateVar =
nullptr;
1995 int64_t allocateIndex = allocateItemForPrivate[privateIndex];
1996 if (allocateIndex >= 0) {
1997 if (mightUseDeviceSharedMem ||
1998 op->template getParentOfType<omp::TargetOp>())
1999 return llvm::createStringError(
2000 "allocate clause on a device parallel region is not supported");
2001 if (!llvmAllocType->isSized())
2002 return llvm::createStringError(
2003 "allocate clause private type must have a fixed size");
2004 llvm::TypeSize size = dataLayout.getTypeAllocSize(llvmAllocType);
2005 if (size.isScalable())
2006 return llvm::createStringError(
2007 "allocate clause private type must have a fixed size");
2008 llvm::IntegerType *sizeTy =
2009 moduleTranslation.
getLLVMModule()->getDataLayout().getIntPtrType(
2011 if (!llvm::isUIntN(sizeTy->getBitWidth(), size.getFixedValue()))
2012 return llvm::createStringError(
2013 "OpenMP allocation size cannot be represented by the target size "
2015 llvm::Value *sizeValue =
2016 llvm::ConstantInt::get(sizeTy, size.getFixedValue());
2018 Value allocatorVar = allocatorVars[allocateIndex];
2021 return llvm::createStringError(
2022 "failed to find converted OpenMP allocator operand");
2023 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2025 allocateAlignments ? allocateAlignments[allocateIndex] : 0;
2026 if (alignment != 0) {
2030 uint64_t alignmentValue = std::max<uint64_t>(
2031 static_cast<uint64_t
>(alignment),
2032 dataLayout.getABITypeAlign(llvmAllocType).value());
2033 if (!llvm::isUIntN(sizeTy->getBitWidth(), alignmentValue))
2034 return llvm::createStringError(
2035 "OpenMP allocation alignment cannot be represented by the "
2036 "target size type");
2037 llvmPrivateVar = ompBuilder->createOMPAlignedAlloc(
2038 ompLoc, llvm::ConstantInt::get(sizeTy, alignmentValue), sizeValue,
2039 allocator->second,
"omp.private.alloc");
2041 llvmPrivateVar = ompBuilder->createOMPAlloc(
2042 ompLoc, sizeValue, allocator->second,
"omp.private.alloc");
2044 if (!llvmPrivateVar)
2045 return llvm::createStringError(
2046 "failed to create OpenMP private allocation");
2048 {llvmPrivateVar, allocator->second});
2049 }
else if (mightUseDeviceSharedMem &&
2051 llvmPrivateVar = ompBuilder->createOMPAllocShared(builder, llvmAllocType);
2053 llvmPrivateVar = builder.CreateAlloca(
2054 llvmAllocType,
nullptr,
"omp.private.alloc");
2055 if (allocaAS != defaultAS)
2056 llvmPrivateVar = builder.CreateAddrSpaceCast(
2057 llvmPrivateVar, builder.getPtrTy(defaultAS));
2060 privateVarsInfo.
llvmVars.push_back(llvmPrivateVar);
2063 return afterAllocas;
2071 if (mlir::isa<omp::SingleOp, omp::CriticalOp>(parent))
2080 if (mlir::isa<omp::ParallelOp>(parent))
2094 bool needsFirstprivate =
2095 llvm::any_of(privateDecls, [](omp::PrivateClauseOp &privOp) {
2096 return privOp.getDataSharingType() ==
2097 omp::DataSharingClauseType::FirstPrivate;
2100 if (!needsFirstprivate)
2103 llvm::BasicBlock *copyBlock =
2104 splitBB(builder,
true,
"omp.private.copy");
2107 for (
auto [decl, moldVar, llvmVar] :
2108 llvm::zip_equal(privateDecls, moldVars, llvmPrivateVars)) {
2109 if (decl.getDataSharingType() != omp::DataSharingClauseType::FirstPrivate)
2113 Region ©Region = decl.getCopyRegion();
2116 builder, moduleTranslation, decl.getCopyMoldArg(), moldVar);
2118 builder, moduleTranslation, decl.getCopyPrivateArg(), llvmVar);
2120 moduleTranslation.
mapValue(decl.getCopyMoldArg(), copyMoldVar);
2123 moduleTranslation.
mapValue(decl.getCopyPrivateArg(), copyPrivateVar);
2127 moduleTranslation)))
2128 return decl.emitError(
"failed to inline `copy` region of `omp.private`");
2142 llvm::OpenMPIRBuilder::InsertPointOrErrorTy res =
2143 ompBuilder->createBarrier(builder, llvm::omp::OMPD_barrier);
2159 llvm::transform(mlirPrivateVars, moldVars.begin(), [&](
mlir::Value mlirVar) {
2161 llvm::Value *moldVar = findAssociatedValue(
2162 mlirVar, builder, moduleTranslation, mappedPrivateVars);
2167 llvmPrivateVars, privateDecls, insertBarrier,
2171template <
typename T>
2179 std::back_inserter(privateCleanupRegions),
2180 [](omp::PrivateClauseOp privatizer) {
2181 return &privatizer.getDeallocRegion();
2185 privateVarsInfo.
llvmVars, moduleTranslation,
2186 builder,
"omp.private.dealloc",
2188 return mlir::emitError(loc,
"failed to inline `dealloc` region of an "
2189 "`omp.private` op in");
2194 for (
auto [privDecl, llvmPrivVar, blockArg] :
2198 ompBuilder->createOMPFreeShared(
2199 builder, llvmPrivVar,
2200 moduleTranslation.
convertType(privDecl.getType()));
2204 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2207 ompBuilder->createOMPFree(ompLoc, allocation.allocatedPtr,
2208 allocation.allocator);
2220 if (mlir::isa<omp::CancelOp, omp::CancellationPointOp>(child))
2237 llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder::InsertPointTy allocaIP,
2239 bool isWorksharing =
false);
2247 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2248 using StorableBodyGenCallbackTy =
2249 llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
2251 auto sectionsOp = cast<omp::SectionsOp>(opInst);
2257 assert(isByRef.size() == sectionsOp.getNumReductionVars());
2261 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
2265 sectionsOp.getNumReductionVars());
2269 cast<omp::BlockArgOpenMPOpInterface>(opInst).getReductionBlockArgs();
2272 sectionsOp, reductionArgs, builder, moduleTranslation, allocaIP,
2273 reductionDecls, privateReductionVariables, reductionVariableMap,
2277 bool isTaskReductionMod =
2278 sectionsOp.getReductionMod() == omp::ReductionModifier::task &&
2279 sectionsOp.getNumReductionVars() > 0;
2284 auto sectionOp = dyn_cast<omp::SectionOp>(op);
2288 Region ®ion = sectionOp.getRegion();
2289 auto sectionCB = [§ionsOp, ®ion, &builder, &moduleTranslation](
2290 InsertPointTy allocaIP, InsertPointTy codeGenIP,
2292 builder.restoreIP(codeGenIP);
2299 sectionsOp.getRegion().getNumArguments());
2300 for (
auto [sectionsArg, sectionArg] : llvm::zip_equal(
2301 sectionsOp.getRegion().getArguments(), region.
getArguments())) {
2302 llvm::Value *llvmVal = moduleTranslation.
lookupValue(sectionsArg);
2304 moduleTranslation.
mapValue(sectionArg, llvmVal);
2311 sectionCBs.push_back(sectionCB);
2317 if (sectionCBs.empty())
2325 if (isTaskReductionMod &&
2327 "__omp_taskred_mod_", builder, allocaIP,
2328 moduleTranslation,
true,
2330 return sectionsOp.emitError(
2331 "failed to emit task reduction modifier initialization");
2333 assert(isa<omp::SectionOp>(*sectionsOp.getRegion().op_begin()));
2338 auto privCB = [&](InsertPointTy, InsertPointTy codeGenIP, llvm::Value &,
2339 llvm::Value &vPtr, llvm::Value *&replacementValue)
2340 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
2341 replacementValue = &vPtr;
2347 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
2351 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2352 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2354 ompLoc, allocaIP, sectionCBs, privCB, finiCB, isCancellable,
2355 sectionsOp.getNowait());
2360 builder.restoreIP(*afterIP);
2363 if (isTaskReductionMod)
2369 sectionsOp, builder, moduleTranslation, allocaIP, reductionDecls,
2370 privateReductionVariables, isByRef, sectionsOp.getNowait());
2377 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2384 assert(isByRef.size() == scopeOp.getNumReductionVars());
2393 scopeOp.getNumReductionVars());
2397 cast<omp::BlockArgOpenMPOpInterface>(*scopeOp).getReductionBlockArgs();
2401 scopeOp, builder, moduleTranslation, privateVarsInfo, allocaIP);
2406 scopeOp, reductionArgs, builder, moduleTranslation, allocaIP,
2407 reductionDecls, privateReductionVariables, reductionVariableMap,
2412 [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
2414 builder.restoreIP(codeGenIP);
2420 return llvm::make_error<PreviouslyReportedError>();
2423 scopeOp, builder, moduleTranslation, privateVarsInfo.
mlirVars,
2425 scopeOp.getPrivateNeedsBarrier())))
2426 return llvm::make_error<PreviouslyReportedError>();
2433 auto finiCB = [&](InsertPointTy codeGenIP) -> llvm::Error {
2434 InsertPointTy oldIP = builder.saveIP();
2435 builder.restoreIP(codeGenIP);
2437 scopeOp.getLoc(), privateVarsInfo)))
2438 return llvm::make_error<PreviouslyReportedError>();
2439 builder.restoreIP(oldIP);
2440 return llvm::Error::success();
2443 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2444 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2445 ompBuilder->createScope(ompLoc, bodyCB, finiCB, scopeOp.getNowait());
2450 builder.restoreIP(*afterIP);
2454 scopeOp, builder, moduleTranslation, allocaIP, reductionDecls,
2455 privateReductionVariables, isByRef, scopeOp.getNowait(),
2463 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2464 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2469 auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
2471 builder.restoreIP(codegenIP);
2473 builder, moduleTranslation)
2476 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
2480 std::optional<ArrayAttr> cpFuncs = singleOp.getCopyprivateSyms();
2483 for (
size_t i = 0, e = cpVars.size(); i < e; ++i) {
2484 llvmCPVars.push_back(moduleTranslation.
lookupValue(cpVars[i]));
2486 singleOp, cast<SymbolRefAttr>((*cpFuncs)[i]));
2487 llvmCPFuncs.push_back(
2491 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2493 ompLoc, bodyCB, finiCB, singleOp.getNowait(), llvmCPVars,
2499 builder.restoreIP(*afterIP);
2503static omp::DistributeOp
2507 omp::DistributeOp distOp;
2508 WalkResult walk = teamsOp.getRegion().walk([&](omp::DistributeOp op) {
2514 if (walk.wasInterrupted() || !distOp)
2518 llvm::cast<mlir::omp::BlockArgOpenMPOpInterface>(teamsOp.getOperation());
2522 for (
auto ra : iface.getReductionBlockArgs())
2523 for (
auto &use : ra.getUses()) {
2524 auto *useOp = use.getOwner();
2526 if (mlir::isa<LLVM::DbgDeclareOp, LLVM::DbgValueOp>(useOp)) {
2527 debugUses.push_back(useOp);
2530 if (!distOp->isProperAncestor(useOp))
2537 for (
auto *use : debugUses)
2546 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2551 unsigned numReductionVars = op.getNumReductionVars();
2555 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
2561 if (doTeamsReduction) {
2562 isByRef =
getIsByRef(op.getReductionByref());
2564 assert(isByRef.size() == op.getNumReductionVars());
2567 llvm::cast<omp::BlockArgOpenMPOpInterface>(*op).getReductionBlockArgs();
2572 op, reductionArgs, builder, moduleTranslation, allocaIP,
2573 reductionDecls, privateReductionVariables, reductionVariableMap,
2578 auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
2581 moduleTranslation, allocaIP, deallocBlocks);
2582 builder.restoreIP(codegenIP);
2588 llvm::Value *numTeamsLower =
nullptr;
2589 if (
Value numTeamsLowerVar = op.getNumTeamsLower())
2590 numTeamsLower = moduleTranslation.
lookupValue(numTeamsLowerVar);
2592 llvm::Value *numTeamsUpper =
nullptr;
2593 if (!op.getNumTeamsUpperVars().empty())
2594 numTeamsUpper = moduleTranslation.
lookupValue(op.getNumTeams(0));
2596 llvm::Value *threadLimit =
nullptr;
2597 if (!op.getThreadLimitVars().empty())
2598 threadLimit = moduleTranslation.
lookupValue(op.getThreadLimit(0));
2600 llvm::Value *ifExpr =
nullptr;
2601 if (
Value ifVar = op.getIfExpr())
2604 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2605 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2607 ompLoc, bodyCB, numTeamsLower, numTeamsUpper, threadLimit, ifExpr);
2612 builder.restoreIP(*afterIP);
2613 if (doTeamsReduction) {
2616 op, builder, moduleTranslation, allocaIP, reductionDecls,
2617 privateReductionVariables, isByRef,
2623static llvm::omp::RTLDependenceKindTy
2626 case mlir::omp::ClauseTaskDepend::taskdependin:
2627 return llvm::omp::RTLDependenceKindTy::DepIn;
2631 case mlir::omp::ClauseTaskDepend::taskdependout:
2632 case mlir::omp::ClauseTaskDepend::taskdependinout:
2633 return llvm::omp::RTLDependenceKindTy::DepInOut;
2634 case mlir::omp::ClauseTaskDepend::taskdependmutexinoutset:
2635 return llvm::omp::RTLDependenceKindTy::DepMutexInOutSet;
2636 case mlir::omp::ClauseTaskDepend::taskdependinoutset:
2637 return llvm::omp::RTLDependenceKindTy::DepInOutSet;
2639 llvm_unreachable(
"unhandled depend kind");
2643 std::optional<ArrayAttr> dependKinds,
OperandRange dependVars,
2646 if (dependVars.empty())
2648 for (
auto dep : llvm::zip(dependVars, dependKinds->getValue())) {
2650 cast<mlir::omp::ClauseTaskDependAttr>(std::get<1>(dep)).getValue();
2652 llvm::Value *depVal = moduleTranslation.
lookupValue(std::get<0>(dep));
2653 llvm::OpenMPIRBuilder::DependData dd(type, depVal->getType(), depVal);
2654 dds.emplace_back(dd);
2666 llvm::IRBuilderBase &llvmBuilder, llvm::OpenMPIRBuilder &ompBuilder,
2668 auto finiCB = [&](llvm::OpenMPIRBuilder::InsertPointTy ip) -> llvm::Error {
2669 llvm::IRBuilderBase::InsertPointGuard guard(llvmBuilder);
2673 llvmBuilder.restoreIP(ip);
2679 cancelTerminators.push_back(llvmBuilder.CreateBr(ip.getBlock()));
2680 return llvm::Error::success();
2685 ompBuilder.pushFinalizationCB(
2695 llvm::OpenMPIRBuilder &ompBuilder,
2696 const llvm::OpenMPIRBuilder::InsertPointTy &afterIP) {
2697 ompBuilder.popFinalizationCB();
2698 llvm::BasicBlock *constructFini = afterIP.getBlock()->getSinglePredecessor();
2699 for (llvm::UncondBrInst *cancelBranch : cancelTerminators)
2700 cancelBranch->setSuccessor(constructFini);
2706class TaskContextStructManager {
2708 TaskContextStructManager(llvm::IRBuilderBase &builder,
2709 LLVM::ModuleTranslation &moduleTranslation,
2710 MutableArrayRef<omp::PrivateClauseOp> privateDecls)
2711 : builder{builder}, moduleTranslation{moduleTranslation},
2712 privateDecls{privateDecls} {}
2718 void generateTaskContextStruct();
2724 void createGEPsToPrivateVars();
2730 SmallVector<llvm::Value *>
2731 createGEPsToPrivateVars(llvm::Value *altStructPtr)
const;
2734 void freeStructPtr();
2736 MutableArrayRef<llvm::Value *> getLLVMPrivateVarGEPs() {
2737 return llvmPrivateVarGEPs;
2740 llvm::Value *getStructPtr() {
return structPtr; }
2743 llvm::IRBuilderBase &builder;
2744 LLVM::ModuleTranslation &moduleTranslation;
2745 MutableArrayRef<omp::PrivateClauseOp> privateDecls;
2748 SmallVector<llvm::Type *> privateVarTypes;
2752 SmallVector<llvm::Value *> llvmPrivateVarGEPs;
2755 llvm::Value *structPtr =
nullptr;
2757 llvm::Type *structTy =
nullptr;
2768 llvm::SmallVector<llvm::Value *> lowerBounds;
2769 llvm::SmallVector<llvm::Value *> upperBounds;
2770 llvm::SmallVector<llvm::Value *> steps;
2771 llvm::SmallVector<llvm::Value *> trips;
2773 llvm::Value *totalTrips;
2775 llvm::Value *lookUpAsI64(mlir::Value val,
const LLVM::ModuleTranslation &mt,
2776 llvm::IRBuilderBase &builder) {
2780 if (v->getType()->isIntegerTy(64))
2782 if (v->getType()->isIntegerTy())
2783 return builder.CreateSExtOrTrunc(v, builder.getInt64Ty());
2788 IteratorInfo(mlir::omp::IteratorOp itersOp,
2789 mlir::LLVM::ModuleTranslation &moduleTranslation,
2790 llvm::IRBuilderBase &builder) {
2791 dims = itersOp.getLoopLowerBounds().size();
2792 lowerBounds.resize(dims);
2793 upperBounds.resize(dims);
2797 for (
unsigned d = 0; d < dims; ++d) {
2798 llvm::Value *lb = lookUpAsI64(itersOp.getLoopLowerBounds()[d],
2799 moduleTranslation, builder);
2800 llvm::Value *ub = lookUpAsI64(itersOp.getLoopUpperBounds()[d],
2801 moduleTranslation, builder);
2803 lookUpAsI64(itersOp.getLoopSteps()[d], moduleTranslation, builder);
2804 assert(lb && ub && st &&
2805 "Expect lowerBounds, upperBounds, and steps in IteratorOp");
2806 assert((!llvm::isa<llvm::ConstantInt>(st) ||
2807 !llvm::cast<llvm::ConstantInt>(st)->isZero()) &&
2808 "Expect non-zero step in IteratorOp");
2810 lowerBounds[d] = lb;
2811 upperBounds[d] = ub;
2815 llvm::Value *diff = builder.CreateSub(ub, lb);
2816 llvm::Value *
div = builder.CreateSDiv(diff, st);
2817 trips[d] = builder.CreateAdd(
2818 div, llvm::ConstantInt::get(builder.getInt64Ty(), 1));
2821 totalTrips = llvm::ConstantInt::get(builder.getInt64Ty(), 1);
2822 for (
unsigned d = 0; d < dims; ++d)
2823 totalTrips = builder.CreateMul(totalTrips, trips[d]);
2826 unsigned getDims()
const {
return dims; }
2827 llvm::ArrayRef<llvm::Value *> getLowerBounds()
const {
return lowerBounds; }
2828 llvm::ArrayRef<llvm::Value *> getUpperBounds()
const {
return upperBounds; }
2829 llvm::ArrayRef<llvm::Value *> getSteps()
const {
return steps; }
2830 llvm::ArrayRef<llvm::Value *> getTrips()
const {
return trips; }
2831 llvm::Value *getTotalTrips()
const {
return totalTrips; }
2836void TaskContextStructManager::generateTaskContextStruct() {
2837 if (privateDecls.empty())
2839 privateVarTypes.reserve(privateDecls.size());
2841 for (omp::PrivateClauseOp &privOp : privateDecls) {
2844 if (!privOp.readsFromMold())
2846 Type mlirType = privOp.getType();
2847 privateVarTypes.push_back(moduleTranslation.
convertType(mlirType));
2850 if (privateVarTypes.empty())
2853 structTy = llvm::StructType::get(moduleTranslation.
getLLVMContext(),
2856 llvm::DataLayout dataLayout =
2857 builder.GetInsertBlock()->getModule()->getDataLayout();
2858 llvm::Type *intPtrTy = builder.getIntPtrTy(dataLayout);
2859 llvm::Constant *allocSize = llvm::ConstantExpr::getSizeOf(structTy);
2862 structPtr = builder.CreateMalloc(intPtrTy, allocSize,
2864 "omp.task.context_ptr");
2867SmallVector<llvm::Value *> TaskContextStructManager::createGEPsToPrivateVars(
2868 llvm::Value *altStructPtr)
const {
2869 SmallVector<llvm::Value *> ret;
2872 ret.reserve(privateDecls.size());
2873 llvm::Value *zero = builder.getInt32(0);
2875 for (
auto privDecl : privateDecls) {
2876 if (!privDecl.readsFromMold()) {
2878 ret.push_back(
nullptr);
2881 llvm::Value *iVal = builder.getInt32(i);
2882 llvm::Value *gep = builder.CreateGEP(structTy, altStructPtr, {zero, iVal});
2889void TaskContextStructManager::createGEPsToPrivateVars() {
2891 assert(privateVarTypes.empty());
2895 llvmPrivateVarGEPs = createGEPsToPrivateVars(structPtr);
2898void TaskContextStructManager::freeStructPtr() {
2902 llvm::IRBuilderBase::InsertPointGuard guard{builder};
2904 builder.SetInsertPoint(builder.GetInsertBlock()->getTerminator());
2905 builder.CreateFree(structPtr);
2909 llvm::OpenMPIRBuilder &ompBuilder,
2910 llvm::Value *affinityList, llvm::Value *
index,
2911 llvm::Value *addr, llvm::Value *len) {
2912 llvm::StructType *kmpTaskAffinityInfoTy =
2913 ompBuilder.getKmpTaskAffinityInfoTy();
2914 llvm::Value *entry = builder.CreateInBoundsGEP(
2915 kmpTaskAffinityInfoTy, affinityList,
index,
"omp.affinity.entry");
2917 addr = builder.CreatePtrToInt(addr, kmpTaskAffinityInfoTy->getElementType(0));
2918 len = builder.CreateIntCast(len, kmpTaskAffinityInfoTy->getElementType(1),
2920 llvm::Value *flags = builder.getInt32(0);
2922 builder.CreateStore(addr,
2923 builder.CreateStructGEP(kmpTaskAffinityInfoTy, entry, 0));
2924 builder.CreateStore(len,
2925 builder.CreateStructGEP(kmpTaskAffinityInfoTy, entry, 1));
2926 builder.CreateStore(flags,
2927 builder.CreateStructGEP(kmpTaskAffinityInfoTy, entry, 2));
2931 llvm::IRBuilderBase &builder,
2933 llvm::Value *affinityList) {
2934 for (
auto [i, affinityVar] : llvm::enumerate(affinityVars)) {
2935 auto entryOp = affinityVar.getDefiningOp<mlir::omp::AffinityEntryOp>();
2936 assert(entryOp &&
"affinity item must be omp.affinity_entry");
2938 llvm::Value *addr = moduleTranslation.
lookupValue(entryOp.getAddr());
2939 llvm::Value *len = moduleTranslation.
lookupValue(entryOp.getLen());
2940 assert(addr && len &&
"expect affinity addr and len to be non-null");
2942 affinityList, builder.getInt64(i), addr, len);
2946static mlir::LogicalResult
2949 llvm::IRBuilderBase &builder,
2951 llvm::Value *tmp = linearIV;
2952 for (
int d = (
int)iterInfo.getDims() - 1; d >= 0; --d) {
2953 llvm::Value *trip = iterInfo.getTrips()[d];
2955 llvm::Value *idx = builder.CreateURem(tmp, trip);
2957 tmp = builder.CreateUDiv(tmp, trip);
2960 llvm::Value *physIV = builder.CreateAdd(
2961 iterInfo.getLowerBounds()[d],
2962 builder.CreateMul(idx, iterInfo.getSteps()[d]),
"omp.it.phys_iv");
2968 moduleTranslation.
mapBlock(&iteratorRegionBlock, builder.GetInsertBlock());
2969 if (mlir::failed(moduleTranslation.
convertBlock(iteratorRegionBlock,
2972 return mlir::failure();
2974 return mlir::success();
2980static mlir::LogicalResult
2983 IteratorInfo &iterInfo, llvm::StringRef loopName,
2988 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
2990 auto bodyGen = [&](llvm::OpenMPIRBuilder::InsertPointTy bodyIP,
2991 llvm::Value *linearIV) -> llvm::Error {
2992 llvm::IRBuilderBase::InsertPointGuard guard(builder);
2993 builder.restoreIP(bodyIP);
2996 builder, moduleTranslation))) {
2997 return llvm::make_error<llvm::StringError>(
2998 "failed to convert iterator region", llvm::inconvertibleErrorCode());
3002 mlir::dyn_cast<mlir::omp::YieldOp>(iteratorRegionBlock.
getTerminator());
3003 assert(yield && yield.getResults().size() == 1 &&
3004 "expect omp.yield in iterator region to have one result");
3006 genStoreEntry(linearIV, yield);
3012 return llvm::Error::success();
3015 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
3017 loc, iterInfo.getTotalTrips(), bodyGen, loopName);
3021 builder.restoreIP(*afterIP);
3023 return mlir::success();
3026static mlir::LogicalResult
3029 llvm::OpenMPIRBuilder::AffinityData &ad) {
3031 if (taskOp.getAffinityVars().empty() && taskOp.getIterated().empty()) {
3034 return mlir::success();
3038 llvm::StructType *kmpTaskAffinityInfoTy =
3041 auto allocateAffinityList = [&](llvm::Value *count) -> llvm::Value * {
3042 llvm::IRBuilderBase::InsertPointGuard guard(builder);
3043 if (llvm::isa<llvm::Constant>(count) || llvm::isa<llvm::Argument>(count))
3045 return builder.CreateAlloca(kmpTaskAffinityInfoTy, count,
3046 "omp.affinity_list");
3049 auto createAffinity =
3050 [&](llvm::Value *count,
3051 llvm::Value *info) -> llvm::OpenMPIRBuilder::AffinityData {
3052 llvm::OpenMPIRBuilder::AffinityData ad{};
3053 ad.Count = builder.CreateTrunc(count, builder.getInt32Ty());
3055 builder.CreatePointerBitCastOrAddrSpaceCast(info, builder.getPtrTy(0));
3059 if (!taskOp.getAffinityVars().empty()) {
3060 llvm::Value *count = llvm::ConstantInt::get(
3061 builder.getInt64Ty(), taskOp.getAffinityVars().size());
3062 llvm::Value *list = allocateAffinityList(count);
3065 ads.emplace_back(createAffinity(count, list));
3068 if (!taskOp.getIterated().empty()) {
3069 for (
auto [i, iter] : llvm::enumerate(taskOp.getIterated())) {
3070 auto itersOp = iter.getDefiningOp<omp::IteratorOp>();
3071 assert(itersOp &&
"iterated value must be defined by omp.iterator");
3072 IteratorInfo iterInfo(itersOp, moduleTranslation, builder);
3073 llvm::Value *affList = allocateAffinityList(iterInfo.getTotalTrips());
3075 itersOp, builder, moduleTranslation, iterInfo,
"iterator",
3076 [&](llvm::Value *linearIV, mlir::omp::YieldOp yield) {
3077 auto entryOp = yield.getResults()[0]
3078 .getDefiningOp<mlir::omp::AffinityEntryOp>();
3079 assert(entryOp &&
"expect yield produce an affinity entry");
3086 affList, linearIV, addr, len);
3088 return llvm::failure();
3089 ads.emplace_back(createAffinity(iterInfo.getTotalTrips(), affList));
3093 llvm::Value *totalAffinityCount = builder.getInt32(0);
3094 for (
const auto &affinity : ads)
3095 totalAffinityCount = builder.CreateAdd(
3097 builder.CreateIntCast(affinity.Count, builder.getInt32Ty(),
3100 llvm::Value *affinityInfo = ads.front().Info;
3101 if (ads.size() > 1) {
3102 llvm::StructType *kmpTaskAffinityInfoTy =
3104 llvm::Value *affinityInfoElemSize = builder.getInt64(
3105 moduleTranslation.
getLLVMModule()->getDataLayout().getTypeAllocSize(
3106 kmpTaskAffinityInfoTy));
3108 llvm::Value *packedAffinityInfo = allocateAffinityList(totalAffinityCount);
3109 llvm::Value *packedAffinityInfoOffset = builder.getInt32(0);
3110 for (
const auto &affinity : ads) {
3111 llvm::Value *affinityCount = builder.CreateIntCast(
3112 affinity.Count, builder.getInt32Ty(),
false);
3113 llvm::Value *affinityCountInt64 = builder.CreateIntCast(
3114 affinityCount, builder.getInt64Ty(),
false);
3115 llvm::Value *affinityInfoSize =
3116 builder.CreateMul(affinityCountInt64, affinityInfoElemSize);
3118 llvm::Value *packedAffinityInfoIndex = builder.CreateIntCast(
3119 packedAffinityInfoOffset, kmpTaskAffinityInfoTy->getElementType(0),
3121 packedAffinityInfoIndex = builder.CreateInBoundsGEP(
3122 kmpTaskAffinityInfoTy, packedAffinityInfo, packedAffinityInfoIndex);
3124 builder.CreateMemCpy(
3125 packedAffinityInfoIndex, llvm::Align(1),
3126 builder.CreatePointerBitCastOrAddrSpaceCast(
3127 affinity.Info, builder.getPtrTy(packedAffinityInfoIndex->getType()
3128 ->getPointerAddressSpace())),
3129 llvm::Align(1), affinityInfoSize);
3131 packedAffinityInfoOffset =
3132 builder.CreateAdd(packedAffinityInfoOffset, affinityCount);
3135 affinityInfo = packedAffinityInfo;
3138 ad.Count = totalAffinityCount;
3139 ad.Info = affinityInfo;
3141 return mlir::success();
3147static mlir::LogicalResult
3150 std::optional<ArrayAttr> dependIteratedKinds,
3151 llvm::IRBuilderBase &builder,
3153 llvm::OpenMPIRBuilder::DependenciesInfo &taskDeps) {
3154 if (dependIterated.empty()) {
3157 return mlir::success();
3161 llvm::Type *dependInfoTy = ompBuilder.DependInfo;
3162 unsigned numLocator = dependVars.size();
3165 llvm::Value *totalCount =
3166 llvm::ConstantInt::get(builder.getInt64Ty(), numLocator);
3169 for (
auto iter : dependIterated) {
3170 auto itersOp = iter.getDefiningOp<mlir::omp::IteratorOp>();
3171 assert(itersOp &&
"depend_iterated value must be defined by omp.iterator");
3172 iterInfos.emplace_back(itersOp, moduleTranslation, builder);
3174 builder.CreateAdd(totalCount, iterInfos.back().getTotalTrips());
3179 llvm::Constant *allocSize = llvm::ConstantExpr::getSizeOf(dependInfoTy);
3180 llvm::Value *depArray =
3181 builder.CreateMalloc(ompBuilder.SizeTy, allocSize, totalCount,
3182 nullptr,
".dep.arr.addr");
3185 if (numLocator > 0) {
3188 for (
auto [i, dd] : llvm::enumerate(dds)) {
3189 llvm::Value *idx = llvm::ConstantInt::get(builder.getInt64Ty(), i);
3190 llvm::Value *entry =
3191 builder.CreateInBoundsGEP(dependInfoTy, depArray, idx);
3192 ompBuilder.emitTaskDependency(builder, entry, dd);
3197 llvm::Value *offset =
3198 llvm::ConstantInt::get(builder.getInt64Ty(), numLocator);
3199 for (
auto [i, iterInfo] : llvm::enumerate(iterInfos)) {
3200 auto kindAttr = cast<mlir::omp::ClauseTaskDependAttr>(
3201 dependIteratedKinds->getValue()[i]);
3202 llvm::omp::RTLDependenceKindTy rtlKind =
3205 auto itersOp = dependIterated[i].getDefiningOp<mlir::omp::IteratorOp>();
3207 itersOp, builder, moduleTranslation, iterInfo,
"dep_iterator",
3208 [&](llvm::Value *linearIV, mlir::omp::YieldOp yield) {
3210 moduleTranslation.
lookupValue(yield.getResults()[0]);
3211 llvm::Value *idx = builder.CreateAdd(offset, linearIV);
3212 llvm::Value *entry =
3213 builder.CreateInBoundsGEP(dependInfoTy, depArray, idx);
3214 ompBuilder.emitTaskDependency(
3216 llvm::OpenMPIRBuilder::DependData{rtlKind, addr->getType(),
3219 return mlir::failure();
3222 offset = builder.CreateAdd(offset, iterInfo.getTotalTrips());
3225 taskDeps.DepArray = depArray;
3226 taskDeps.NumDeps = builder.CreateTrunc(totalCount, builder.getInt32Ty());
3227 return mlir::success();
3234 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
3239 TaskContextStructManager taskStructMgr{builder, moduleTranslation,
3251 InsertPointTy allocaIP =
3256 assert(builder.GetInsertPoint() == builder.GetInsertBlock()->end());
3257 llvm::BasicBlock *taskStartBlock = llvm::BasicBlock::Create(
3258 builder.getContext(),
"omp.task.start",
3259 builder.GetInsertBlock()->getParent());
3260 llvm::Instruction *branchToTaskStartBlock = builder.CreateBr(taskStartBlock);
3261 builder.SetInsertPoint(branchToTaskStartBlock);
3264 llvm::BasicBlock *copyBlock =
3265 splitBB(builder,
true,
"omp.private.copy");
3266 llvm::BasicBlock *initBlock =
3267 splitBB(builder,
true,
"omp.private.init");
3283 moduleTranslation, allocaIP, deallocBlocks);
3286 builder.SetInsertPoint(initBlock->getTerminator());
3289 taskStructMgr.generateTaskContextStruct();
3296 taskStructMgr.createGEPsToPrivateVars();
3298 for (
auto [privDecl, mlirPrivVar, blockArg, llvmPrivateVarAlloc] :
3301 taskStructMgr.getLLVMPrivateVarGEPs())) {
3303 if (!privDecl.readsFromMold())
3305 assert(llvmPrivateVarAlloc &&
3306 "reads from mold so shouldn't have been skipped");
3309 initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar,
3310 blockArg, llvmPrivateVarAlloc, initBlock);
3311 if (!privateVarOrErr)
3312 return handleError(privateVarOrErr, *taskOp.getOperation());
3321 [[maybe_unused]] llvm::Value *llvmPrivateVar = llvmPrivateVarAlloc;
3322 if ((privateVarOrErr.get() != llvmPrivateVarAlloc) &&
3323 !mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
3324 builder.CreateStore(privateVarOrErr.get(), llvmPrivateVarAlloc);
3326 llvmPrivateVar = builder.CreateLoad(privateVarOrErr.get()->getType(),
3327 llvmPrivateVarAlloc);
3329 assert(llvmPrivateVar->getType() ==
3330 moduleTranslation.
convertType(blockArg.getType()));
3340 taskOp, builder, moduleTranslation, privateVarsInfo.
mlirVars,
3341 taskStructMgr.getLLVMPrivateVarGEPs(), privateVarsInfo.
privatizers,
3342 taskOp.getPrivateNeedsBarrier())))
3343 return llvm::failure();
3345 llvm::OpenMPIRBuilder::AffinityData ad;
3347 return llvm::failure();
3357 taskOp.getOperation(), taskOp.getInReductionSyms(),
"omp.task",
3358 "in_reduction", inRedDecls)))
3361 inRedOrigPtrs.reserve(inRedDecls.size());
3362 for (
Value v : taskOp.getInReductionVars())
3363 inRedOrigPtrs.push_back(moduleTranslation.
lookupValue(v));
3366 builder.SetInsertPoint(taskStartBlock);
3369 [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
3374 moduleTranslation, allocaIP, deallocBlocks);
3377 builder.restoreIP(codegenIP);
3379 llvm::BasicBlock *privInitBlock =
nullptr;
3381 for (
auto [i, zip] : llvm::enumerate(llvm::zip_equal(
3384 auto [blockArg, privDecl, mlirPrivVar] = zip;
3386 if (privDecl.readsFromMold())
3389 llvm::IRBuilderBase::InsertPointGuard guard(builder);
3390 llvm::Type *llvmAllocType =
3391 moduleTranslation.
convertType(privDecl.getType());
3392 builder.SetInsertPoint(allocaIP.getBlock()->getTerminator());
3393 llvm::Value *llvmPrivateVar = builder.CreateAlloca(
3394 llvmAllocType,
nullptr,
"omp.private.alloc");
3397 initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar,
3398 blockArg, llvmPrivateVar, privInitBlock);
3399 if (!privateVarOrError)
3400 return privateVarOrError.takeError();
3401 moduleTranslation.
mapValue(blockArg, privateVarOrError.get());
3402 privateVarsInfo.
llvmVars[i] = privateVarOrError.get();
3405 taskStructMgr.createGEPsToPrivateVars();
3406 for (
auto [i, llvmPrivVar] :
3407 llvm::enumerate(taskStructMgr.getLLVMPrivateVarGEPs())) {
3409 assert(privateVarsInfo.
llvmVars[i] &&
3410 "This is added in the loop above");
3413 privateVarsInfo.
llvmVars[i] = llvmPrivVar;
3418 for (
auto [blockArg, llvmPrivateVar, privateDecl] :
3422 if (!privateDecl.readsFromMold())
3425 if (!mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
3426 llvmPrivateVar = builder.CreateLoad(
3427 moduleTranslation.
convertType(blockArg.getType()), llvmPrivateVar);
3429 assert(llvmPrivateVar->getType() ==
3430 moduleTranslation.
convertType(blockArg.getType()));
3431 moduleTranslation.
mapValue(blockArg, llvmPrivateVar);
3442 if (!inRedDecls.empty()) {
3443 auto iface = cast<omp::BlockArgOpenMPOpInterface>(taskOp.getOperation());
3446 llvm::LLVMContext &llvmCtx = m->getContext();
3447 llvm::OpenMPIRBuilder::LocationDescription bodyLoc(builder);
3448 uint32_t srcLocSize;
3449 llvm::Constant *srcLocStr =
3450 ompB.getOrCreateSrcLocStr(bodyLoc, srcLocSize);
3451 llvm::Value *bodyIdent = ompB.getOrCreateIdent(srcLocStr, srcLocSize);
3454 ompB.updateToLocation(bodyLoc);
3455 llvm::Value *bodyGtid = ompB.getOrCreateThreadID(bodyIdent);
3456 llvm::FunctionCallee getThData = ompB.getOrCreateRuntimeFunction(
3457 *m, llvm::omp::OMPRTL___kmpc_task_reduction_get_th_data);
3458 llvm::Type *ptrTy = llvm::PointerType::getUnqual(llvmCtx);
3459 llvm::Value *nullDesc = llvm::ConstantPointerNull::get(ptrTy);
3461 for (
auto [blockArg, origPtr] :
3462 llvm::zip_equal(inRedBlockArgs, inRedOrigPtrs)) {
3469 llvm::Value *lookupPtr = origPtr;
3470 if (
auto *origPtrTy =
3471 llvm::dyn_cast<llvm::PointerType>(lookupPtr->getType());
3472 origPtrTy && origPtrTy->getAddressSpace() != 0)
3473 lookupPtr = builder.CreateAddrSpaceCast(lookupPtr, ptrTy);
3474 llvm::Value *priv = builder.CreateCall(
3475 getThData, {bodyGtid, nullDesc, lookupPtr},
"omp.inred.priv");
3476 if (
auto *argPtrTy = llvm::dyn_cast<llvm::PointerType>(
3477 moduleTranslation.
convertType(blockArg.getType()));
3478 argPtrTy && argPtrTy->getAddressSpace() != 0)
3479 priv = builder.CreateAddrSpaceCast(priv, argPtrTy);
3480 moduleTranslation.
mapValue(blockArg, priv);
3485 taskOp.getRegion(),
"omp.task.region", builder, moduleTranslation);
3486 if (failed(
handleError(continuationBlockOrError, *taskOp)))
3487 return llvm::make_error<PreviouslyReportedError>();
3489 builder.SetInsertPoint(continuationBlockOrError.get()->getTerminator());
3492 taskOp.getLoc(), privateVarsInfo)))
3493 return llvm::make_error<PreviouslyReportedError>();
3496 taskStructMgr.freeStructPtr();
3498 return llvm::Error::success();
3507 llvm::omp::Directive::OMPD_taskgroup);
3509 llvm::OpenMPIRBuilder::DependenciesInfo dependencies;
3510 if (failed(
buildDependData(taskOp.getDependVars(), taskOp.getDependKinds(),
3511 taskOp.getDependIterated(),
3512 taskOp.getDependIteratedKinds(), builder,
3513 moduleTranslation, dependencies)))
3516 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
3517 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
3519 ompLoc, allocaIP, deallocBlocks, bodyCB, !taskOp.getUntied(),
3521 moduleTranslation.
lookupValue(taskOp.getIfExpr()), dependencies, ad,
3522 taskOp.getMergeable(),
3523 moduleTranslation.
lookupValue(taskOp.getEventHandle()),
3524 moduleTranslation.
lookupValue(taskOp.getPriority()),
3525 taskOp.getThreadset() == omp::ThreadsetPolicy::omp_pool);
3533 builder.restoreIP(*afterIP);
3535 if (dependencies.DepArray)
3536 builder.CreateFree(dependencies.DepArray);
3545 llvm::IRBuilderBase &builder,
3553 loopWrapperOp.getRegion(),
"omp.taskloop.wrapper.region", builder,
3556 if (failed(
handleError(continuationBlockOrError, opInst)))
3559 builder.SetInsertPoint(continuationBlockOrError.get());
3567static llvm::Expected<llvm::Value *>
3570 llvm::IRBuilderBase &builder) {
3571 if (llvm::Value *mapped = moduleTranslation.
lookupValue(value))
3576 return llvm::make_error<llvm::StringError>(
3577 "value is a block argument and is not mapped",
3578 llvm::inconvertibleErrorCode());
3580 return llvm::make_error<llvm::StringError>(
3581 "unsupported op defining taskloop loop bound",
3582 llvm::inconvertibleErrorCode());
3592 if (!operandOrError)
3593 return operandOrError.takeError();
3594 moduleTranslation.
mapValue(operand, *operandOrError);
3595 mappingsToRemove.push_back(operand);
3599 return llvm::make_error<llvm::StringError>(
3600 "failed to convert op defining taskloop loop bound",
3601 llvm::inconvertibleErrorCode());
3604 assert(
result &&
"expected conversion of loop bound op to produce a value");
3608 mappingsToRemove.push_back(resultValue);
3610 for (
Value mappedValue : mappingsToRemove)
3619 llvm::Value *&lbVal, llvm::Value *&ubVal,
3620 llvm::Value *&stepVal) {
3628 return firstLbOrErr.takeError();
3630 llvm::Type *boundType = (*firstLbOrErr)->getType();
3631 ubVal = builder.getIntN(boundType->getIntegerBitWidth(), 1);
3632 if (loopOp.getCollapseNumLoops() > 1) {
3650 for (uint64_t i = 0; i < loopOp.getCollapseNumLoops(); i++) {
3652 i == 0 ? std::move(firstLbOrErr)
3656 return lbOrErr.takeError();
3658 upperBounds[i], moduleTranslation, builder);
3660 return ubOrErr.takeError();
3664 return stepOrErr.takeError();
3666 llvm::Value *loopLb = *lbOrErr;
3667 llvm::Value *loopUb = *ubOrErr;
3668 llvm::Value *loopStep = *stepOrErr;
3674 llvm::Value *loopLbMinusOne = builder.CreateSub(
3675 loopLb, builder.getIntN(boundType->getIntegerBitWidth(), 1));
3676 llvm::Value *loopUbMinusOne = builder.CreateSub(
3677 loopUb, builder.getIntN(boundType->getIntegerBitWidth(), 1));
3678 llvm::Value *boundsCmp = builder.CreateICmpSLT(loopLb, loopUb);
3679 llvm::Value *ubMinusLb = builder.CreateSub(loopUb, loopLbMinusOne);
3680 llvm::Value *lbMinusUb = builder.CreateSub(loopLb, loopUbMinusOne);
3681 llvm::Value *loopTripCount =
3682 builder.CreateSelect(boundsCmp, ubMinusLb, lbMinusUb);
3683 loopTripCount = builder.CreateBinaryIntrinsic(
3684 llvm::Intrinsic::abs, loopTripCount, builder.getFalse());
3688 llvm::Value *loopTripCountDivStep =
3689 builder.CreateSDiv(loopTripCount, loopStep);
3690 loopTripCountDivStep = builder.CreateBinaryIntrinsic(
3691 llvm::Intrinsic::abs, loopTripCountDivStep, builder.getFalse());
3692 llvm::Value *loopTripCountRem =
3693 builder.CreateSRem(loopTripCount, loopStep);
3694 loopTripCountRem = builder.CreateBinaryIntrinsic(
3695 llvm::Intrinsic::abs, loopTripCountRem, builder.getFalse());
3696 llvm::Value *needsRoundUp = builder.CreateICmpNE(
3698 builder.getIntN(loopTripCountRem->getType()->getIntegerBitWidth(),
3701 builder.CreateAdd(loopTripCountDivStep,
3702 builder.CreateZExtOrTrunc(
3703 needsRoundUp, loopTripCountDivStep->getType()));
3704 ubVal = builder.CreateMul(ubVal, loopTripCount);
3706 lbVal = builder.getIntN(boundType->getIntegerBitWidth(), 1);
3707 stepVal = builder.getIntN(boundType->getIntegerBitWidth(), 1);
3712 return ubOrErr.takeError();
3716 return stepOrErr.takeError();
3717 lbVal = *firstLbOrErr;
3719 stepVal = *stepOrErr;
3722 assert(lbVal !=
nullptr &&
"Expected value for lbVal");
3723 assert(ubVal !=
nullptr &&
"Expected value for ubVal");
3724 assert(stepVal !=
nullptr &&
"Expected value for stepVal");
3725 return llvm::Error::success();
3731 llvm::IRBuilderBase &builder,
3733 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
3735 omp::TaskloopWrapperOp loopWrapperOp = contextOp.getLoopOp();
3743 TaskContextStructManager taskStructMgr{builder, moduleTranslation,
3747 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
3750 assert(builder.GetInsertPoint() == builder.GetInsertBlock()->end());
3751 llvm::BasicBlock *taskloopStartBlock = llvm::BasicBlock::Create(
3752 builder.getContext(),
"omp.taskloop.wrapper.start",
3753 builder.GetInsertBlock()->getParent());
3754 llvm::Instruction *branchToTaskloopStartBlock =
3755 builder.CreateBr(taskloopStartBlock);
3756 builder.SetInsertPoint(branchToTaskloopStartBlock);
3758 llvm::BasicBlock *copyBlock =
3759 splitBB(builder,
true,
"omp.private.copy");
3760 llvm::BasicBlock *initBlock =
3761 splitBB(builder,
true,
"omp.private.init");
3764 moduleTranslation, allocaIP, deallocBlocks);
3767 builder.SetInsertPoint(initBlock->getTerminator());
3770 taskStructMgr.generateTaskContextStruct();
3771 taskStructMgr.createGEPsToPrivateVars();
3773 llvmFirstPrivateVars.resize(privateVarsInfo.
blockArgs.size());
3775 for (
auto [i, zip] : llvm::enumerate(llvm::zip_equal(
3777 privateVarsInfo.
blockArgs, taskStructMgr.getLLVMPrivateVarGEPs()))) {
3778 auto [privDecl, mlirPrivVar, blockArg, llvmPrivateVarAlloc] = zip;
3780 if (!privDecl.readsFromMold())
3782 assert(llvmPrivateVarAlloc &&
3783 "reads from mold so shouldn't have been skipped");
3786 initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar,
3787 blockArg, llvmPrivateVarAlloc, initBlock);
3788 if (!privateVarOrErr)
3789 return handleError(privateVarOrErr, *contextOp.getOperation());
3791 llvmFirstPrivateVars[i] = privateVarOrErr.get();
3793 llvm::IRBuilderBase::InsertPointGuard guard(builder);
3794 builder.SetInsertPoint(builder.GetInsertBlock()->getTerminator());
3796 [[maybe_unused]] llvm::Value *llvmPrivateVar = llvmPrivateVarAlloc;
3797 if ((privateVarOrErr.get() != llvmPrivateVarAlloc) &&
3798 !mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
3799 builder.CreateStore(privateVarOrErr.get(), llvmPrivateVarAlloc);
3801 llvmPrivateVar = builder.CreateLoad(privateVarOrErr.get()->getType(),
3802 llvmPrivateVarAlloc);
3804 assert(llvmPrivateVar->getType() ==
3805 moduleTranslation.
convertType(blockArg.getType()));
3811 contextOp, builder, moduleTranslation, privateVarsInfo.
mlirVars,
3812 taskStructMgr.getLLVMPrivateVarGEPs(), privateVarsInfo.
privatizers,
3813 contextOp.getPrivateNeedsBarrier())))
3814 return llvm::failure();
3824 contextOp.getOperation(), contextOp.getReductionSyms(),
3825 "omp.taskloop.context",
"reduction", redDecls)))
3829 contextOp.getOperation(), contextOp.getInReductionSyms(),
3830 "omp.taskloop.context",
"in_reduction", inRedDecls)))
3836 redOrigPtrs.reserve(redDecls.size());
3837 for (
Value v : contextOp.getReductionVars())
3838 redOrigPtrs.push_back(moduleTranslation.
lookupValue(v));
3840 inRedOrigPtrs.reserve(inRedDecls.size());
3841 for (
Value v : contextOp.getInReductionVars())
3842 inRedOrigPtrs.push_back(moduleTranslation.
lookupValue(v));
3846 builder.SetInsertPoint(taskloopStartBlock);
3848 llvm::OpenMPIRBuilder &ompBuilderRef = *moduleTranslation.
getOpenMPBuilder();
3855 bool implicitTaskgroup = !redDecls.empty();
3856 llvm::Value *redDesc =
nullptr;
3857 if (implicitTaskgroup) {
3858 llvm::OpenMPIRBuilder::LocationDescription redLoc(builder);
3859 uint32_t srcLocSize;
3860 llvm::Constant *srcLocStr =
3861 ompBuilderRef.getOrCreateSrcLocStr(redLoc, srcLocSize);
3862 llvm::Value *ident = ompBuilderRef.getOrCreateIdent(srcLocStr, srcLocSize);
3865 ompBuilderRef.updateToLocation(redLoc);
3866 llvm::Value *outerGtid = ompBuilderRef.getOrCreateThreadID(ident);
3867 llvm::FunctionCallee taskgroupFn = ompBuilderRef.getOrCreateRuntimeFunction(
3868 *module, llvm::omp::OMPRTL___kmpc_taskgroup);
3869 builder.CreateCall(taskgroupFn, {ident, outerGtid});
3872 "__omp_taskloop_taskred_", builder,
3873 allocaIP, moduleTranslation);
3878 auto loopOp = cast<omp::LoopNestOp>(loopWrapperOp.getWrappedLoop());
3879 llvm::Value *lbVal =
nullptr;
3880 llvm::Value *ubVal =
nullptr;
3881 llvm::Value *stepVal =
nullptr;
3883 loopOp, builder, moduleTranslation, lbVal, ubVal, stepVal))
3887 [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
3892 moduleTranslation, allocaIP, deallocBlocks);
3895 builder.restoreIP(codegenIP);
3897 llvm::BasicBlock *privInitBlock =
nullptr;
3899 for (
auto [i, zip] : llvm::enumerate(llvm::zip_equal(
3902 auto [blockArg, privDecl, mlirPrivVar] = zip;
3904 if (privDecl.readsFromMold())
3907 llvm::IRBuilderBase::InsertPointGuard guard(builder);
3908 llvm::Type *llvmAllocType =
3909 moduleTranslation.
convertType(privDecl.getType());
3910 builder.SetInsertPoint(allocaIP.getBlock()->getTerminator());
3911 llvm::Value *llvmPrivateVar = builder.CreateAlloca(
3912 llvmAllocType,
nullptr,
"omp.private.alloc");
3915 initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar,
3916 blockArg, llvmPrivateVar, privInitBlock);
3917 if (!privateVarOrError)
3918 return privateVarOrError.takeError();
3919 moduleTranslation.
mapValue(blockArg, privateVarOrError.get());
3920 privateVarsInfo.
llvmVars[i] = privateVarOrError.get();
3923 taskStructMgr.createGEPsToPrivateVars();
3924 for (
auto [i, llvmPrivVar] :
3925 llvm::enumerate(taskStructMgr.getLLVMPrivateVarGEPs())) {
3927 assert(privateVarsInfo.
llvmVars[i] &&
3928 "This is added in the loop above");
3931 privateVarsInfo.
llvmVars[i] = llvmPrivVar;
3936 for (
auto [blockArg, llvmPrivateVar, privateDecl] :
3940 if (!privateDecl.readsFromMold())
3943 if (!mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
3944 llvmPrivateVar = builder.CreateLoad(
3945 moduleTranslation.
convertType(blockArg.getType()), llvmPrivateVar);
3947 assert(llvmPrivateVar->getType() ==
3948 moduleTranslation.
convertType(blockArg.getType()));
3949 moduleTranslation.
mapValue(blockArg, llvmPrivateVar);
3961 if (!redDecls.empty() || !inRedDecls.empty()) {
3963 cast<omp::BlockArgOpenMPOpInterface>(contextOp.getOperation());
3966 llvm::LLVMContext &llvmCtx = m->getContext();
3967 llvm::OpenMPIRBuilder::LocationDescription bodyLoc(builder);
3968 uint32_t srcLocSize;
3969 llvm::Constant *srcLocStr =
3970 ompB.getOrCreateSrcLocStr(bodyLoc, srcLocSize);
3971 llvm::Value *bodyIdent = ompB.getOrCreateIdent(srcLocStr, srcLocSize);
3974 ompB.updateToLocation(bodyLoc);
3975 llvm::Value *bodyGtid = ompB.getOrCreateThreadID(bodyIdent);
3976 llvm::FunctionCallee getThData = ompB.getOrCreateRuntimeFunction(
3977 *m, llvm::omp::OMPRTL___kmpc_task_reduction_get_th_data);
3978 llvm::Type *ptrTy = llvm::PointerType::getUnqual(llvmCtx);
3988 auto remapReductionArg = [&](
BlockArgument blockArg, llvm::Value *desc,
3989 llvm::Value *origPtr,
3990 const llvm::Twine &name) {
3991 if (
auto *origPtrTy =
3992 llvm::dyn_cast<llvm::PointerType>(origPtr->getType());
3993 origPtrTy && origPtrTy->getAddressSpace() != 0)
3994 origPtr = builder.CreateAddrSpaceCast(origPtr, ptrTy);
3996 builder.CreateCall(getThData, {bodyGtid, desc, origPtr}, name);
3997 if (
auto *argPtrTy = llvm::dyn_cast<llvm::PointerType>(
3999 argPtrTy && argPtrTy->getAddressSpace() != 0)
4000 priv = builder.CreateAddrSpaceCast(priv, argPtrTy);
4001 moduleTranslation.
mapValue(blockArg, priv);
4005 for (
auto [blockArg, origPtr] :
4006 llvm::zip_equal(redBlockArgs, redOrigPtrs))
4007 remapReductionArg(blockArg, redDesc, origPtr,
"omp.taskred.priv");
4009 llvm::Value *nullDesc = llvm::ConstantPointerNull::get(ptrTy);
4010 for (
auto [blockArg, origPtr] :
4011 llvm::zip_equal(inRedBlockArgs, inRedOrigPtrs))
4012 remapReductionArg(blockArg, nullDesc, origPtr,
"omp.inred.priv");
4018 contextOp.getRegion(),
"omp.taskloop.context.region", builder,
4021 if (failed(
handleError(continuationBlockOrError, opInst)))
4022 return llvm::make_error<PreviouslyReportedError>();
4024 builder.SetInsertPoint(continuationBlockOrError.get()->getTerminator());
4032 contextOp.getLoc(), privateVarsInfo)))
4033 return llvm::make_error<PreviouslyReportedError>();
4036 taskStructMgr.freeStructPtr();
4038 return llvm::Error::success();
4044 auto taskDupCB = [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
4045 llvm::Value *destPtr, llvm::Value *srcPtr)
4047 llvm::IRBuilderBase::InsertPointGuard guard(builder);
4048 builder.restoreIP(codegenIP);
4051 builder.getPtrTy(srcPtr->getType()->getPointerAddressSpace());
4053 builder.CreateLoad(ptrTy, srcPtr,
"omp.taskloop.context.src");
4055 TaskContextStructManager &srcStructMgr = taskStructMgr;
4056 TaskContextStructManager destStructMgr(builder, moduleTranslation,
4058 destStructMgr.generateTaskContextStruct();
4059 llvm::Value *dest = destStructMgr.getStructPtr();
4060 dest->setName(
"omp.taskloop.context.dest");
4061 builder.CreateStore(dest, destPtr);
4064 srcStructMgr.createGEPsToPrivateVars(src);
4066 destStructMgr.createGEPsToPrivateVars(dest);
4069 for (
auto [privDecl, mold, blockArg, llvmPrivateVarAlloc] :
4070 llvm::zip_equal(privateVarsInfo.
privatizers, srcGEPs,
4073 if (!privDecl.readsFromMold())
4075 assert(llvmPrivateVarAlloc &&
4076 "reads from mold so shouldn't have been skipped");
4079 builder, moduleTranslation, privDecl.getInitMoldArg(), mold);
4081 builder, moduleTranslation, privDecl, moldArg, blockArg,
4082 llvmPrivateVarAlloc, builder.GetInsertBlock());
4083 if (!privateVarOrErr)
4084 return privateVarOrErr.takeError();
4093 [[maybe_unused]] llvm::Value *llvmPrivateVar = llvmPrivateVarAlloc;
4094 if ((privateVarOrErr.get() != llvmPrivateVarAlloc) &&
4095 !mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
4096 builder.CreateStore(privateVarOrErr.get(), llvmPrivateVarAlloc);
4098 llvmPrivateVar = builder.CreateLoad(privateVarOrErr.get()->getType(),
4099 llvmPrivateVarAlloc);
4101 assert(llvmPrivateVar->getType() ==
4102 moduleTranslation.
convertType(blockArg.getType()));
4110 moduleTranslation, srcGEPs, destGEPs,
4112 contextOp.getPrivateNeedsBarrier())))
4113 return llvm::make_error<PreviouslyReportedError>();
4115 return builder.saveIP();
4123 llvm::Value *ifCond =
nullptr;
4124 llvm::Value *grainsize =
nullptr;
4126 mlir::Value grainsizeVal = contextOp.getGrainsize();
4127 mlir::Value numTasksVal = contextOp.getNumTasks();
4128 if (
Value ifVar = contextOp.getIfExpr())
4131 grainsize = moduleTranslation.
lookupValue(grainsizeVal);
4133 }
else if (numTasksVal) {
4134 grainsize = moduleTranslation.
lookupValue(numTasksVal);
4138 llvm::OpenMPIRBuilder::TaskDupCallbackTy taskDupOrNull =
nullptr;
4139 if (taskStructMgr.getStructPtr())
4140 taskDupOrNull = taskDupCB;
4150 llvm::omp::Directive::OMPD_taskgroup);
4152 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4153 bool effectiveNoGroup = contextOp.getNogroup() || implicitTaskgroup;
4154 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
4156 ompLoc, allocaIP, deallocBlocks, bodyCB, loopInfo, lbVal, ubVal,
4157 stepVal, contextOp.getUntied(), ifCond, grainsize, effectiveNoGroup,
4158 sched, moduleTranslation.
lookupValue(contextOp.getFinal()),
4159 contextOp.getMergeable(),
4160 moduleTranslation.
lookupValue(contextOp.getPriority()),
4161 loopOp.getCollapseNumLoops(), taskDupOrNull,
4162 taskStructMgr.getStructPtr(),
4163 contextOp.getThreadset() == omp::ThreadsetPolicy::omp_pool);
4170 builder.restoreIP(*afterIP);
4174 if (implicitTaskgroup) {
4175 llvm::OpenMPIRBuilder::LocationDescription endLoc(builder);
4176 uint32_t srcLocSize;
4177 llvm::Constant *srcLocStr =
4178 ompBuilder.getOrCreateSrcLocStr(endLoc, srcLocSize);
4179 llvm::Value *ident = ompBuilder.getOrCreateIdent(srcLocStr, srcLocSize);
4182 ompBuilder.updateToLocation(endLoc);
4183 llvm::Value *outerGtid = ompBuilder.getOrCreateThreadID(ident);
4184 llvm::FunctionCallee endTgFn = ompBuilder.getOrCreateRuntimeFunction(
4186 llvm::omp::OMPRTL___kmpc_end_taskgroup);
4187 builder.CreateCall(endTgFn, {ident, outerGtid});
4198static llvm::Function *
4201 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
4202 llvm::LLVMContext &ctx = llvmModule->getContext();
4203 llvm::Type *voidTy = llvm::Type::getVoidTy(ctx);
4204 llvm::Type *ptrTy = llvm::PointerType::getUnqual(ctx);
4205 llvm::FunctionType *fty =
4206 llvm::FunctionType::get(voidTy, {ptrTy, ptrTy},
false);
4207 llvm::Function *fn =
4208 llvm::Function::Create(fty, llvm::GlobalValue::InternalLinkage,
4209 baseName +
".red.init", llvmModule);
4210 fn->setDoesNotRecurse();
4211 fn->getArg(0)->setName(
"priv");
4212 fn->getArg(1)->setName(
"orig");
4214 llvm::BasicBlock *entry = llvm::BasicBlock::Create(ctx,
"entry", fn);
4215 llvm::IRBuilder<>
b(entry);
4222 Value moldArg = decl.getInitializerMoldArg();
4223 llvm::Value *origVal = fn->getArg(1);
4224 if (!isa<LLVM::LLVMPointerType>(moldArg.
getType()))
4226 fn->getArg(1),
"omp.orig");
4227 moduleTranslation.
mapValue(moldArg, origVal);
4230 "omp.taskred.init",
b, moduleTranslation,
4232 fn->eraseFromParent();
4235 assert(phis.size() == 1 &&
4236 "expected one value yielded from reduction initializer");
4237 b.CreateStore(phis[0], fn->getArg(0));
4240 moduleTranslation.
forgetMapping(decl.getInitializerRegion());
4248static llvm::Function *
4251 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
4252 llvm::LLVMContext &ctx = llvmModule->getContext();
4253 llvm::Type *voidTy = llvm::Type::getVoidTy(ctx);
4254 llvm::Type *ptrTy = llvm::PointerType::getUnqual(ctx);
4255 llvm::FunctionType *fty =
4256 llvm::FunctionType::get(voidTy, {ptrTy, ptrTy},
false);
4257 llvm::Function *fn =
4258 llvm::Function::Create(fty, llvm::GlobalValue::InternalLinkage,
4259 baseName +
".red.comb", llvmModule);
4260 fn->setDoesNotRecurse();
4261 fn->getArg(0)->setName(
"lhs");
4262 fn->getArg(1)->setName(
"rhs");
4264 llvm::BasicBlock *entry = llvm::BasicBlock::Create(ctx,
"entry", fn);
4265 llvm::IRBuilder<>
b(entry);
4267 llvm::Type *elemTy = moduleTranslation.
convertType(decl.getType());
4268 Block &combBlock = decl.getReductionRegion().
front();
4270 "expected two arguments in declare_reduction combiner");
4271 llvm::Value *lhsVal =
b.CreateLoad(elemTy, fn->getArg(0),
"omp.lhs");
4272 llvm::Value *rhsVal =
b.CreateLoad(elemTy, fn->getArg(1),
"omp.rhs");
4278 "omp.taskred.comb",
b, moduleTranslation,
4280 fn->eraseFromParent();
4283 assert(phis.size() == 1 &&
4284 "expected one value yielded from reduction combiner");
4285 b.CreateStore(phis[0], fn->getArg(0));
4311 llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder::InsertPointTy allocaIP,
4313 bool isWorksharing) {
4314 assert(redDecls.size() == origPtrs.size() &&
4315 "expected one orig pointer per reduction decl");
4317 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
4318 llvm::LLVMContext &ctx = llvmModule->getContext();
4319 const llvm::DataLayout &dl = llvmModule->getDataLayout();
4321 llvm::Type *ptrTy = llvm::PointerType::getUnqual(ctx);
4322 llvm::Type *i32Ty = llvm::Type::getInt32Ty(ctx);
4323 llvm::Type *sizeTy =
4324 llvm::Type::getIntNTy(ctx, dl.getPointerSizeInBits(0));
4328 llvm::StructType *redInputTy =
4329 llvm::StructType::getTypeByName(ctx,
"kmp_taskred_input_t");
4331 redInputTy = llvm::StructType::create(
4332 ctx, {ptrTy, ptrTy, sizeTy, ptrTy, ptrTy, ptrTy, i32Ty},
4333 "kmp_taskred_input_t");
4335 unsigned n = redDecls.size();
4336 llvm::ArrayType *arrTy = llvm::ArrayType::get(redInputTy, n);
4339 llvm::AllocaInst *arrAlloca;
4341 llvm::IRBuilderBase::InsertPointGuard guard(builder);
4342 builder.restoreIP(allocaIP);
4344 builder.CreateAlloca(arrTy,
nullptr,
".taskred.input");
4348 llvm::Value *zero = builder.getInt32(0);
4349 for (
unsigned i = 0; i < n; ++i) {
4350 omp::DeclareReductionOp decl = redDecls[i];
4351 llvm::Value *orig = origPtrs[i];
4352 if (
auto *origPtrTy = llvm::dyn_cast<llvm::PointerType>(orig->getType());
4353 origPtrTy && origPtrTy->getAddressSpace() != 0)
4354 orig = builder.CreateAddrSpaceCast(orig, ptrTy);
4355 llvm::Type *elemTy = moduleTranslation.
convertType(decl.getType());
4356 uint64_t size = dl.getTypeAllocSize(elemTy).getFixedValue();
4358 std::string baseName =
4359 (llvm::Twine(helperNamePrefix) + decl.getSymName()).str();
4360 llvm::Function *initFn =
4362 llvm::Function *combFn =
4364 if (!initFn || !combFn)
4366 llvm::Value *elemPtr = builder.CreateInBoundsGEP(
4367 arrTy, arrAlloca, {zero, builder.getInt32(i)},
".taskred.elem");
4368 auto storeField = [&](
unsigned fieldIdx, llvm::Value *val) {
4369 llvm::Value *fieldPtr =
4370 builder.CreateStructGEP(redInputTy, elemPtr, fieldIdx);
4371 builder.CreateStore(val, fieldPtr);
4373 storeField(0, orig);
4374 storeField(1, orig);
4375 storeField(2, llvm::ConstantInt::get(sizeTy, size));
4376 storeField(3, initFn);
4377 storeField(4, llvm::ConstantPointerNull::get(ptrTy));
4378 storeField(5, combFn);
4379 storeField(6, llvm::ConstantInt::get(i32Ty, 0));
4383 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4384 uint32_t srcLocSize;
4385 llvm::Constant *srcLocStr =
4386 ompBuilder->getOrCreateSrcLocStr(ompLoc, srcLocSize);
4387 llvm::Value *ident = ompBuilder->getOrCreateIdent(srcLocStr, srcLocSize);
4388 ompBuilder->updateToLocation(ompLoc);
4389 llvm::Value *gtid = ompBuilder->getOrCreateThreadID(ident);
4393 llvm::FunctionCallee modInit = ompBuilder->getOrCreateRuntimeFunction(
4394 *llvmModule, llvm::omp::OMPRTL___kmpc_taskred_modifier_init);
4395 return builder.CreateCall(modInit,
4397 builder.getInt32(isWorksharing ? 1 : 0),
4398 builder.getInt32(n), arrAlloca},
4402 llvm::FunctionCallee taskredInit = ompBuilder->getOrCreateRuntimeFunction(
4403 *llvmModule, llvm::omp::OMPRTL___kmpc_taskred_init);
4404 return builder.CreateCall(taskredInit, {gtid, builder.getInt32(n), arrAlloca},
4415 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
4416 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4417 uint32_t srcLocSize;
4418 llvm::Constant *srcLocStr =
4419 ompBuilder->getOrCreateSrcLocStr(ompLoc, srcLocSize);
4420 llvm::Value *ident = ompBuilder->getOrCreateIdent(srcLocStr, srcLocSize);
4421 ompBuilder->updateToLocation(ompLoc);
4422 llvm::Value *gtid = ompBuilder->getOrCreateThreadID(ident);
4423 llvm::FunctionCallee fini = ompBuilder->getOrCreateRuntimeFunction(
4424 *llvmModule, llvm::omp::OMPRTL___kmpc_task_reduction_modifier_fini);
4425 builder.CreateCall(fini,
4426 {ident, gtid, builder.getInt32(isWorksharing ? 1 : 0)});
4433 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4442 if (
auto syms = tgOp.getTaskReductionSyms()) {
4443 redDecls.reserve(syms->size());
4444 for (
auto sym : syms->getAsRange<SymbolRefAttr>()) {
4448 return tgOp.emitError()
4449 <<
"failed to resolve task_reduction declare_reduction symbol "
4450 << sym.getRootReference() <<
" in omp.taskgroup";
4451 if (decl.getInitializerRegion().front().getNumArguments() != 1)
4452 return tgOp.emitError(
"not yet implemented: task_reduction with "
4453 "two-argument initializer in omp.taskgroup");
4454 if (!decl.getCleanupRegion().empty())
4455 return tgOp.emitError(
"not yet implemented: task_reduction with "
4456 "cleanup region in omp.taskgroup");
4457 if (decl.getReductionRegion().empty())
4458 return tgOp.emitError(
"task_reduction declare_reduction is missing a "
4460 redDecls.push_back(decl);
4465 [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
4467 builder.restoreIP(codegenIP);
4469 if (!redDecls.empty()) {
4471 origPtrs.reserve(redDecls.size());
4472 for (
Value v : tgOp.getTaskReductionVars())
4473 origPtrs.push_back(moduleTranslation.
lookupValue(v));
4475 builder, allocaIP, moduleTranslation))
4476 return llvm::createStringError(
4477 llvm::inconvertibleErrorCode(),
4478 "failed to emit task_reduction initialization for omp.taskgroup");
4486 for (
auto [i, blockArg] :
4487 llvm::enumerate(tgOp.getRegion().getArguments())) {
4489 moduleTranslation.
lookupValue(tgOp.getTaskReductionVars()[i]);
4490 moduleTranslation.
mapValue(blockArg, orig);
4494 builder, moduleTranslation)
4499 InsertPointTy allocaIP =
4501 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4502 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
4504 ompLoc, allocaIP, deallocBlocks, bodyCB);
4509 builder.restoreIP(*afterIP);
4516 if (!initOp.getDependVars().empty() || initOp.getDependKinds() ||
4517 !initOp.getDependIterated().empty() || initOp.getDependIteratedKinds())
4518 return initOp.emitError()
4519 <<
"not yet implemented: Unhandled clause depend in "
4520 << omp::InteropInitOp::getOperationName() <<
" operation";
4523 llvm::Value *interopVar =
4524 moduleTranslation.
lookupValue(initOp.getInteropVar());
4525 llvm::Value *device = initOp.getDevice()
4526 ? moduleTranslation.
lookupValue(initOp.getDevice())
4530 llvm::Value *numDeps = llvm::ConstantInt::get(builder.getInt32Ty(), 0);
4531 llvm::Value *depArray = llvm::ConstantPointerNull::get(builder.getPtrTy());
4532 bool hasNowait = initOp.getNowait();
4539 bool hasTarget =
false, hasTargetSync =
false;
4541 switch (cast<omp::InteropTypeAttr>(typeAttr).getValue()) {
4542 case omp::InteropType::target:
4545 case omp::InteropType::targetsync:
4546 hasTargetSync =
true;
4550 llvm::omp::OMPInteropType interopType =
4551 (!hasTarget && hasTargetSync) ? llvm::omp::OMPInteropType::TargetSync
4552 : llvm::omp::OMPInteropType::Target;
4553 ompBuilder->createOMPInteropInit(builder, interopVar, interopType, device,
4554 numDeps, depArray, hasNowait);
4560 llvm::IRBuilderBase &builder,
4562 if (!destroyOp.getDependVars().empty() || destroyOp.getDependKinds() ||
4563 !destroyOp.getDependIterated().empty() ||
4564 destroyOp.getDependIteratedKinds())
4565 return destroyOp.emitError()
4566 <<
"not yet implemented: Unhandled clause depend in "
4567 << omp::InteropDestroyOp::getOperationName() <<
" operation";
4570 llvm::Value *interopVar =
4571 moduleTranslation.
lookupValue(destroyOp.getInteropVar());
4572 llvm::Value *device =
4573 destroyOp.getDevice()
4574 ? moduleTranslation.
lookupValue(destroyOp.getDevice())
4577 llvm::Value *numDeps = llvm::ConstantInt::get(builder.getInt32Ty(), 0);
4578 llvm::Value *depArray = llvm::ConstantPointerNull::get(builder.getPtrTy());
4579 bool hasNowait = destroyOp.getNowait();
4581 ompBuilder->createOMPInteropDestroy(builder, interopVar, device, numDeps,
4582 depArray, hasNowait);
4589 if (!useOp.getDependVars().empty() || useOp.getDependKinds() ||
4590 !useOp.getDependIterated().empty() || useOp.getDependIteratedKinds())
4591 return useOp.emitError()
4592 <<
"not yet implemented: Unhandled clause depend in "
4593 << omp::InteropUseOp::getOperationName() <<
" operation";
4596 llvm::Value *interopVar =
4597 moduleTranslation.
lookupValue(useOp.getInteropVar());
4598 llvm::Value *device = useOp.getDevice()
4599 ? moduleTranslation.
lookupValue(useOp.getDevice())
4602 llvm::Value *numDeps = llvm::ConstantInt::get(builder.getInt32Ty(), 0);
4603 llvm::Value *depArray = llvm::ConstantPointerNull::get(builder.getPtrTy());
4604 bool hasNowait = useOp.getNowait();
4606 ompBuilder->createOMPInteropUse(builder, interopVar, device, numDeps,
4607 depArray, hasNowait);
4617 llvm::OpenMPIRBuilder::DependenciesInfo dds;
4619 twOp.getDependVars(), twOp.getDependKinds(), twOp.getDependIterated(),
4620 twOp.getDependIteratedKinds(), builder, moduleTranslation, dds))) {
4626 builder.CreateFree(dds.DepArray);
4637 auto wsloopOp = cast<omp::WsloopOp>(opInst);
4641 auto loopOp = cast<omp::LoopNestOp>(wsloopOp.getWrappedLoop());
4643 assert(isByRef.size() == wsloopOp.getNumReductionVars());
4647 wsloopOp.getScheduleKind().value_or(omp::ClauseScheduleKind::Static);
4650 llvm::Value *step = moduleTranslation.
lookupValue(loopOp.getLoopSteps()[0]);
4651 llvm::Type *ivType = step->getType();
4652 llvm::Value *chunk =
nullptr;
4653 if (wsloopOp.getScheduleChunk()) {
4654 llvm::Value *chunkVar =
4655 moduleTranslation.
lookupValue(wsloopOp.getScheduleChunk());
4656 chunk = builder.CreateSExtOrTrunc(chunkVar, ivType);
4659 omp::DistributeOp distributeOp =
nullptr;
4660 llvm::Value *distScheduleChunk =
nullptr;
4661 bool hasDistSchedule =
false;
4662 if (llvm::isa_and_present<omp::DistributeOp>(opInst.
getParentOp())) {
4663 distributeOp = cast<omp::DistributeOp>(opInst.
getParentOp());
4664 hasDistSchedule = distributeOp.getDistScheduleStatic();
4665 if (distributeOp.getDistScheduleChunkSize()) {
4666 llvm::Value *chunkVar = moduleTranslation.
lookupValue(
4667 distributeOp.getDistScheduleChunkSize());
4668 distScheduleChunk = builder.CreateSExtOrTrunc(chunkVar, ivType);
4677 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
4681 wsloopOp.getNumReductionVars());
4684 wsloopOp, builder, moduleTranslation, privateVarsInfo, allocaIP);
4691 cast<omp::BlockArgOpenMPOpInterface>(opInst).getReductionBlockArgs();
4696 moduleTranslation, allocaIP, reductionDecls,
4697 privateReductionVariables, reductionVariableMap,
4698 deferredStores, isByRef)))
4707 wsloopOp, builder, moduleTranslation, privateVarsInfo.
mlirVars,
4709 wsloopOp.getPrivateNeedsBarrier())))
4712 assert(afterAllocas.get()->getSinglePredecessor());
4713 if (failed(initReductionVars(wsloopOp, reductionArgs, builder,
4715 afterAllocas.get()->getSinglePredecessor(),
4716 reductionDecls, privateReductionVariables,
4717 reductionVariableMap, isByRef, deferredStores)))
4723 bool isTaskReductionMod =
4724 wsloopOp.getReductionMod() == omp::ReductionModifier::task &&
4725 wsloopOp.getNumReductionVars() > 0;
4726 if (isTaskReductionMod &&
4728 "__omp_taskred_mod_", builder, allocaIP,
4729 moduleTranslation,
true,
4731 return wsloopOp.emitError(
4732 "failed to emit task reduction modifier initialization");
4735 bool isOrdered = wsloopOp.getOrdered().has_value();
4736 std::optional<omp::ScheduleModifier> scheduleMod = wsloopOp.getScheduleMod();
4737 bool isSimd = wsloopOp.getScheduleSimd();
4738 bool loopNeedsBarrier = !wsloopOp.getNowait();
4743 llvm::omp::WorksharingLoopType workshareLoopType =
4744 llvm::isa_and_present<omp::DistributeOp>(opInst.
getParentOp())
4745 ? llvm::omp::WorksharingLoopType::DistributeForStaticLoop
4746 : llvm::omp::WorksharingLoopType::ForStaticLoop;
4750 llvm::omp::Directive::OMPD_for);
4752 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4755 LinearClauseProcessor linearClauseProcessor;
4757 if (!wsloopOp.getLinearVars().empty()) {
4758 auto linearVarTypes = wsloopOp.getLinearVarTypes().value();
4760 linearClauseProcessor.registerType(moduleTranslation, linearVarType);
4762 for (
auto [idx, linearVar] : llvm::enumerate(wsloopOp.getLinearVars()))
4763 linearClauseProcessor.createLinearVar(
4764 builder, moduleTranslation, moduleTranslation.
lookupValue(linearVar),
4766 for (
mlir::Value linearStep : wsloopOp.getLinearStepVars())
4767 linearClauseProcessor.initLinearStep(moduleTranslation, linearStep);
4771 wsloopOp.getRegion(),
"omp.wsloop.region", builder, moduleTranslation);
4779 if (!wsloopOp.getLinearVars().empty()) {
4780 linearClauseProcessor.initLinearVar(builder, moduleTranslation,
4781 loopInfo->getPreheader());
4782 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterBarrierIP =
4784 builder, llvm::omp::OMPD_barrier);
4787 builder.restoreIP(*afterBarrierIP);
4788 linearClauseProcessor.updateLinearVar(builder, loopInfo->getBody(),
4789 loopInfo->getIndVar());
4790 linearClauseProcessor.splitLinearFiniBB(builder, loopInfo->getExit());
4793 builder.SetInsertPoint(*regionBlock, (*regionBlock)->begin());
4796 bool noLoopMode =
false;
4797 omp::TargetOp targetOp = wsloopOp->getParentOfType<mlir::omp::TargetOp>();
4799 targetOp.getKernelType() == omp::TargetExecMode::spmd_no_loop) {
4801 cast<omp::ComposableOpInterface>(*targetOp).findCapturedOp();
4805 if (loopOp == targetCapturedOp)
4809 for (
size_t index = 0;
index < wsloopOp.getLinearVars().size();
index++)
4810 linearClauseProcessor.rewriteInPlace(builder, loopInfo->getBody(),
4811 loopInfo->getLatch(),
index);
4813 llvm::OpenMPIRBuilder::InsertPointOrErrorTy wsloopIP =
4814 ompBuilder->applyWorkshareLoop(
4815 ompLoc.DL, loopInfo, allocaIP, loopNeedsBarrier,
4816 convertToScheduleKind(schedule), chunk, isSimd,
4817 scheduleMod == omp::ScheduleModifier::monotonic,
4818 scheduleMod == omp::ScheduleModifier::nonmonotonic, isOrdered,
4819 workshareLoopType, noLoopMode, hasDistSchedule, distScheduleChunk);
4825 if (!wsloopOp.getLinearVars().empty()) {
4826 llvm::OpenMPIRBuilder::InsertPointTy oldIP = builder.saveIP();
4827 assert(loopInfo->getLastIter() &&
4828 "`lastiter` in CanonicalLoopInfo is nullptr");
4829 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterBarrierIP =
4830 linearClauseProcessor.finalizeLinearVar(builder, moduleTranslation,
4831 loopInfo->getLastIter());
4835 builder.restoreIP(oldIP);
4842 if (isTaskReductionMod)
4848 wsloopOp, builder, moduleTranslation, allocaIP, reductionDecls,
4849 privateReductionVariables, isByRef, wsloopOp.getNowait(),
4854 wsloopOp.getLoc(), privateVarsInfo);
4861 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4863 assert(isByRef.size() == opInst.getNumReductionVars());
4871 for (
Value allocatorVar : opInst.getAllocatorVars()) {
4875 llvm::Value *allocator = moduleTranslation.
lookupValue(allocatorVar);
4877 return opInst.emitError(
"failed to translate OpenMP allocator operand");
4878 if (allocator->getType()->isIntegerTy())
4879 allocator = builder.CreateIntToPtr(allocator, builder.getPtrTy());
4880 else if (allocator->getType()->isPointerTy())
4881 allocator = builder.CreatePointerBitCastOrAddrSpaceCast(
4882 allocator, builder.getPtrTy());
4884 return opInst.emitError(
4885 "OpenMP allocator operand must have integer or pointer type");
4894 opInst.getNumReductionVars());
4900 bool isTaskReductionMod =
4901 opInst.getReductionMod() == omp::ReductionModifier::task &&
4902 opInst.getNumReductionVars() > 0;
4905 [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
4908 opInst, builder, moduleTranslation, privateVarsInfo, allocaIP);
4910 return llvm::make_error<PreviouslyReportedError>();
4916 cast<omp::BlockArgOpenMPOpInterface>(*opInst).getReductionBlockArgs();
4919 InsertPointTy(allocaIP.getBlock(),
4920 allocaIP.getBlock()->getTerminator()->getIterator());
4923 opInst, reductionArgs, builder, moduleTranslation, allocaIP,
4924 reductionDecls, privateReductionVariables, reductionVariableMap,
4925 deferredStores, isByRef)))
4926 return llvm::make_error<PreviouslyReportedError>();
4928 assert(afterAllocas.get()->getSinglePredecessor());
4929 builder.restoreIP(codeGenIP);
4935 return llvm::make_error<PreviouslyReportedError>();
4938 opInst, builder, moduleTranslation, privateVarsInfo.
mlirVars,
4940 opInst.getPrivateNeedsBarrier())))
4941 return llvm::make_error<PreviouslyReportedError>();
4944 initReductionVars(opInst, reductionArgs, builder, moduleTranslation,
4945 afterAllocas.get()->getSinglePredecessor(),
4946 reductionDecls, privateReductionVariables,
4947 reductionVariableMap, isByRef, deferredStores)))
4948 return llvm::make_error<PreviouslyReportedError>();
4953 if (isTaskReductionMod &&
4955 "__omp_taskred_mod_", builder, allocaIP,
4956 moduleTranslation,
true,
4958 return llvm::createStringError(
4959 "failed to emit task reduction modifier initialization");
4964 moduleTranslation, allocaIP, deallocBlocks);
4968 opInst.getRegion(),
"omp.par.region", builder, moduleTranslation);
4970 return regionBlock.takeError();
4973 if (opInst.getNumReductionVars() > 0) {
4978 owningReductionGenRefDataPtrGens;
4980 collectReductionInfo(opInst, builder, moduleTranslation, reductionDecls,
4982 owningReductionGenRefDataPtrGens,
4983 privateReductionVariables, reductionInfos, isByRef);
4986 builder.SetInsertPoint((*regionBlock)->getTerminator());
4990 if (isTaskReductionMod)
4995 llvm::UnreachableInst *tempTerminator = builder.CreateUnreachable();
4996 builder.SetInsertPoint(tempTerminator);
4998 llvm::OpenMPIRBuilder::InsertPointOrErrorTy contInsertPoint =
4999 ompBuilder->createReductions(builder, allocaIP, reductionInfos,
5003 if (!contInsertPoint)
5004 return contInsertPoint.takeError();
5006 if (!contInsertPoint->getBlock())
5007 return llvm::make_error<PreviouslyReportedError>();
5009 tempTerminator->eraseFromParent();
5010 builder.restoreIP(*contInsertPoint);
5013 return llvm::Error::success();
5016 auto privCB = [](InsertPointTy allocaIP, InsertPointTy codeGenIP,
5017 llvm::Value &, llvm::Value &val, llvm::Value *&replVal) {
5026 auto finiCB = [&](InsertPointTy codeGenIP) -> llvm::Error {
5027 InsertPointTy oldIP = builder.saveIP();
5028 builder.restoreIP(codeGenIP);
5033 llvm::transform(reductionDecls, std::back_inserter(reductionCleanupRegions),
5034 [](omp::DeclareReductionOp reductionDecl) {
5035 return &reductionDecl.getCleanupRegion();
5038 reductionCleanupRegions, privateReductionVariables,
5039 moduleTranslation, builder,
"omp.reduction.cleanup")))
5040 return llvm::createStringError(
5041 "failed to inline `cleanup` region of `omp.declare_reduction`");
5044 opInst.getLoc(), privateVarsInfo)))
5045 return llvm::make_error<PreviouslyReportedError>();
5049 if (isCancellable) {
5050 auto IPOrErr = ompBuilder->createBarrier(
5051 llvm::OpenMPIRBuilder::LocationDescription(builder),
5052 llvm::omp::Directive::OMPD_unknown,
5056 return IPOrErr.takeError();
5059 builder.restoreIP(oldIP);
5060 return llvm::Error::success();
5063 llvm::Value *ifCond =
nullptr;
5064 if (
auto ifVar = opInst.getIfExpr())
5066 llvm::Value *numThreads =
nullptr;
5067 if (!opInst.getNumThreadsVars().empty())
5068 numThreads = moduleTranslation.
lookupValue(opInst.getNumThreads(0));
5069 auto pbKind = llvm::omp::OMP_PROC_BIND_default;
5070 if (
auto bind = opInst.getProcBindKind())
5074 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
5076 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5078 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
5079 ompBuilder->createParallel(ompLoc, allocaIP, deallocBlocks, bodyGenCB,
5080 privCB, finiCB, ifCond, numThreads, pbKind,
5086 builder.restoreIP(*afterIP);
5091static llvm::omp::OrderKind
5094 return llvm::omp::OrderKind::OMP_ORDER_unknown;
5096 case omp::ClauseOrderKind::Concurrent:
5097 return llvm::omp::OrderKind::OMP_ORDER_concurrent;
5099 llvm_unreachable(
"Unknown ClauseOrderKind kind");
5107 auto simdOp = cast<omp::SimdOp>(opInst);
5115 cast<omp::BlockArgOpenMPOpInterface>(opInst).getReductionBlockArgs();
5118 simdOp.getNumReductionVars());
5123 assert(isByRef.size() == simdOp.getNumReductionVars());
5125 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
5129 simdOp, builder, moduleTranslation, privateVarsInfo, allocaIP);
5134 LinearClauseProcessor linearClauseProcessor;
5135 if (linearClauseProcessor.initLinearIV(simdOp).failed())
5138 if (!simdOp.getLinearVars().empty()) {
5139 auto linearVarTypes = simdOp.getLinearVarTypes().value();
5141 linearClauseProcessor.registerType(moduleTranslation, linearVarType);
5142 for (
auto [idx, linearVar] : llvm::enumerate(simdOp.getLinearVars())) {
5143 bool isImplicit =
false;
5144 for (
auto [mlirPrivVar, llvmPrivateVar] : llvm::zip_equal(
5148 if (linearVar == mlirPrivVar) {
5150 linearClauseProcessor.createLinearVar(builder, moduleTranslation,
5151 llvmPrivateVar, idx);
5157 linearClauseProcessor.createLinearVar(
5158 builder, moduleTranslation,
5161 for (
mlir::Value linearStep : simdOp.getLinearStepVars())
5162 linearClauseProcessor.initLinearStep(moduleTranslation, linearStep);
5166 moduleTranslation, allocaIP, reductionDecls,
5167 privateReductionVariables, reductionVariableMap,
5168 deferredStores, isByRef)))
5179 assert(afterAllocas.get()->getSinglePredecessor());
5180 if (failed(initReductionVars(simdOp, reductionArgs, builder,
5182 afterAllocas.get()->getSinglePredecessor(),
5183 reductionDecls, privateReductionVariables,
5184 reductionVariableMap, isByRef, deferredStores)))
5187 llvm::ConstantInt *simdlen =
nullptr;
5188 if (std::optional<uint64_t> simdlenVar = simdOp.getSimdlen())
5189 simdlen = builder.getInt64(simdlenVar.value());
5191 llvm::ConstantInt *safelen =
nullptr;
5192 if (std::optional<uint64_t> safelenVar = simdOp.getSafelen())
5193 safelen = builder.getInt64(safelenVar.value());
5195 llvm::MapVector<llvm::Value *, llvm::Value *> alignedVars;
5198 llvm::BasicBlock *sourceBlock = builder.GetInsertBlock();
5199 std::optional<ArrayAttr> alignmentValues = simdOp.getAlignments();
5201 for (
size_t i = 0; i < operands.size(); ++i) {
5202 llvm::Value *alignment =
nullptr;
5203 llvm::Value *llvmVal = moduleTranslation.
lookupValue(operands[i]);
5204 llvm::Type *ty = llvmVal->getType();
5206 auto intAttr = cast<IntegerAttr>((*alignmentValues)[i]);
5207 alignment = builder.getInt64(intAttr.getInt());
5208 assert(ty->isPointerTy() &&
"Invalid type for aligned variable");
5209 assert(alignment &&
"Invalid alignment value");
5213 if (!intAttr.getValue().isPowerOf2())
5216 auto curInsert = builder.saveIP();
5217 builder.SetInsertPoint(sourceBlock);
5218 llvmVal = builder.CreateLoad(ty, llvmVal);
5219 builder.restoreIP(curInsert);
5220 alignedVars[llvmVal] = alignment;
5224 simdOp.getRegion(),
"omp.simd.region", builder, moduleTranslation);
5231 if (simdOp.getLinearVars().size()) {
5232 linearClauseProcessor.initLinearVar(builder, moduleTranslation,
5233 loopInfo->getPreheader());
5235 linearClauseProcessor.updateLinearVar(builder, loopInfo->getBody(),
5236 loopInfo->getIndVar());
5238 builder.SetInsertPoint(*regionBlock, (*regionBlock)->begin());
5240 for (
size_t index = 0;
index < simdOp.getLinearVars().size();
index++)
5241 linearClauseProcessor.rewriteInPlace(builder, loopInfo->getBody(),
5242 loopInfo->getLatch(),
index);
5244 ompBuilder->applySimd(loopInfo, alignedVars,
5246 ? moduleTranslation.
lookupValue(simdOp.getIfExpr())
5248 order, simdlen, safelen);
5250 linearClauseProcessor.updateLinearIV(builder, moduleTranslation);
5251 linearClauseProcessor.emitStoresForLinearVar(builder);
5257 for (
auto [i, tuple] : llvm::enumerate(
5258 llvm::zip(reductionDecls, isByRef, simdOp.getReductionVars(),
5259 privateReductionVariables))) {
5260 auto [decl, byRef, reductionVar, privateReductionVar] = tuple;
5262 OwningReductionGen gen =
makeReductionGen(decl, builder, moduleTranslation);
5263 llvm::Value *originalVariable = moduleTranslation.
lookupValue(reductionVar);
5264 llvm::Type *reductionType = moduleTranslation.
convertType(decl.getType());
5268 llvm::Value *redValue = originalVariable;
5271 builder.CreateLoad(reductionType, redValue,
"red.value." + Twine(i));
5272 llvm::Value *privateRedValue = builder.CreateLoad(
5273 reductionType, privateReductionVar,
"red.private.value." + Twine(i));
5274 llvm::Value *reduced;
5276 auto res = gen(builder.saveIP(), redValue, privateRedValue, reduced);
5279 builder.restoreIP(res.get());
5283 builder.CreateStore(reduced, originalVariable);
5288 llvm::transform(reductionDecls, std::back_inserter(reductionRegions),
5289 [](omp::DeclareReductionOp reductionDecl) {
5290 return &reductionDecl.getCleanupRegion();
5293 moduleTranslation, builder,
5294 "omp.reduction.cleanup")))
5306 auto loopOp = cast<omp::LoopNestOp>(opInst);
5312 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5317 auto bodyGen = [&](llvm::OpenMPIRBuilder::InsertPointTy ip,
5318 llvm::Value *iv) -> llvm::Error {
5321 loopOp.getRegion().front().getArgument(loopInfos.size()), iv);
5326 bodyInsertPoints.push_back(ip);
5328 if (loopInfos.size() != loopOp.getNumLoops() - 1)
5329 return llvm::Error::success();
5332 builder.restoreIP(ip);
5334 loopOp.getRegion(),
"omp.loop_nest.region", builder, moduleTranslation);
5336 return regionBlock.takeError();
5338 builder.SetInsertPoint(*regionBlock, (*regionBlock)->begin());
5339 return llvm::Error::success();
5347 for (
unsigned i = 0, e = loopOp.getNumLoops(); i < e; ++i) {
5348 llvm::Value *lowerBound =
5349 moduleTranslation.
lookupValue(loopOp.getLoopLowerBounds()[i]);
5350 llvm::Value *upperBound =
5351 moduleTranslation.
lookupValue(loopOp.getLoopUpperBounds()[i]);
5352 llvm::Value *step = moduleTranslation.
lookupValue(loopOp.getLoopSteps()[i]);
5357 llvm::OpenMPIRBuilder::LocationDescription loc = ompLoc;
5358 llvm::OpenMPIRBuilder::InsertPointTy computeIP = ompLoc.IP;
5360 loc = llvm::OpenMPIRBuilder::LocationDescription(bodyInsertPoints.back(),
5362 computeIP = loopInfos.front()->getPreheaderIP();
5366 ompBuilder->createCanonicalLoop(
5367 loc, bodyGen, lowerBound, upperBound, step,
5368 true, loopOp.getLoopInclusive(), computeIP);
5373 loopInfos.push_back(*loopResult);
5376 llvm::OpenMPIRBuilder::InsertPointTy afterIP =
5377 loopInfos.front()->getAfterIP();
5380 if (
const auto &tiles = loopOp.getTileSizes()) {
5381 llvm::Type *ivType = loopInfos.front()->getIndVarType();
5384 for (
auto tile : tiles.value()) {
5385 llvm::Value *tileVal = llvm::ConstantInt::get(ivType,
tile);
5386 tileSizes.push_back(tileVal);
5389 std::vector<llvm::CanonicalLoopInfo *> newLoops =
5390 ompBuilder->tileLoops(ompLoc.DL, loopInfos, tileSizes);
5394 llvm::BasicBlock *afterBB = newLoops.front()->getAfter();
5395 llvm::BasicBlock *afterAfterBB = afterBB->getSingleSuccessor();
5396 afterIP = {afterAfterBB, afterAfterBB->begin()};
5400 for (
const auto &newLoop : newLoops)
5401 loopInfos.push_back(newLoop);
5405 const auto &numCollapse = loopOp.getCollapseNumLoops();
5407 loopInfos.begin(), loopInfos.begin() + (numCollapse));
5409 auto newTopLoopInfo =
5410 ompBuilder->collapseLoops(ompLoc.DL, collapseLoopInfos, {});
5412 assert(newTopLoopInfo &&
"New top loop information is missing");
5413 moduleTranslation.
stackWalk<OpenMPLoopInfoStackFrame>(
5414 [&](OpenMPLoopInfoStackFrame &frame) {
5415 frame.loopInfo = newTopLoopInfo;
5423 builder.restoreIP(afterIP);
5433 llvm::OpenMPIRBuilder::LocationDescription loopLoc(builder);
5434 Value loopIV = op.getInductionVar();
5435 Value loopTC = op.getTripCount();
5437 llvm::Value *llvmTC = moduleTranslation.
lookupValue(loopTC);
5440 ompBuilder->createCanonicalLoop(
5442 [&](llvm::OpenMPIRBuilder::InsertPointTy ip, llvm::Value *llvmIV) {
5445 moduleTranslation.
mapValue(loopIV, llvmIV);
5447 builder.restoreIP(ip);
5452 return bodyGenStatus.takeError();
5454 llvmTC,
"omp.loop");
5456 return op.emitError(llvm::toString(llvmOrError.takeError()));
5458 llvm::CanonicalLoopInfo *llvmCLI = *llvmOrError;
5459 llvm::IRBuilderBase::InsertPoint afterIP = llvmCLI->getAfterIP();
5460 builder.restoreIP(afterIP);
5463 if (
Value cli = op.getCli())
5476 Value applyee = op.getApplyee();
5477 assert(applyee &&
"Loop to apply unrolling on required");
5479 llvm::CanonicalLoopInfo *consBuilderCLI =
5481 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
5482 ompBuilder->unrollLoopHeuristic(loc.DL, consBuilderCLI);
5495 Value applyee = op.getApplyee();
5496 assert(applyee &&
"Loop to apply unrolling on required");
5498 llvm::CanonicalLoopInfo *consBuilderCLI =
5500 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
5501 ompBuilder->unrollLoopFull(loc.DL, consBuilderCLI);
5514 Value applyee = op.getApplyee();
5515 assert(applyee &&
"Loop to apply unrolling on required");
5517 llvm::CanonicalLoopInfo *consBuilderCLI =
5519 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
5523 int32_t factor =
static_cast<int32_t
>(op.getUnrollFactor());
5524 ompBuilder->unrollLoopPartial(loc.DL, consBuilderCLI, factor,
5533static LogicalResult
applyTile(omp::TileOp op, llvm::IRBuilderBase &builder,
5536 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
5541 for (
Value size : op.getSizes()) {
5542 llvm::Value *translatedSize = moduleTranslation.
lookupValue(size);
5543 assert(translatedSize &&
5544 "sizes clause arguments must already be translated");
5545 translatedSizes.push_back(translatedSize);
5548 for (
Value applyee : op.getApplyees()) {
5549 llvm::CanonicalLoopInfo *consBuilderCLI =
5551 assert(applyee &&
"Canonical loop must already been translated");
5552 translatedLoops.push_back(consBuilderCLI);
5555 auto generatedLoops =
5556 ompBuilder->tileLoops(loc.DL, translatedLoops, translatedSizes);
5557 if (!op.getGeneratees().empty()) {
5558 for (
auto [mlirLoop,
genLoop] :
5559 zip_equal(op.getGeneratees(), generatedLoops))
5564 for (
Value applyee : op.getApplyees())
5572static LogicalResult
applyFuse(omp::FuseOp op, llvm::IRBuilderBase &builder,
5575 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
5579 for (
size_t i = 0; i < op.getApplyees().size(); i++) {
5580 Value applyee = op.getApplyees()[i];
5581 llvm::CanonicalLoopInfo *consBuilderCLI =
5583 assert(applyee &&
"Canonical loop must already been translated");
5584 if (op.getFirst().has_value() && i < op.getFirst().value() - 1)
5585 beforeFuse.push_back(consBuilderCLI);
5586 else if (op.getCount().has_value() &&
5587 i >= op.getFirst().value() + op.getCount().value() - 1)
5588 afterFuse.push_back(consBuilderCLI);
5590 toFuse.push_back(consBuilderCLI);
5593 (op.getGeneratees().empty() ||
5594 beforeFuse.size() + afterFuse.size() + 1 == op.getGeneratees().size()) &&
5595 "Wrong number of generatees");
5598 auto generatedLoop = ompBuilder->fuseLoops(loc.DL, toFuse);
5599 if (!op.getGeneratees().empty()) {
5601 for (; i < beforeFuse.size(); i++)
5602 moduleTranslation.
mapOmpLoop(op.getGeneratees()[i], beforeFuse[i]);
5603 moduleTranslation.
mapOmpLoop(op.getGeneratees()[i++], generatedLoop);
5604 for (; i < afterFuse.size(); i++)
5605 moduleTranslation.
mapOmpLoop(op.getGeneratees()[i], afterFuse[i]);
5609 for (
Value applyee : op.getApplyees())
5616static llvm::AtomicOrdering
5619 return llvm::AtomicOrdering::Monotonic;
5622 case omp::ClauseMemoryOrderKind::Seq_cst:
5623 return llvm::AtomicOrdering::SequentiallyConsistent;
5624 case omp::ClauseMemoryOrderKind::Acq_rel:
5625 return llvm::AtomicOrdering::AcquireRelease;
5626 case omp::ClauseMemoryOrderKind::Acquire:
5627 return llvm::AtomicOrdering::Acquire;
5628 case omp::ClauseMemoryOrderKind::Release:
5629 return llvm::AtomicOrdering::Release;
5630 case omp::ClauseMemoryOrderKind::Relaxed:
5631 return llvm::AtomicOrdering::Monotonic;
5633 llvm_unreachable(
"Unknown ClauseMemoryOrderKind kind");
5640static llvm::AtomicOrdering
5642 llvm::AtomicOrdering atomicOrdering) {
5643 if (atomicCompareOp.getFailMemoryOrder())
5645 return llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(atomicOrdering);
5652 auto readOp = cast<omp::AtomicReadOp>(opInst);
5657 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
5660 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5663 llvm::Value *x = moduleTranslation.
lookupValue(readOp.getX());
5664 llvm::Value *v = moduleTranslation.
lookupValue(readOp.getV());
5666 llvm::Type *elementType =
5667 moduleTranslation.
convertType(readOp.getElementType());
5669 llvm::OpenMPIRBuilder::AtomicOpValue V = {v, elementType,
false,
false};
5670 llvm::OpenMPIRBuilder::AtomicOpValue X = {x, elementType,
false,
false};
5671 builder.restoreIP(ompBuilder->createAtomicRead(ompLoc, X, V, AO, allocaIP));
5679 auto writeOp = cast<omp::AtomicWriteOp>(opInst);
5684 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
5687 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5689 llvm::Value *expr = moduleTranslation.
lookupValue(writeOp.getExpr());
5690 llvm::Value *dest = moduleTranslation.
lookupValue(writeOp.getX());
5691 llvm::Type *ty = moduleTranslation.
convertType(writeOp.getExpr().getType());
5692 llvm::OpenMPIRBuilder::AtomicOpValue x = {dest, ty,
false,
5695 ompBuilder->createAtomicWrite(ompLoc, x, expr, ao, allocaIP));
5703 .Case([&](LLVM::AddOp) {
return llvm::AtomicRMWInst::BinOp::Add; })
5704 .Case([&](LLVM::SubOp) {
return llvm::AtomicRMWInst::BinOp::Sub; })
5705 .Case([&](LLVM::AndOp) {
return llvm::AtomicRMWInst::BinOp::And; })
5706 .Case([&](LLVM::OrOp) {
return llvm::AtomicRMWInst::BinOp::Or; })
5707 .Case([&](LLVM::XOrOp) {
return llvm::AtomicRMWInst::BinOp::Xor; })
5708 .Case([&](LLVM::UMaxOp) {
return llvm::AtomicRMWInst::BinOp::UMax; })
5709 .Case([&](LLVM::UMinOp) {
return llvm::AtomicRMWInst::BinOp::UMin; })
5710 .Case([&](LLVM::FAddOp) {
return llvm::AtomicRMWInst::BinOp::FAdd; })
5711 .Case([&](LLVM::FSubOp) {
return llvm::AtomicRMWInst::BinOp::FSub; })
5712 .Default(llvm::AtomicRMWInst::BinOp::BAD_BINOP);
5716 bool &isIgnoreDenormalMode,
5717 bool &isFineGrainedMemory,
5718 bool &isRemoteMemory) {
5719 isIgnoreDenormalMode =
false;
5720 isFineGrainedMemory =
false;
5721 isRemoteMemory =
false;
5722 if (atomicUpdateOp && atomicUpdateOp.getAtomicControlAttr()) {
5723 mlir::omp::AtomicControlAttr atomicControlAttr =
5724 atomicUpdateOp.getAtomicControlAttr();
5725 isIgnoreDenormalMode = atomicControlAttr.getIgnoreDenormalMode();
5726 isFineGrainedMemory = atomicControlAttr.getFineGrainedMemory();
5727 isRemoteMemory = atomicControlAttr.getRemoteMemory();
5734 llvm::IRBuilderBase &builder,
5741 auto &innerOpList = opInst.getRegion().front().getOperations();
5742 bool isXBinopExpr{
false};
5743 llvm::AtomicRMWInst::BinOp binop;
5745 llvm::Value *llvmExpr =
nullptr;
5746 llvm::Value *llvmX =
nullptr;
5747 llvm::Type *llvmXElementType =
nullptr;
5748 if (innerOpList.size() == 2) {
5754 opInst.getRegion().getArgument(0))) {
5755 return opInst.emitError(
"no atomic update operation with region argument"
5756 " as operand found inside atomic.update region");
5759 isXBinopExpr = innerOp.
getOperand(0) == opInst.getRegion().getArgument(0);
5761 llvmExpr = moduleTranslation.
lookupValue(mlirExpr);
5765 binop = llvm::AtomicRMWInst::BinOp::BAD_BINOP;
5767 llvmX = moduleTranslation.
lookupValue(opInst.getX());
5769 opInst.getRegion().getArgument(0).getType());
5770 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {llvmX, llvmXElementType,
5774 llvm::AtomicOrdering atomicOrdering =
5779 [&opInst, &moduleTranslation](
5780 llvm::Value *atomicx,
5783 moduleTranslation.
mapValue(*opInst.getRegion().args_begin(), atomicx);
5784 moduleTranslation.
mapBlock(&bb, builder.GetInsertBlock());
5785 if (failed(moduleTranslation.
convertBlock(bb,
true, builder)))
5786 return llvm::make_error<PreviouslyReportedError>();
5788 omp::YieldOp yieldop = dyn_cast<omp::YieldOp>(bb.
getTerminator());
5789 assert(yieldop && yieldop.getResults().size() == 1 &&
5790 "terminator must be omp.yield op and it must have exactly one "
5792 return moduleTranslation.
lookupValue(yieldop.getResults()[0]);
5795 bool isIgnoreDenormalMode;
5796 bool isFineGrainedMemory;
5797 bool isRemoteMemory;
5802 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5803 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
5804 ompBuilder->createAtomicUpdate(ompLoc, allocaIP, llvmAtomicX, llvmExpr,
5805 atomicOrdering, binop, updateFn,
5806 isXBinopExpr, isIgnoreDenormalMode,
5807 isFineGrainedMemory, isRemoteMemory);
5812 builder.restoreIP(*afterIP);
5818static std::optional<llvm::omp::OMPAtomicCompareOp>
5820 switch (predicate) {
5821 case LLVM::ICmpPredicate::eq:
5822 return llvm::omp::OMPAtomicCompareOp::EQ;
5823 case LLVM::ICmpPredicate::slt:
5824 case LLVM::ICmpPredicate::ult:
5825 return llvm::omp::OMPAtomicCompareOp::MIN;
5826 case LLVM::ICmpPredicate::sgt:
5827 case LLVM::ICmpPredicate::ugt:
5828 return llvm::omp::OMPAtomicCompareOp::MAX;
5830 return std::nullopt;
5836static std::optional<llvm::omp::OMPAtomicCompareOp>
5838 switch (predicate) {
5839 case LLVM::FCmpPredicate::oeq:
5840 case LLVM::FCmpPredicate::ueq:
5841 return llvm::omp::OMPAtomicCompareOp::EQ;
5842 case LLVM::FCmpPredicate::olt:
5843 case LLVM::FCmpPredicate::ult:
5844 return llvm::omp::OMPAtomicCompareOp::MIN;
5845 case LLVM::FCmpPredicate::ogt:
5846 case LLVM::FCmpPredicate::ugt:
5847 return llvm::omp::OMPAtomicCompareOp::MAX;
5849 return std::nullopt;
5876 if (
auto extractOp = v.getDefiningOp<LLVM::ExtractValueOp>())
5877 return extractOp.getContainer();
5881 if (!isa<LLVM::AndOp, LLVM::OrOp>(op))
5885 if (!lhsFcmp || !rhsFcmp)
5887 mlir::Value lhsAgg0 = traceToAggregate(lhsFcmp.getOperand(0));
5888 mlir::Value lhsAgg1 = traceToAggregate(lhsFcmp.getOperand(1));
5889 bool lhsXIsOp0 = (lhsAgg0 == block.
getArgument(0));
5890 bool lhsXIsOp1 = (lhsAgg1 == block.
getArgument(0));
5891 if (!lhsXIsOp0 && !lhsXIsOp1)
5893 mlir::Value eAggregate = lhsXIsOp0 ? lhsAgg1 : lhsAgg0;
5897 result.isNE = isa<LLVM::OrOp>(op);
5898 result.eAggregate = eAggregate;
5899 result.isXBinopExpr = lhsXIsOp0;
5911 llvm::Value *llvmX, llvm::Type *complexTy,
5912 llvm::Value *eVal, llvm::Value *dVal,
5913 llvm::AtomicOrdering atomicOrdering,
5914 llvm::AtomicOrdering failOrdering,
5915 bool isWeak, llvm::Value *&oldComplex,
5916 llvm::Value *&cmpOk) {
5917 const llvm::DataLayout &DL =
5918 builder.GetInsertBlock()->getModule()->getDataLayout();
5919 unsigned totalBits = DL.getTypeStoreSizeInBits(complexTy).getFixedValue();
5920 llvm::IntegerType *intTy =
5921 llvm::IntegerType::get(builder.getContext(), totalBits);
5922 llvm::Align complexAlign = DL.getABITypeAlign(complexTy);
5923 llvm::Align intAlign = DL.getABITypeAlign(intTy);
5924 llvm::Align maxAlign = std::max(complexAlign, intAlign);
5927 llvm::AllocaInst *dAlloca =
5928 builder.CreateAlloca(complexTy,
nullptr,
"cmplx.d");
5929 dAlloca->setAlignment(maxAlign);
5930 builder.CreateAlignedStore(dVal, dAlloca, maxAlign);
5932 builder.CreateAlignedLoad(intTy, dAlloca, maxAlign,
"cmplx.d.int");
5937 llvm::LoadInst *xCurr =
5938 builder.CreateAlignedLoad(intTy, llvmX, maxAlign,
"cmplx.x.load");
5939 xCurr->setAtomic(failOrdering);
5940 llvm::AllocaInst *xAlloca =
5941 builder.CreateAlloca(complexTy,
nullptr,
"cmplx.x");
5942 xAlloca->setAlignment(maxAlign);
5943 builder.CreateAlignedStore(xCurr, xAlloca, maxAlign);
5944 llvm::Value *xStruct =
5945 builder.CreateAlignedLoad(complexTy, xAlloca, maxAlign,
"cmplx.x.val");
5950 llvm::Value *reX = builder.CreateExtractValue(xStruct, 0);
5951 llvm::Value *imX = builder.CreateExtractValue(xStruct, 1);
5952 llvm::Value *reE = builder.CreateExtractValue(eVal, 0);
5953 llvm::Value *imE = builder.CreateExtractValue(eVal, 1);
5954 llvm::Value *reEq = builder.CreateFCmpOEQ(reX, reE,
"cmplx.re.eq");
5955 llvm::Value *imEq = builder.CreateFCmpOEQ(imX, imE,
"cmplx.im.eq");
5956 llvm::Value *fpEqual = builder.CreateAnd(reEq, imEq,
"cmplx.eq");
5961 llvm::BasicBlock *curBB = builder.GetInsertBlock();
5962 llvm::Function *fn = curBB->getParent();
5963 llvm::BasicBlock *swapBB =
5964 llvm::BasicBlock::Create(builder.getContext(),
"cmplx.atomic.swap", fn);
5965 llvm::BasicBlock *exitBB =
5966 llvm::BasicBlock::Create(builder.getContext(),
"cmplx.atomic.exit", fn);
5967 builder.CreateCondBr(fpEqual, swapBB, exitBB);
5969 builder.SetInsertPoint(swapBB);
5970 llvm::AtomicCmpXchgInst *cmpXchg = builder.CreateAtomicCmpXchg(
5971 llvmX, xCurr, dInt, maxAlign, atomicOrdering, failOrdering);
5972 cmpXchg->setWeak(isWeak);
5973 llvm::Value *oldSwap = builder.CreateExtractValue(cmpXchg, 0);
5974 llvm::Value *okSwap = builder.CreateExtractValue(cmpXchg, 1);
5975 builder.CreateBr(exitBB);
5978 builder.SetInsertPoint(exitBB);
5979 llvm::PHINode *oldIntPHI = builder.CreatePHI(intTy, 2,
"cmplx.old.int");
5980 oldIntPHI->addIncoming(oldSwap, swapBB);
5981 oldIntPHI->addIncoming(xCurr, curBB);
5982 llvm::PHINode *okPHI = builder.CreatePHI(builder.getInt1Ty(), 2,
"cmplx.ok");
5983 okPHI->addIncoming(okSwap, swapBB);
5984 okPHI->addIncoming(builder.getFalse(), curBB);
5987 llvm::AllocaInst *oldAlloca =
5988 builder.CreateAlloca(complexTy,
nullptr,
"cmplx.old");
5989 oldAlloca->setAlignment(maxAlign);
5990 builder.CreateAlignedStore(oldIntPHI, oldAlloca, maxAlign);
5991 oldComplex = builder.CreateAlignedLoad(complexTy, oldAlloca, maxAlign,
5999 llvm::omp::OMPAtomicCompareOp
compareOp = llvm::omp::OMPAtomicCompareOp::EQ;
6019 return atomicCompareOp.emitError(
6020 "unsupported comparison predicate (NE) for complex atomic compare");
6021 info.
compareOp = llvm::omp::OMPAtomicCompareOp::EQ;
6023 info.
eVal = materializeValue(cplx.eAggregate);
6025 if (
auto selectOp = dyn_cast<LLVM::SelectOp>(op)) {
6026 info.
dVal = materializeValue(selectOp.getTrueValue());
6036 if (
auto icmpOp = dyn_cast<LLVM::ICmpOp>(op);
6037 icmpOp && icmpOp.getOperand(0) != block.
getArgument(0) &&
6043 .Case<LLVM::ICmpOp>([&](LLVM::ICmpOp icmpOp) -> LogicalResult {
6047 return atomicCompareOp.emitError(
6048 "unsupported comparison predicate in atomic compare");
6050 LLVM::ICmpPredicate pred = icmpOp.getPredicate();
6051 info.
isSigned = (pred == LLVM::ICmpPredicate::slt ||
6052 pred == LLVM::ICmpPredicate::sgt ||
6053 pred == LLVM::ICmpPredicate::sle ||
6054 pred == LLVM::ICmpPredicate::sge);
6058 : icmpOp.getOperand(0);
6059 info.
eVal = materializeValue(eOperand);
6062 .Case<LLVM::FCmpOp>([&](LLVM::FCmpOp fcmpOp) -> LogicalResult {
6066 return atomicCompareOp.emitError(
6067 "unsupported comparison predicate in atomic compare");
6072 : fcmpOp.getOperand(0);
6073 info.
eVal = materializeValue(eOperand);
6076 .Case<LLVM::SelectOp>([&](LLVM::SelectOp selectOp) {
6078 info.
dVal = materializeValue(selectOp.getTrueValue());
6081 .Case<mlir::arith::MaxSIOp, mlir::arith::MinSIOp,
6082 mlir::arith::MaxUIOp, mlir::arith::MinUIOp,
6083 mlir::arith::MaximumFOp, mlir::arith::MinimumFOp,
6084 LLVM::SMaxOp, LLVM::SMinOp, LLVM::UMaxOp, LLVM::UMinOp,
6085 LLVM::MaxNumOp, LLVM::MinNumOp>([&](
Operation *) {
6090 bool isMax = isa<mlir::arith::MaxSIOp, mlir::arith::MaxUIOp,
6091 mlir::arith::MaximumFOp, LLVM::SMaxOp,
6092 LLVM::UMaxOp, LLVM::MaxNumOp>(op);
6093 info.
compareOp = isMax ? llvm::omp::OMPAtomicCompareOp::MIN
6094 : llvm::omp::OMPAtomicCompareOp::MAX;
6095 info.
isSigned = isa<mlir::arith::MaxSIOp, mlir::arith::MinSIOp,
6096 LLVM::SMaxOp, LLVM::SMinOp>(op);
6100 info.
eVal = materializeValue(eOperand);
6114 llvm::IRBuilderBase &builder,
6120 omp::AtomicUpdateOp atomicUpdateOp = atomicCaptureOp.getAtomicUpdateOp();
6121 omp::AtomicWriteOp atomicWriteOp = atomicCaptureOp.getAtomicWriteOp();
6122 omp::AtomicCompareOp atomicCompareOp = atomicCaptureOp.getAtomicCompareOp();
6126 if (atomicCompareOp) {
6127 omp::AtomicReadOp atomicReadOp = atomicCaptureOp.getAtomicReadOp();
6128 assert(atomicReadOp &&
"expected atomic.read in capture+compare");
6130 Region ®ion = atomicCompareOp.getRegion();
6133 llvm::Type *llvmXElementType =
6135 llvm::Value *llvmX = moduleTranslation.
lookupValue(atomicCompareOp.getX());
6136 llvm::Value *llvmV = moduleTranslation.
lookupValue(atomicReadOp.getV());
6138 bool isSigned =
false;
6139 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {
6140 llvmX, llvmXElementType, isSigned,
false};
6141 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicV = {
6142 llvmV, llvmXElementType,
false,
false};
6143 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicR = {
nullptr,
nullptr,
false,
6146 llvm::AtomicOrdering atomicOrdering =
6150 auto isAtomicComparePatternOp = [](
Operation &op) {
6151 return llvm::isa<LLVM::ICmpOp, LLVM::FCmpOp, LLVM::SelectOp, LLVM::AndOp,
6152 LLVM::OrOp, LLVM::SMaxOp, LLVM::SMinOp, LLVM::UMaxOp,
6153 LLVM::UMinOp, LLVM::MaxNumOp, LLVM::MinNumOp,
6154 mlir::arith::MaxSIOp, mlir::arith::MinSIOp,
6155 mlir::arith::MaxUIOp, mlir::arith::MinUIOp,
6156 mlir::arith::MaximumFOp, mlir::arith::MinimumFOp>(op);
6159 if (isAtomicComparePatternOp(op))
6161 bool allOperandsMapped =
6163 return moduleTranslation.lookupValue(v) != nullptr;
6165 if (!allOperandsMapped)
6168 return atomicCompareOp.emitError(
6169 "failed to translate operation inside atomic compare region");
6172 auto materializeValue = [&](
mlir::Value val) -> llvm::Value * {
6173 if (llvm::Value *existing = moduleTranslation.
lookupValue(val))
6176 if (loadOp->getParentRegion() == ®ion) {
6177 llvm::Value *loadAddr =
6181 llvm::Type *loadType =
6182 moduleTranslation.
convertType(loadOp.getResult().getType());
6183 return builder.CreateLoad(loadType, loadAddr);
6192 atomicCompareOp, patternInfo)))
6195 llvm::omp::OMPAtomicCompareOp compareOp = patternInfo.
compareOp;
6196 llvm::Value *eVal = patternInfo.
eVal;
6197 llvm::Value *dVal = patternInfo.
dVal;
6202 return atomicCompareOp.emitError(
6203 "failed to extract expected value (e) from atomic compare region");
6206 if (yieldOp.getResults().empty())
6207 return atomicCompareOp.emitError(
6208 "failed to extract desired value (d) from atomic compare region");
6209 dVal = materializeValue(yieldOp.getResults()[0]);
6212 llvmAtomicX.IsSigned = isSigned;
6214 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6215 bool isReadFirst = isa<omp::AtomicReadOp>(atomicCaptureOp.getFirstOp());
6216 bool isPostfixCapture = !isReadFirst;
6217 bool isFailOnly = atomicCaptureOp.getFailOnly();
6225 if (llvmXElementType->isStructTy()) {
6226 llvm::Value *oldComplex =
nullptr;
6227 llvm::Value *cmpOk =
nullptr;
6228 llvm::AtomicOrdering failOrdering =
6231 atomicOrdering, failOrdering,
6232 atomicCompareOp.getWeak(), oldComplex, cmpOk);
6236 llvm::Value *cmpFailed = builder.CreateNot(cmpOk);
6237 llvm::BasicBlock *curBB = builder.GetInsertBlock();
6238 llvm::Function *fn = curBB->getParent();
6239 llvm::BasicBlock *contBB = llvm::BasicBlock::Create(
6240 builder.getContext(),
"omp.atomic.cont", fn);
6241 llvm::BasicBlock *exitBB = llvm::BasicBlock::Create(
6242 builder.getContext(),
"omp.atomic.exit", fn);
6243 builder.CreateCondBr(cmpFailed, contBB, exitBB);
6244 builder.SetInsertPoint(contBB);
6245 builder.CreateStore(oldComplex, llvmAtomicV.Var,
6246 llvmAtomicV.IsVolatile);
6247 builder.CreateBr(exitBB);
6248 builder.SetInsertPoint(exitBB);
6249 }
else if (isPostfixCapture) {
6251 llvm::Value *newComplex = builder.CreateSelect(cmpOk, dVal, oldComplex);
6252 builder.CreateStore(newComplex, llvmAtomicV.Var,
6253 llvmAtomicV.IsVolatile);
6256 builder.CreateStore(oldComplex, llvmAtomicV.Var,
6257 llvmAtomicV.IsVolatile);
6261 if (atomicOrdering == llvm::AtomicOrdering::Release ||
6262 atomicOrdering == llvm::AtomicOrdering::AcquireRelease ||
6263 atomicOrdering == llvm::AtomicOrdering::SequentiallyConsistent) {
6264 llvm::OpenMPIRBuilder::LocationDescription flushLoc(builder);
6265 ompBuilder->createFlush(flushLoc);
6276 bool isMinMax = compareOp != llvm::omp::OMPAtomicCompareOp::EQ;
6278 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicVForCall = llvmAtomicV;
6285 bool minMaxManualCapture = isMinMax && (isPostfixCapture || isFailOnly);
6286 bool eqPostfixManualCapture = !isMinMax && isPostfixCapture && !isFailOnly;
6287 if (minMaxManualCapture || eqPostfixManualCapture)
6288 llvmAtomicVForCall = {
nullptr,
nullptr,
false,
false};
6292 bool builderFailOnly = isFailOnly && !isMinMax;
6299 bool isPostfixUpdate = !builderFailOnly;
6301 bool isWeak = atomicCompareOp.getWeak();
6302 bool savedHandleFPNegZero = ompBuilder->setHandleFPNegZero(
true);
6303 llvm::AtomicOrdering failureOrdering =
6305 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
6306 ompBuilder->createAtomicCompare(
6307 ompLoc, llvmAtomicX, llvmAtomicVForCall, llvmAtomicR, eVal, dVal,
6308 atomicOrdering, compareOp, isXBinopExpr, isPostfixUpdate,
6309 builderFailOnly, failureOrdering, isWeak);
6310 ompBuilder->setHandleFPNegZero(savedHandleFPNegZero);
6312 if (failed(
handleError(afterIP, *atomicCaptureOp)))
6315 builder.restoreIP(*afterIP);
6324 if (isMinMax && (isPostfixCapture || isFailOnly)) {
6325 llvm::BasicBlock *curBB = builder.GetInsertBlock();
6326 llvm::AtomicRMWInst *rmw =
nullptr;
6327 for (
auto &inst : llvm::reverse(*curBB)) {
6328 if (
auto *r = dyn_cast<llvm::AtomicRMWInst>(&inst)) {
6333 assert(rmw &&
"expected atomicrmw for min/max compare capture");
6334 llvm::Value *oldVal = rmw;
6335 llvm::Value *rhs = rmw->getValOperand();
6341 llvm::CmpInst::Predicate updatePred;
6342 switch (rmw->getOperation()) {
6343 case llvm::AtomicRMWInst::Min:
6344 updatePred = llvm::CmpInst::ICMP_SGT;
6346 case llvm::AtomicRMWInst::Max:
6347 updatePred = llvm::CmpInst::ICMP_SLT;
6349 case llvm::AtomicRMWInst::UMin:
6350 updatePred = llvm::CmpInst::ICMP_UGT;
6352 case llvm::AtomicRMWInst::UMax:
6353 updatePred = llvm::CmpInst::ICMP_ULT;
6355 case llvm::AtomicRMWInst::FMin:
6356 updatePred = llvm::CmpInst::FCMP_OGT;
6358 case llvm::AtomicRMWInst::FMax:
6359 updatePred = llvm::CmpInst::FCMP_OLT;
6363 "unexpected atomicrmw op for min/max compare capture");
6365 llvm::Value *updated = builder.CreateCmp(updatePred, oldVal, rhs);
6366 llvm::Value *failed = builder.CreateNot(updated);
6367 llvm::Function *fn = curBB->getParent();
6368 llvm::BasicBlock *contBB = llvm::BasicBlock::Create(
6369 builder.getContext(),
"omp.atomic.cont", fn);
6370 llvm::BasicBlock *exitBB = llvm::BasicBlock::Create(
6371 builder.getContext(),
"omp.atomic.exit", fn);
6372 builder.CreateCondBr(failed, contBB, exitBB);
6373 builder.SetInsertPoint(contBB);
6374 builder.CreateStore(oldVal, llvmAtomicV.Var, llvmAtomicV.IsVolatile);
6375 builder.CreateBr(exitBB);
6376 builder.SetInsertPoint(exitBB);
6378 llvm::Intrinsic::ID id;
6379 switch (rmw->getOperation()) {
6380 case llvm::AtomicRMWInst::Min:
6381 id = llvm::Intrinsic::smin;
6383 case llvm::AtomicRMWInst::Max:
6384 id = llvm::Intrinsic::smax;
6386 case llvm::AtomicRMWInst::UMin:
6387 id = llvm::Intrinsic::umin;
6389 case llvm::AtomicRMWInst::UMax:
6390 id = llvm::Intrinsic::umax;
6392 case llvm::AtomicRMWInst::FMin:
6393 id = llvm::Intrinsic::minnum;
6395 case llvm::AtomicRMWInst::FMax:
6396 id = llvm::Intrinsic::maxnum;
6400 "unexpected atomicrmw op for min/max compare capture");
6402 llvm::Value *newVal = builder.CreateBinaryIntrinsic(
id, oldVal, rhs);
6403 builder.CreateStore(newVal, llvmAtomicV.Var, llvmAtomicV.IsVolatile);
6409 if (!isMinMax && isPostfixCapture && !isFailOnly) {
6410 llvm::BasicBlock *curBB = builder.GetInsertBlock();
6411 llvm::Value *oldVal =
nullptr;
6412 llvm::Value *successVal =
nullptr;
6416 for (
auto &inst : llvm::reverse(*curBB)) {
6417 if (isa<llvm::AtomicCmpXchgInst>(&inst)) {
6418 oldVal = builder.CreateExtractValue(&inst, 0);
6419 successVal = builder.CreateExtractValue(&inst, 1);
6430 for (
auto &inst : *curBB) {
6431 auto *phi = dyn_cast<llvm::PHINode>(&inst);
6434 if (phi->getType()->isIntegerTy(1))
6437 for (
auto &inst : *curBB) {
6438 if (
auto *bc = dyn_cast<llvm::BitCastInst>(&inst)) {
6445 assert(oldVal &&
"expected cmpxchg or PHI+bitcast for compare capture");
6446 assert(successVal &&
"expected success flag for compare capture");
6447 llvm::Value *newVal = builder.CreateSelect(successVal, dVal, oldVal);
6448 builder.CreateStore(newVal, llvmAtomicV.Var, llvmAtomicV.IsVolatile);
6455 bool isXBinopExpr =
false, isPostfixUpdate =
false;
6456 llvm::AtomicRMWInst::BinOp binop = llvm::AtomicRMWInst::BinOp::BAD_BINOP;
6458 assert((atomicUpdateOp || atomicWriteOp) &&
6459 "internal op must be an atomic.update or atomic.write op");
6461 if (atomicWriteOp) {
6462 isPostfixUpdate =
true;
6463 mlirExpr = atomicWriteOp.getExpr();
6465 isPostfixUpdate = atomicCaptureOp.getSecondOp() ==
6466 atomicCaptureOp.getAtomicUpdateOp().getOperation();
6467 auto &innerOpList = atomicUpdateOp.getRegion().front().getOperations();
6470 if (innerOpList.size() == 2) {
6473 atomicUpdateOp.getRegion().getArgument(0))) {
6474 return atomicUpdateOp.emitError(
6475 "no atomic update operation with region argument"
6476 " as operand found inside atomic.update region");
6480 innerOp.
getOperand(0) == atomicUpdateOp.getRegion().getArgument(0);
6483 binop = llvm::AtomicRMWInst::BinOp::BAD_BINOP;
6487 llvm::Value *llvmExpr = moduleTranslation.
lookupValue(mlirExpr);
6488 llvm::Value *llvmX =
6489 moduleTranslation.
lookupValue(atomicCaptureOp.getAtomicReadOp().getX());
6490 llvm::Value *llvmV =
6491 moduleTranslation.
lookupValue(atomicCaptureOp.getAtomicReadOp().getV());
6492 llvm::Type *llvmXElementType = moduleTranslation.
convertType(
6493 atomicCaptureOp.getAtomicReadOp().getElementType());
6494 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {llvmX, llvmXElementType,
6497 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicV = {llvmV, llvmXElementType,
6501 llvm::AtomicOrdering atomicOrdering =
6505 [&](llvm::Value *atomicx,
6508 return moduleTranslation.
lookupValue(atomicWriteOp.getExpr());
6509 Block &bb = *atomicUpdateOp.getRegion().
begin();
6510 moduleTranslation.
mapValue(*atomicUpdateOp.getRegion().args_begin(),
6512 moduleTranslation.
mapBlock(&bb, builder.GetInsertBlock());
6513 if (failed(moduleTranslation.
convertBlock(bb,
true, builder)))
6514 return llvm::make_error<PreviouslyReportedError>();
6516 omp::YieldOp yieldop = dyn_cast<omp::YieldOp>(bb.
getTerminator());
6517 assert(yieldop && yieldop.getResults().size() == 1 &&
6518 "terminator must be omp.yield op and it must have exactly one "
6520 return moduleTranslation.
lookupValue(yieldop.getResults()[0]);
6523 bool isIgnoreDenormalMode;
6524 bool isFineGrainedMemory;
6525 bool isRemoteMemory;
6527 isFineGrainedMemory, isRemoteMemory);
6530 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6531 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
6532 ompBuilder->createAtomicCapture(
6533 ompLoc, allocaIP, llvmAtomicX, llvmAtomicV, llvmExpr, atomicOrdering,
6534 binop, updateFn, atomicUpdateOp, isPostfixUpdate, isXBinopExpr,
6535 isIgnoreDenormalMode, isFineGrainedMemory, isRemoteMemory);
6537 if (failed(
handleError(afterIP, *atomicCaptureOp)))
6540 builder.restoreIP(*afterIP);
6562 llvm::IRBuilderBase &builder,
6568 Region ®ion = atomicCompareOp.getRegion();
6572 llvm::Type *llvmXElementType =
6574 if (!llvmXElementType)
6575 return atomicCompareOp.emitError(
6576 "unable to determine element type for atomic compare");
6578 llvm::Value *llvmX = moduleTranslation.
lookupValue(atomicCompareOp.getX());
6583 bool isSigned =
false;
6584 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {llvmX, llvmXElementType,
6588 llvm::AtomicOrdering atomicOrdering =
6591 auto isAtomicComparePatternOp = [](
Operation &op) {
6592 return llvm::isa<LLVM::ICmpOp, LLVM::FCmpOp, LLVM::SelectOp, LLVM::AndOp,
6593 LLVM::OrOp, LLVM::SMaxOp, LLVM::SMinOp, LLVM::UMaxOp,
6594 LLVM::UMinOp, LLVM::MaxNumOp, LLVM::MinNumOp,
6595 mlir::arith::MaxSIOp, mlir::arith::MinSIOp,
6596 mlir::arith::MaxUIOp, mlir::arith::MinUIOp,
6597 mlir::arith::MaximumFOp, mlir::arith::MinimumFOp>(op);
6617 if (isAtomicComparePatternOp(op))
6622 return moduleTranslation.lookupValue(v) != nullptr;
6624 if (!allOperandsMapped)
6628 return atomicCompareOp.emitError(
6629 "failed to translate operation inside atomic compare region");
6634 auto materializeValue = [&](
mlir::Value val) -> llvm::Value * {
6636 if (llvm::Value *existing = moduleTranslation.
lookupValue(val))
6641 if (loadOp->getParentRegion() == ®ion) {
6642 llvm::Value *loadAddr = moduleTranslation.
lookupValue(loadOp.getAddr());
6645 llvm::Type *loadType =
6646 moduleTranslation.
convertType(loadOp.getResult().getType());
6647 return builder.CreateLoad(loadType, loadAddr);
6655 llvm::omp::OMPAtomicCompareOp compareOp = llvm::omp::OMPAtomicCompareOp::EQ;
6656 llvm::Value *eVal =
nullptr;
6657 llvm::Value *dVal =
nullptr;
6658 bool isXBinopExpr =
false;
6664 if (isComplexPattern) {
6667 return atomicCompareOp.emitError(
6668 "unsupported comparison predicate (NE) for complex atomic compare");
6669 compareOp = llvm::omp::OMPAtomicCompareOp::EQ;
6674 if (isComplexPattern) {
6677 if (
auto selectOp = dyn_cast<LLVM::SelectOp>(op)) {
6678 dVal = materializeValue(selectOp.getTrueValue());
6684 if (yieldOp.getResults().empty())
6685 return atomicCompareOp.emitError(
6686 "failed to extract desired value (d) from atomic compare region");
6687 dVal = materializeValue(yieldOp.getResults()[0]);
6690 llvm::Value *oldComplex =
nullptr;
6691 llvm::Value *cmpOk =
nullptr;
6692 llvm::AtomicOrdering failOrdering =
6695 atomicOrdering, failOrdering,
6696 atomicCompareOp.getWeak(), oldComplex, cmpOk);
6702 if (atomicOrdering == llvm::AtomicOrdering::Release ||
6703 atomicOrdering == llvm::AtomicOrdering::AcquireRelease ||
6704 atomicOrdering == llvm::AtomicOrdering::SequentiallyConsistent) {
6705 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6706 ompBuilder->createFlush(ompLoc);
6712 atomicCompareOp, patternInfo)))
6715 eVal = patternInfo.
eVal;
6716 dVal = patternInfo.
dVal;
6722 return atomicCompareOp.emitError(
6723 "failed to extract expected value (e) from atomic compare region");
6727 if (yieldOp.getResults().empty())
6728 return atomicCompareOp.emitError(
6729 "failed to extract desired value (d) from atomic compare region");
6730 dVal = materializeValue(yieldOp.getResults()[0]);
6733 llvmAtomicX.IsSigned = isSigned;
6735 llvm::OpenMPIRBuilder::AtomicOpValue vOpVal = {
nullptr,
nullptr,
false,
6737 llvm::OpenMPIRBuilder::AtomicOpValue rOpVal = {
nullptr,
nullptr,
false,
6739 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6741 bool isWeak = atomicCompareOp.getWeak();
6743 bool savedHandleFPNegZero = ompBuilder->setHandleFPNegZero(
true);
6744 llvm::AtomicOrdering failureOrdering =
6746 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
6747 ompBuilder->createAtomicCompare(
6748 ompLoc, llvmAtomicX, vOpVal, rOpVal, eVal, dVal, atomicOrdering,
6749 compareOp, isXBinopExpr,
false,
6750 false, failureOrdering, isWeak);
6751 ompBuilder->setHandleFPNegZero(savedHandleFPNegZero);
6753 if (failed(
handleError(afterIP, *atomicCompareOp)))
6756 builder.restoreIP(*afterIP);
6761 omp::ClauseCancellationConstructType directive) {
6762 switch (directive) {
6763 case omp::ClauseCancellationConstructType::Loop:
6764 return llvm::omp::Directive::OMPD_for;
6765 case omp::ClauseCancellationConstructType::Parallel:
6766 return llvm::omp::Directive::OMPD_parallel;
6767 case omp::ClauseCancellationConstructType::Sections:
6768 return llvm::omp::Directive::OMPD_sections;
6769 case omp::ClauseCancellationConstructType::Taskgroup:
6770 return llvm::omp::Directive::OMPD_taskgroup;
6772 llvm_unreachable(
"Unhandled cancellation construct type");
6781 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6784 llvm::Value *ifCond =
nullptr;
6785 if (
Value ifVar = op.getIfExpr())
6788 llvm::omp::Directive cancelledDirective =
6791 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
6792 ompBuilder->createCancel(ompLoc, ifCond, cancelledDirective);
6794 if (failed(
handleError(afterIP, *op.getOperation())))
6797 builder.restoreIP(afterIP.get());
6804 llvm::IRBuilderBase &builder,
6809 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6812 llvm::omp::Directive cancelledDirective =
6815 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
6816 ompBuilder->createCancellationPoint(ompLoc, cancelledDirective);
6818 if (failed(
handleError(afterIP, *op.getOperation())))
6821 builder.restoreIP(afterIP.get());
6831 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6833 auto threadprivateOp = cast<omp::ThreadprivateOp>(opInst);
6838 Value symAddr = threadprivateOp.getSymAddr();
6841 if (
auto asCast = dyn_cast<LLVM::AddrSpaceCastOp>(symOp))
6844 if (!isa<LLVM::AddressOfOp>(symOp))
6845 return opInst.
emitError(
"Addressing symbol not found");
6846 LLVM::AddressOfOp addressOfOp = dyn_cast<LLVM::AddressOfOp>(symOp);
6848 LLVM::GlobalOp global =
6849 addressOfOp.getGlobal(moduleTranslation.
symbolTable());
6850 llvm::GlobalValue *globalValue = moduleTranslation.
lookupGlobal(global);
6851 llvm::Type *type = globalValue->getValueType();
6852 llvm::TypeSize typeSize =
6853 builder.GetInsertBlock()->getModule()->getDataLayout().getTypeStoreSize(
6855 llvm::ConstantInt *size = builder.getInt64(typeSize.getFixedValue());
6856 llvm::Value *callInst = ompBuilder->createCachedThreadPrivate(
6857 ompLoc, globalValue, size, global.getSymName() +
".cache");
6863static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind
6865 switch (deviceClause) {
6866 case mlir::omp::DeclareTargetDeviceType::host:
6867 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseHost;
6869 case mlir::omp::DeclareTargetDeviceType::nohost:
6870 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNoHost;
6872 case mlir::omp::DeclareTargetDeviceType::any:
6873 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny;
6876 llvm_unreachable(
"unhandled device clause");
6879static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind
6881 mlir::omp::DeclareTargetCaptureClause captureClause) {
6882 switch (captureClause) {
6883 case mlir::omp::DeclareTargetCaptureClause::to:
6884 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo;
6885 case mlir::omp::DeclareTargetCaptureClause::link:
6886 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink;
6887 case mlir::omp::DeclareTargetCaptureClause::enter:
6888 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter;
6889 case mlir::omp::DeclareTargetCaptureClause::none:
6890 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
6892 llvm_unreachable(
"unhandled capture clause");
6897 if (
auto addrCast = dyn_cast_if_present<LLVM::AddrSpaceCastOp>(op))
6899 if (
auto addressOfOp = dyn_cast_if_present<LLVM::AddressOfOp>(op)) {
6900 auto modOp = addressOfOp->getParentOfType<mlir::ModuleOp>();
6901 return modOp.lookupSymbol(addressOfOp.getGlobalName());
6908 if (
auto addrCast = dyn_cast_if_present<LLVM::AddrSpaceCastOp>(op))
6909 value = addrCast.getOperand();
6933 if (!llvmVarTy->isPointerTy())
6937 if (
auto gop = dyn_cast<LLVM::GlobalOp>(globalOp))
6938 return moduleTranslation.
convertType(gop.getGlobalType());
6941 dyn_cast_if_present<LLVM::AllocaOp>(baseVar.
getDefiningOp()))
6942 return moduleTranslation.
convertType(allocaOp.getElemType());
6944 if (llvm::Value *baseLlvm = moduleTranslation.
lookupValue(baseVar))
6945 if (
auto *allocaInst = dyn_cast<llvm::AllocaInst>(baseLlvm))
6946 return allocaInst->getAllocatedType();
6955 llvm::IRBuilderBase &builder,
const llvm::DataLayout &dataLayout) {
6957 dyn_cast_if_present<LLVM::AllocaOp>(baseVar.
getDefiningOp())) {
6958 if (
Value arraySize = allocaOp.getArraySize()) {
6959 llvm::Type *elemTy =
6960 moduleTranslation.
convertType(allocaOp.getElemType());
6961 llvm::Value *numElems = moduleTranslation.
lookupValue(arraySize);
6962 if (!numElems->getType()->isIntegerTy(64))
6963 numElems = builder.CreateZExt(numElems, builder.getInt64Ty());
6964 uint64_t elemSize = dataLayout.getTypeAllocSize(elemTy).getFixedValue();
6965 return builder.CreateMul(numElems, builder.getInt64(elemSize));
6968 if (llvm::Value *baseLlvm = moduleTranslation.
lookupValue(baseVar)) {
6969 if (
auto *allocaInst = dyn_cast<llvm::AllocaInst>(baseLlvm)) {
6970 if (allocaInst->isArrayAllocation() &&
6971 !llvm::isa<llvm::ArrayType>(allocaInst->getAllocatedType())) {
6973 dataLayout.getTypeAllocSize(allocaInst->getAllocatedType())
6975 return builder.CreateMul(allocaInst->getArraySize(),
6976 builder.getInt64(elemSize));
6980 return std::nullopt;
6983static llvm::SmallString<64>
6985 llvm::OpenMPIRBuilder &ompBuilder,
6986 llvm::vfs::FileSystem &vfs) {
6988 llvm::raw_svector_ostream os(suffix);
6991 auto fileInfoCallBack = [&loc]() {
6992 return std::pair<std::string, uint64_t>(
6993 llvm::StringRef(loc.getFilename()), loc.getLine());
6998 ompBuilder.getTargetEntryUniqueInfo(fileInfoCallBack, vfs).FileID);
7000 os <<
"_decl_tgt_ref_ptr";
7006 if (
auto declareTargetGlobal =
7007 dyn_cast_if_present<omp::DeclareTargetInterface>(
7009 if (declareTargetGlobal.getDeclareTargetCaptureClause() ==
7010 omp::DeclareTargetCaptureClause::link)
7016 if (
auto declareTargetGlobal =
7017 dyn_cast_if_present<omp::DeclareTargetInterface>(
7019 if (declareTargetGlobal.getDeclareTargetCaptureClause() ==
7020 omp::DeclareTargetCaptureClause::to ||
7021 declareTargetGlobal.getDeclareTargetCaptureClause() ==
7022 omp::DeclareTargetCaptureClause::enter)
7040 ompBuilder->Config.hasRequiresUnifiedSharedMemory())) {
7044 if (gOp.getSymName().contains(suffix))
7049 (gOp.getSymName().str() + suffix.str()).str());
7057struct MapInfosTy : llvm::OpenMPIRBuilder::MapInfosTy {
7058 SmallVector<Operation *, 4> Mappers;
7061 void append(MapInfosTy &curInfo) {
7062 Mappers.append(curInfo.Mappers.begin(), curInfo.Mappers.end());
7063 llvm::OpenMPIRBuilder::MapInfosTy::append(curInfo);
7072struct MapInfoData : MapInfosTy {
7073 llvm::SmallVector<bool, 4> IsDeclareTarget;
7074 llvm::SmallVector<bool, 4> IsAMember;
7076 llvm::SmallVector<bool, 4> IsAMapping;
7077 llvm::SmallVector<mlir::Operation *, 4> MapClause;
7078 llvm::SmallVector<llvm::Value *, 4> OriginalValue;
7081 llvm::SmallVector<llvm::Type *, 4> BaseType;
7084 void append(MapInfoData &CurInfo) {
7085 IsDeclareTarget.append(CurInfo.IsDeclareTarget.begin(),
7086 CurInfo.IsDeclareTarget.end());
7087 MapClause.append(CurInfo.MapClause.begin(), CurInfo.MapClause.end());
7088 OriginalValue.append(CurInfo.OriginalValue.begin(),
7089 CurInfo.OriginalValue.end());
7090 BaseType.append(CurInfo.BaseType.begin(), CurInfo.BaseType.end());
7091 MapInfosTy::append(CurInfo);
7095enum class TargetDirectiveEnumTy : uint32_t {
7099 TargetEnterData = 3,
7104static TargetDirectiveEnumTy getTargetDirectiveEnumTyFromOp(Operation *op) {
7105 return llvm::TypeSwitch<Operation *, TargetDirectiveEnumTy>(op)
7106 .Case([](omp::TargetDataOp) {
return TargetDirectiveEnumTy::TargetData; })
7107 .Case([](omp::TargetEnterDataOp) {
7108 return TargetDirectiveEnumTy::TargetEnterData;
7110 .Case([&](omp::TargetExitDataOp) {
7111 return TargetDirectiveEnumTy::TargetExitData;
7113 .Case([&](omp::TargetUpdateOp) {
7114 return TargetDirectiveEnumTy::TargetUpdate;
7116 .Case([&](omp::TargetOp) {
return TargetDirectiveEnumTy::Target; })
7117 .Default([&](Operation *op) {
return TargetDirectiveEnumTy::None; });
7124 if (
auto nestedArrTy = llvm::dyn_cast_if_present<LLVM::LLVMArrayType>(
7125 arrTy.getElementType()))
7139 if (mapOp.getVarPtrPtr())
7156 return bitEnumContainsAll(mapType, omp::ClauseMapFlags::priv |
7157 omp::ClauseMapFlags::target_param |
7158 omp::ClauseMapFlags::attach);
7173 llvm::Value *basePointer,
7174 llvm::Type *baseType,
7175 llvm::IRBuilderBase &builder,
7177 if (
auto memberClause =
7178 mlir::dyn_cast_if_present<mlir::omp::MapInfoOp>(clauseOp)) {
7183 if (!memberClause.getBounds().empty()) {
7184 llvm::Value *elementCount = builder.getInt64(1);
7185 for (
auto bounds : memberClause.getBounds()) {
7186 if (
auto boundOp = mlir::dyn_cast_if_present<mlir::omp::MapBoundsOp>(
7187 bounds.getDefiningOp())) {
7192 elementCount = builder.CreateMul(
7196 moduleTranslation.
lookupValue(boundOp.getUpperBound()),
7197 moduleTranslation.
lookupValue(boundOp.getLowerBound())),
7198 builder.getInt64(1)));
7205 if (
auto arrTy = llvm::dyn_cast_if_present<LLVM::LLVMArrayType>(type))
7213 llvm::Value *sizeCalc = builder.CreateMul(
7214 elementCount, builder.getInt64(underlyingTypeSzInBits / 8),
7252 return builder.CreateSelect(
7253 builder.CreateICmpEQ(sizeCalc, builder.getInt64(0)),
7254 builder.getInt64(1), sizeCalc);
7268static llvm::omp::OpenMPOffloadMappingFlags
7270 const bool hasExplicitMap =
7271 (mlirFlags &
~omp::ClauseMapFlags::is_device_ptr) !=
7272 omp::ClauseMapFlags::none;
7274 llvm::omp::OpenMPOffloadMappingFlags mapType =
7275 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7277 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::to))
7278 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
7280 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::from))
7281 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7283 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::always))
7284 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
7286 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::del))
7287 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
7289 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::return_param))
7290 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
7292 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::priv))
7293 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRIVATE;
7295 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::literal))
7296 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL;
7298 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::implicit))
7299 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
7301 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::close))
7302 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
7304 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::present))
7305 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
7307 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::ompx_hold))
7308 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
7310 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::attach))
7311 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH;
7313 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::target_param))
7314 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7316 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::is_device_ptr)) {
7317 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7318 if (!hasExplicitMap)
7319 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL;
7329 ArrayRef<Value> useDevAddrOperands = {},
7330 ArrayRef<Value> hasDevAddrOperands = {}) {
7332 auto checkRefPtrOrPteeMapWithAttach = [](omp::ClauseMapFlags mapType) {
7334 bitEnumContainsAll(mapType, omp::ClauseMapFlags::ref_ptr) ||
7335 bitEnumContainsAll(mapType, omp::ClauseMapFlags::ref_ptee);
7336 return hasRefType &&
7337 bitEnumContainsAll(mapType, omp::ClauseMapFlags::attach);
7340 auto checkIsAMember = [](
const auto &mapVars,
auto mapOp) {
7348 for (Value mapValue : mapVars) {
7349 auto map = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
7350 for (
auto member : map.getMembers())
7351 if (member == mapOp)
7358 for (Value mapValue : mapVars) {
7359 auto mapOp = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
7360 bool isAttachStyleMap =
7361 checkRefPtrOrPteeMapWithAttach(mapOp.getMapType()) ||
7363 Value offloadPtr = (mapOp.getVarPtrPtr() && !isAttachStyleMap)
7364 ? mapOp.getVarPtrPtr()
7365 : mapOp.getVarPtr();
7366 mapData.OriginalValue.push_back(moduleTranslation.
lookupValue(offloadPtr));
7367 mapData.Pointers.push_back(
7368 isAttachStyleMap ? moduleTranslation.
lookupValue(mapOp.getVarPtrPtr())
7369 : mapData.OriginalValue.back());
7371 if (llvm::Value *refPtr =
7373 mapData.IsDeclareTarget.push_back(
true);
7374 mapData.BasePointers.push_back(refPtr);
7376 mapData.IsDeclareTarget.push_back(
true);
7377 mapData.BasePointers.push_back(mapData.OriginalValue.back());
7379 mapData.IsDeclareTarget.push_back(
false);
7380 mapData.BasePointers.push_back(mapData.OriginalValue.back());
7386 mapData.BaseType.push_back(moduleTranslation.
convertType(
7387 mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtrType().value()
7388 : mapOp.getVarPtrType()));
7395 mlir::Type sizeType = (isAttachStyleMap || !mapOp.getVarPtrPtr())
7396 ? mapOp.getVarPtrType()
7397 : mapOp.getVarPtrPtrType().value();
7399 dl, sizeType, isAttachStyleMap ?
nullptr : mapOp,
7400 mapData.Pointers.back(), moduleTranslation.
convertType(sizeType),
7401 builder, moduleTranslation));
7402 mapData.MapClause.push_back(mapOp.getOperation());
7405 mapData.HasAttachPtr.push_back(
false);
7406 mapData.Names.push_back(LLVM::createMappingInformation(
7408 mapData.DevicePointers.push_back(llvm::OpenMPIRBuilder::DeviceInfoTy::None);
7409 if (mapOp.getMapperId())
7410 mapData.Mappers.push_back(
7412 mapOp, mapOp.getMapperIdAttr()));
7414 mapData.Mappers.push_back(
nullptr);
7415 mapData.IsAMapping.push_back(
true);
7416 mapData.IsAMember.push_back(checkIsAMember(mapVars, mapOp));
7419 auto findMapInfo = [&mapData](llvm::Value *val,
7420 llvm::OpenMPIRBuilder::DeviceInfoTy devInfoTy,
7421 size_t memberCount) {
7424 for (llvm::Value *basePtr : mapData.OriginalValue) {
7425 auto mapOp = cast<omp::MapInfoOp>(mapData.MapClause[index]);
7436 (mapData.Types[index] &
7437 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH) ==
7438 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH;
7439 if (!isAttachMap && basePtr == val && mapData.IsAMapping[index] &&
7440 memberCount == mapOp.getMembers().size()) {
7442 mapData.Types[index] |=
7443 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
7444 mapData.DevicePointers[index] = devInfoTy;
7452 auto addDevInfos = [&](
const llvm::ArrayRef<Value> &useDevOperands,
7453 llvm::OpenMPIRBuilder::DeviceInfoTy devInfoTy) {
7454 for (Value mapValue : useDevOperands) {
7455 auto mapOp = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
7457 mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtr() : mapOp.getVarPtr();
7458 llvm::Value *origValue = moduleTranslation.
lookupValue(offloadPtr);
7461 if (!findMapInfo(origValue, devInfoTy, mapOp.getMembers().size())) {
7462 mapData.OriginalValue.push_back(origValue);
7463 mapData.Pointers.push_back(mapData.OriginalValue.back());
7464 mapData.IsDeclareTarget.push_back(
false);
7465 mapData.BasePointers.push_back(mapData.OriginalValue.back());
7466 mlir::Type baseTy = mapOp.getVarPtrPtr()
7467 ? mapOp.getVarPtrPtrType().value()
7468 : mapOp.getVarPtrType();
7469 mapData.BaseType.push_back(moduleTranslation.
convertType(baseTy));
7470 mapData.Sizes.push_back(builder.getInt64(0));
7471 mapData.MapClause.push_back(mapOp.getOperation());
7472 mapData.Types.push_back(
7473 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM);
7475 mapData.HasAttachPtr.push_back(
false);
7476 mapData.Names.push_back(LLVM::createMappingInformation(
7478 mapData.DevicePointers.push_back(devInfoTy);
7479 mapData.Mappers.push_back(
nullptr);
7480 mapData.IsAMapping.push_back(
false);
7481 mapData.IsAMember.push_back(checkIsAMember(useDevOperands, mapOp));
7486 addDevInfos(useDevAddrOperands, llvm::OpenMPIRBuilder::DeviceInfoTy::Address);
7487 addDevInfos(useDevPtrOperands, llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer);
7489 for (Value mapValue : hasDevAddrOperands) {
7490 auto mapOp = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
7492 mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtr() : mapOp.getVarPtr();
7493 llvm::Value *origValue = moduleTranslation.
lookupValue(offloadPtr);
7495 auto mapTypeAlways = llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
7497 (mapOp.getMapType() & omp::ClauseMapFlags::is_device_ptr) !=
7498 omp::ClauseMapFlags::none;
7500 mapData.OriginalValue.push_back(origValue);
7501 mapData.BasePointers.push_back(origValue);
7502 mapData.Pointers.push_back(origValue);
7503 mapData.IsDeclareTarget.push_back(
false);
7505 mlir::Type baseTy = mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtrType().value()
7506 : mapOp.getVarPtrType();
7507 mapData.BaseType.push_back(moduleTranslation.
convertType(baseTy));
7508 mapData.Sizes.push_back(builder.getInt64(dl.
getTypeSize(baseTy)));
7510 mapData.MapClause.push_back(mapOp.getOperation());
7511 if (llvm::to_underlying(mapType & mapTypeAlways)) {
7515 mapData.Types.push_back(mapType);
7517 mapData.HasAttachPtr.push_back(
false);
7521 if (mapOp.getMapperId()) {
7522 mapData.Mappers.push_back(
7524 mapOp, mapOp.getMapperIdAttr()));
7526 mapData.Mappers.push_back(
nullptr);
7531 mapData.Types.push_back(
7532 isDevicePtr ? mapType
7533 : llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
7535 mapData.HasAttachPtr.push_back(
false);
7536 mapData.Mappers.push_back(
nullptr);
7538 mapData.Names.push_back(LLVM::createMappingInformation(
7540 mapData.DevicePointers.push_back(
7541 isDevicePtr ? llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer
7542 : llvm::OpenMPIRBuilder::DeviceInfoTy::Address);
7543 mapData.IsAMapping.push_back(
false);
7544 mapData.IsAMember.push_back(checkIsAMember(hasDevAddrOperands, mapOp));
7549 auto *res = llvm::find(mapData.MapClause, memberOp);
7550 assert(res != mapData.MapClause.end() &&
7551 "MapInfoOp for member not found in MapData, cannot return index");
7552 return std::distance(mapData.MapClause.begin(), res);
7556 omp::MapInfoOp mapInfo,
bool first =
true) {
7557 ArrayAttr indexAttr = mapInfo.getMembersIndexAttr();
7567 auto memberIndicesA = cast<ArrayAttr>(indexAttr[a]);
7568 auto memberIndicesB = cast<ArrayAttr>(indexAttr[b]);
7570 for (auto it : llvm::zip(memberIndicesA, memberIndicesB)) {
7571 int64_t aIndex = mlir::cast<IntegerAttr>(std::get<0>(it)).getInt();
7572 int64_t bIndex = mlir::cast<IntegerAttr>(std::get<1>(it)).getInt();
7574 if (aIndex == bIndex)
7577 if (aIndex < bIndex)
7580 if (aIndex > bIndex)
7587 bool memberAParent = memberIndicesA.size() < memberIndicesB.size();
7589 occludedChildren.push_back(
b);
7591 occludedChildren.push_back(a);
7592 return memberAParent;
7595 for (
auto v : occludedChildren)
7602 ArrayAttr indexAttr = mapInfo.getMembersIndexAttr();
7604 if (indexAttr.size() == 1)
7605 return cast<omp::MapInfoOp>(mapInfo.getMembers()[0].getDefiningOp());
7609 return llvm::cast<omp::MapInfoOp>(
7610 mapInfo.getMembers()[
indices.front()].getDefiningOp());
7633static std::vector<llvm::Value *>
7635 llvm::IRBuilderBase &builder,
bool isArrayTy,
7637 std::vector<llvm::Value *> idx;
7648 idx.push_back(builder.getInt64(0));
7649 for (
int i = bounds.size() - 1; i >= 0; --i) {
7650 if (
auto boundOp = dyn_cast_if_present<omp::MapBoundsOp>(
7651 bounds[i].getDefiningOp())) {
7652 idx.push_back(moduleTranslation.
lookupValue(boundOp.getLowerBound()));
7670 for (
int i = bounds.size() - 1; i >= 0; --i) {
7671 if (
auto boundOp = dyn_cast_if_present<omp::MapBoundsOp>(
7672 bounds[i].getDefiningOp())) {
7673 if (i == ((
int)bounds.size() - 1))
7675 moduleTranslation.
lookupValue(boundOp.getLowerBound()));
7677 idx.back() = builder.CreateAdd(
7678 builder.CreateMul(idx.back(), moduleTranslation.
lookupValue(
7679 boundOp.getExtent())),
7680 moduleTranslation.
lookupValue(boundOp.getLowerBound()));
7689 llvm::transform(values, std::back_inserter(ints), [](
Attribute value) {
7690 return cast<IntegerAttr>(value).getInt();
7698 omp::MapInfoOp parentOp) {
7700 if (parentOp.getMembers().empty())
7704 if (parentOp.getMembers().size() == 1) {
7705 overlapMapDataIdxs.push_back(0);
7709 ArrayAttr indexAttr = parentOp.getMembersIndexAttr();
7710 size_t numMembers = indexAttr.size();
7714 for (
auto [i, indicesAttr] : llvm::enumerate(indexAttr))
7715 getAsIntegers(cast<ArrayAttr>(indicesAttr), memberIndices[i]);
7721 llvm::SmallDenseSet<size_t> skipIndices;
7722 for (
size_t i = 0; i < numMembers; ++i) {
7723 const auto &iIndices = memberIndices[i];
7724 for (
size_t j = 0;
j < numMembers; ++
j) {
7727 const auto &jIndices = memberIndices[
j];
7729 if (jIndices.size() < iIndices.size() &&
7730 std::equal(jIndices.begin(), jIndices.end(), iIndices.begin())) {
7731 skipIndices.insert(i);
7738 for (
size_t i = 0; i < numMembers; ++i)
7739 if (!skipIndices.contains(i))
7740 overlapMapDataIdxs.push_back(i);
7754 llvm::OpenMPIRBuilder &ompBuilder, MapInfoData &mapData,
7755 size_t mapDataIdx, MapInfosTy &combinedInfo,
7756 TargetDirectiveEnumTy targetDirective,
7757 llvm::omp::OpenMPOffloadMappingFlags memberOfFlag =
7758 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE,
7759 bool isTargetParam =
true,
int mapDataParentIdx = -1) {
7760 auto mapFlag = mapData.Types[mapDataIdx];
7761 auto mapInfoOp = llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIdx]);
7765 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH) ==
7766 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
7772 if (isTargetParam &&
7773 (targetDirective == TargetDirectiveEnumTy::Target &&
7774 !mapData.IsDeclareTarget[mapDataIdx]) &&
7776 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7778 if (mapInfoOp.getMapCaptureType() == omp::VariableCaptureKind::ByCopy &&
7780 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL;
7789 if (memberOfFlag != llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE) {
7790 if (!isPtrTy && !isAttachMap)
7791 ompBuilder.setCorrectMemberOfFlag(mapFlag, memberOfFlag);
7798 mapFlag &=
~llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
7808 if (isPtrTy && !isAttachMap && mapData.IsDeclareTarget[mapDataIdx])
7809 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
7818 !bitEnumContainsAll(mapInfoOp.getMapType(),
7819 omp::ClauseMapFlags::ref_ptr) &&
7820 bitEnumContainsAll(mapInfoOp.getMapType(), omp::ClauseMapFlags::ref_ptee);
7821 bool isRefPtrPtee = bitEnumContainsAll(mapInfoOp.getMapType(),
7822 omp::ClauseMapFlags::ref_ptr |
7823 omp::ClauseMapFlags::ref_ptee);
7825 if (!mapInfoOp->getParentOfType<omp::DeclareMapperOp>() &&
7826 mapDataParentIdx >= 0 && !(isRefPtee || (isRefPtrPtee && isPtrTy))) {
7827 combinedInfo.BasePointers.emplace_back(
7828 mapData.BasePointers[mapDataParentIdx]);
7830 combinedInfo.BasePointers.emplace_back(mapData.BasePointers[mapDataIdx]);
7833 combinedInfo.Pointers.emplace_back(mapData.Pointers[mapDataIdx]);
7834 combinedInfo.DevicePointers.emplace_back(
7835 memberOfFlag != llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE
7836 ? llvm::OpenMPIRBuilder::DeviceInfoTy::None
7837 : mapData.DevicePointers[mapDataIdx]);
7838 combinedInfo.Mappers.emplace_back(mapData.Mappers[mapDataIdx]);
7839 combinedInfo.Names.emplace_back(mapData.Names[mapDataIdx]);
7840 combinedInfo.Types.emplace_back(mapFlag);
7842 combinedInfo.HasAttachPtr.emplace_back(
false);
7843 combinedInfo.Sizes.emplace_back(
7844 isPtrTy ? builder.CreateSelect(
7845 builder.CreateIsNull(mapData.Pointers[mapDataIdx]),
7846 builder.getInt64(0), mapData.Sizes[mapDataIdx])
7847 : mapData.Sizes[mapDataIdx]);
7867 llvm::OpenMPIRBuilder &ompBuilder,
DataLayout &dl, MapInfosTy &combinedInfo,
7868 MapInfoData &mapData, uint64_t mapDataIndex,
7869 llvm::omp::OpenMPOffloadMappingFlags memberOfFlag,
7870 TargetDirectiveEnumTy targetDirective) {
7871 using MapFlags = llvm::omp::OpenMPOffloadMappingFlags;
7872 assert(!ompBuilder.Config.isTargetDevice() &&
7873 "function only supported for host device codegen");
7875 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
7876 auto *parentMapper = mapData.Mappers[mapDataIndex];
7882 MapFlags baseFlag = (targetDirective == TargetDirectiveEnumTy::Target &&
7883 !mapData.IsDeclareTarget[mapDataIndex])
7884 ? MapFlags::OMP_MAP_TARGET_PARAM
7885 : MapFlags::OMP_MAP_NONE;
7891 MapFlags parentFlags = mapData.Types[mapDataIndex];
7892 MapFlags preserve = MapFlags::OMP_MAP_TO | MapFlags::OMP_MAP_FROM |
7893 MapFlags::OMP_MAP_ALWAYS | MapFlags::OMP_MAP_CLOSE |
7894 MapFlags::OMP_MAP_PRESENT |
7895 MapFlags::OMP_MAP_OMPX_HOLD |
7896 MapFlags::OMP_MAP_IMPLICIT;
7897 baseFlag |= (parentFlags & preserve);
7899 MapFlags parentFlags = mapData.Types[mapDataIndex];
7900 MapFlags preserve = MapFlags::OMP_MAP_TO | MapFlags::OMP_MAP_FROM |
7901 MapFlags::OMP_MAP_PRESENT |
7902 MapFlags::OMP_MAP_RETURN_PARAM |
7903 MapFlags::OMP_MAP_IMPLICIT;
7904 baseFlag |= (parentFlags & preserve);
7907 combinedInfo.Types.emplace_back(baseFlag);
7909 combinedInfo.HasAttachPtr.emplace_back(
false);
7910 combinedInfo.DevicePointers.emplace_back(
7911 mapData.DevicePointers[mapDataIndex]);
7915 combinedInfo.Mappers.emplace_back(
7916 parentMapper && !parentClause.getPartialMap() ? parentMapper :
nullptr);
7918 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder));
7919 combinedInfo.BasePointers.emplace_back(mapData.BasePointers[mapDataIndex]);
7928 llvm::Value *lowAddr, *highAddr;
7929 if (!parentClause.getPartialMap()) {
7930 lowAddr = builder.CreatePointerCast(mapData.Pointers[mapDataIndex],
7931 builder.getPtrTy());
7932 highAddr = builder.CreatePointerCast(
7933 builder.CreateConstGEP1_32(mapData.BaseType[mapDataIndex],
7934 mapData.Pointers[mapDataIndex], 1),
7935 builder.getPtrTy());
7936 combinedInfo.Pointers.emplace_back(mapData.Pointers[mapDataIndex]);
7938 auto mapOp = dyn_cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
7941 lowAddr = builder.CreatePointerCast(mapData.BasePointers[firstMemberIdx],
7942 builder.getPtrTy());
7946 auto lastMemberMapInfo =
7947 cast<omp::MapInfoOp>(mapData.MapClause[lastMemberIdx]);
7956 bool isRefPteeMap = bitEnumContainsAll(lastMemberMapInfo.getMapType(),
7957 omp::ClauseMapFlags::ref_ptee) &&
7958 !bitEnumContainsAll(lastMemberMapInfo.getMapType(),
7959 omp::ClauseMapFlags::ref_ptr);
7960 llvm::Type *castType = mapData.BaseType[lastMemberIdx];
7963 moduleTranslation.
convertType(lastMemberMapInfo.getVarPtrType());
7964 highAddr = builder.CreatePointerCast(
7965 builder.CreateGEP(castType, mapData.BasePointers[lastMemberIdx],
7966 builder.getInt64(1)),
7967 builder.getPtrTy());
7968 combinedInfo.Pointers.emplace_back(mapData.BasePointers[firstMemberIdx]);
7971 llvm::Value *size = builder.CreateIntCast(
7972 builder.CreatePtrDiff(builder.getInt8Ty(), highAddr, lowAddr),
7973 builder.getInt64Ty(),
7975 combinedInfo.Sizes.push_back(size);
7983 if (!parentClause.getPartialMap()) {
7988 MapFlags mapFlag = mapData.Types[mapDataIndex];
7989 bool hasMapClose = (MapFlags(mapFlag) & MapFlags::OMP_MAP_CLOSE) ==
7990 MapFlags::OMP_MAP_CLOSE;
7991 ompBuilder.setCorrectMemberOfFlag(mapFlag, memberOfFlag);
8007 if (targetDirective == TargetDirectiveEnumTy::TargetUpdate || hasMapClose ||
8008 overlapIdxs.size() == 1) {
8009 combinedInfo.Types.emplace_back(mapFlag);
8011 combinedInfo.HasAttachPtr.emplace_back(
false);
8012 combinedInfo.DevicePointers.emplace_back(
8013 mapData.DevicePointers[mapDataIndex]);
8015 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder));
8016 combinedInfo.BasePointers.emplace_back(
8017 mapData.BasePointers[mapDataIndex]);
8018 combinedInfo.Pointers.emplace_back(mapData.Pointers[mapDataIndex]);
8019 combinedInfo.Sizes.emplace_back(mapData.Sizes[mapDataIndex]);
8020 combinedInfo.Mappers.emplace_back(
nullptr);
8026 lowAddr = builder.CreatePointerCast(mapData.Pointers[mapDataIndex],
8027 builder.getPtrTy());
8028 highAddr = builder.CreatePointerCast(
8029 builder.CreateConstGEP1_32(mapData.BaseType[mapDataIndex],
8030 mapData.Pointers[mapDataIndex], 1),
8031 builder.getPtrTy());
8038 mapFlag &=
~llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
8045 for (
auto v : overlapIdxs) {
8048 cast<omp::MapInfoOp>(parentClause.getMembers()[v].getDefiningOp()));
8050 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataOverlapIdx]));
8051 combinedInfo.Types.emplace_back(mapFlag);
8053 combinedInfo.HasAttachPtr.emplace_back(
false);
8054 combinedInfo.DevicePointers.emplace_back(
8055 llvm::OpenMPIRBuilder::DeviceInfoTy::None);
8057 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder));
8058 combinedInfo.BasePointers.emplace_back(
8059 mapData.BasePointers[mapDataIndex]);
8060 combinedInfo.Mappers.emplace_back(
nullptr);
8061 combinedInfo.Pointers.emplace_back(lowAddr);
8062 auto sizeCalc = builder.CreateIntCast(
8063 builder.CreatePtrDiff(builder.getInt8Ty(),
8064 mapData.OriginalValue[mapDataOverlapIdx],
8066 builder.getInt64Ty(),
true);
8071 auto sizeSel = builder.CreateSelect(
8072 builder.CreateICmpNE(builder.getInt64(0), sizeCalc), sizeCalc,
8073 isPtrMap ? llvm::ConstantExpr::getSizeOf(builder.getPtrTy())
8074 : mapData.Sizes[mapDataOverlapIdx]);
8075 combinedInfo.Sizes.emplace_back(sizeSel);
8076 lowAddr = builder.CreateConstGEP1_32(
8077 isPtrMap ? builder.getPtrTy() : mapData.BaseType[mapDataOverlapIdx],
8078 mapData.BasePointers[mapDataOverlapIdx], 1);
8081 combinedInfo.Types.emplace_back(mapFlag);
8083 combinedInfo.HasAttachPtr.emplace_back(
false);
8084 combinedInfo.DevicePointers.emplace_back(
8085 llvm::OpenMPIRBuilder::DeviceInfoTy::None);
8087 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder));
8088 combinedInfo.BasePointers.emplace_back(
8089 mapData.BasePointers[mapDataIndex]);
8090 combinedInfo.Mappers.emplace_back(
nullptr);
8091 combinedInfo.Pointers.emplace_back(lowAddr);
8092 combinedInfo.Sizes.emplace_back(builder.CreateIntCast(
8093 builder.CreatePtrDiff(builder.getInt8Ty(), highAddr, lowAddr),
8094 builder.getInt64Ty(),
true));
8100 llvm::IRBuilderBase &builder,
8101 llvm::OpenMPIRBuilder &ompBuilder,
8103 MapInfoData &mapData, uint64_t mapDataIndex,
8104 TargetDirectiveEnumTy targetDirective) {
8105 assert(!ompBuilder.Config.isTargetDevice() &&
8106 "function only supported for host device codegen");
8109 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
8114 if (parentClause.getMembers().size() == 1 && parentClause.getPartialMap()) {
8115 auto memberClause = llvm::cast<omp::MapInfoOp>(
8116 parentClause.getMembers()[0].getDefiningOp());
8129 builder, ompBuilder, mapData, memberDataIdx, combinedInfo,
8131 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE,
8132 true, mapDataIndex);
8136 auto collectMapInfoIdxs =
8139 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
8141 for (
auto member : parentClause.getMembers())
8143 mapData, llvm::cast<omp::MapInfoOp>(member.getDefiningOp())));
8147 collectMapInfoIdxs(mapInfoIdx);
8149 llvm::omp::OpenMPOffloadMappingFlags memberOfFlag =
8150 ompBuilder.getMemberOfFlag(combinedInfo.Types.size());
8160 bool parentIsPrivatizeableAttach =
8162 for (
auto [i, idx] : llvm::enumerate(mapInfoIdx)) {
8163 bool emitParentMap = i == 0 && !parentIsPrivatizeableAttach;
8164 if (emitParentMap) {
8166 combinedInfo, mapData, idx, memberOfFlag,
8170 builder, ompBuilder, mapData, idx, combinedInfo, targetDirective,
8171 parentIsPrivatizeableAttach
8172 ? llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE
8174 false, mapDataIndex);
8186 llvm::IRBuilderBase &builder) {
8188 "function only supported for host device codegen");
8189 for (
size_t i = 0; i < mapData.MapClause.size(); ++i) {
8190 auto mapOp = cast<omp::MapInfoOp>(mapData.MapClause[i]);
8193 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH) ==
8194 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
8199 if (!mapData.IsDeclareTarget[i] ||
8200 (mapData.IsDeclareTarget[i] && isAttachMap)) {
8201 omp::VariableCaptureKind captureKind = mapOp.getMapCaptureType();
8211 switch (captureKind) {
8212 case omp::VariableCaptureKind::ByRef: {
8213 llvm::Value *newV = mapData.Pointers[i];
8215 moduleTranslation, builder, mapData.BaseType[i]->isArrayTy(),
8218 newV = builder.CreateLoad(builder.getPtrTy(), newV);
8220 if (!offsetIdx.empty())
8221 newV = builder.CreateInBoundsGEP(mapData.BaseType[i], newV, offsetIdx,
8223 mapData.Pointers[i] = newV;
8225 case omp::VariableCaptureKind::ByCopy: {
8226 llvm::Type *type = mapData.BaseType[i];
8228 if (mapData.Pointers[i]->getType()->isPointerTy())
8229 newV = builder.CreateLoad(type, mapData.Pointers[i]);
8231 newV = mapData.Pointers[i];
8234 auto curInsert = builder.saveIP();
8235 llvm::DebugLoc DbgLoc = builder.getCurrentDebugLocation();
8237 auto *memTempAlloc =
8238 builder.CreateAlloca(builder.getPtrTy(),
nullptr,
".casted");
8239 builder.SetCurrentDebugLocation(DbgLoc);
8240 builder.restoreIP(curInsert);
8242 builder.CreateStore(newV, memTempAlloc);
8243 newV = builder.CreateLoad(builder.getPtrTy(), memTempAlloc);
8246 mapData.Pointers[i] = newV;
8247 mapData.BasePointers[i] = newV;
8249 case omp::VariableCaptureKind::This:
8250 case omp::VariableCaptureKind::VLAType:
8251 mapData.MapClause[i]->emitOpError(
"Unhandled capture kind");
8262 MapInfoData &mapData,
8263 TargetDirectiveEnumTy targetDirective) {
8265 "function only supported for host device codegen");
8286 for (
size_t i = 0; i < mapData.MapClause.size(); ++i) {
8287 if (mapData.IsAMember[i])
8290 auto mapInfoOp = dyn_cast<omp::MapInfoOp>(mapData.MapClause[i]);
8291 if (!mapInfoOp.getMembers().empty()) {
8293 combinedInfo, mapData, i, targetDirective);
8302static llvm::Expected<llvm::Function *>
8304 LLVM::ModuleTranslation &moduleTranslation,
8305 llvm::StringRef mapperFuncName,
8306 TargetDirectiveEnumTy targetDirective);
8308static llvm::Expected<llvm::Function *>
8311 TargetDirectiveEnumTy targetDirective) {
8313 "function only supported for host device codegen");
8314 auto declMapperOp = cast<omp::DeclareMapperOp>(op);
8315 std::string mapperFuncName =
8317 {
"omp_mapper", declMapperOp.getSymName()});
8319 if (
auto *lookupFunc = moduleTranslation.
lookupFunction(mapperFuncName))
8327 if (llvm::Function *existingFunc =
8328 moduleTranslation.
getLLVMModule()->getFunction(mapperFuncName)) {
8329 moduleTranslation.
mapFunction(mapperFuncName, existingFunc);
8330 return existingFunc;
8334 mapperFuncName, targetDirective);
8337static llvm::Expected<llvm::Function *>
8340 llvm::StringRef mapperFuncName,
8341 TargetDirectiveEnumTy targetDirective) {
8343 "function only supported for host device codegen");
8344 auto declMapperOp = cast<omp::DeclareMapperOp>(op);
8345 auto declMapperInfoOp = declMapperOp.getDeclareMapperInfo();
8347 return llvm::make_error<PreviouslyReportedError>();
8351 llvm::Type *varType = moduleTranslation.
convertType(declMapperOp.getType());
8354 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
8357 MapInfosTy combinedInfo;
8359 [&](InsertPointTy codeGenIP, llvm::Value *ptrPHI,
8360 llvm::Value *unused2) -> llvm::OpenMPIRBuilder::MapInfosOrErrorTy {
8361 builder.restoreIP(codeGenIP);
8362 moduleTranslation.
mapValue(declMapperOp.getSymVal(), ptrPHI);
8363 moduleTranslation.
mapBlock(&declMapperOp.getRegion().front(),
8364 builder.GetInsertBlock());
8365 if (failed(moduleTranslation.
convertBlock(declMapperOp.getRegion().front(),
8368 return llvm::make_error<PreviouslyReportedError>();
8369 MapInfoData mapData;
8372 genMapInfos(builder, moduleTranslation, dl, combinedInfo, mapData,
8378 return combinedInfo;
8382 if (!combinedInfo.Mappers[i])
8385 moduleTranslation, targetDirective);
8389 genMapInfoCB, varType, mapperFuncName, customMapperCB,
8392 return newFn.takeError();
8393 if ([[maybe_unused]] llvm::Function *mappedFunc =
8395 assert(mappedFunc == *newFn &&
8396 "mapper function mapping disagrees with emitted function");
8398 moduleTranslation.
mapFunction(mapperFuncName, *newFn);
8406 llvm::Value *ifCond =
nullptr;
8407 llvm::Value *deviceID = builder.getInt64(llvm::omp::OMP_DEVICEID_UNDEF);
8411 llvm::omp::RuntimeFunction RTLFn;
8413 TargetDirectiveEnumTy targetDirective = getTargetDirectiveEnumTyFromOp(op);
8416 llvm::OpenMPIRBuilder::TargetDataInfo info(
8420 if (ompBuilder->Config.isTargetDevice())
8421 return op->
emitOpError() <<
"not allowed in a target device";
8423 bool isOffloadEntry = !ompBuilder->Config.TargetTriples.empty();
8425 auto getDeviceID = [&](
mlir::Value dev) -> llvm::Value * {
8426 llvm::Value *v = moduleTranslation.
lookupValue(dev);
8427 return builder.CreateIntCast(v, builder.getInt64Ty(),
true);
8432 .Case([&](omp::TargetDataOp dataOp) {
8436 if (
auto ifVar = dataOp.getIfExpr())
8440 deviceID = getDeviceID(devId);
8442 mapVars = dataOp.getMapVars();
8443 useDevicePtrVars = dataOp.getUseDevicePtrVars();
8444 useDeviceAddrVars = dataOp.getUseDeviceAddrVars();
8447 .Case([&](omp::TargetEnterDataOp enterDataOp) -> LogicalResult {
8451 if (
auto ifVar = enterDataOp.getIfExpr())
8455 deviceID = getDeviceID(devId);
8458 enterDataOp.getNowait()
8459 ? llvm::omp::OMPRTL___tgt_target_data_begin_nowait_mapper
8460 : llvm::omp::OMPRTL___tgt_target_data_begin_mapper;
8461 mapVars = enterDataOp.getMapVars();
8462 info.HasNoWait = enterDataOp.getNowait();
8465 .Case([&](omp::TargetExitDataOp exitDataOp) -> LogicalResult {
8469 if (
auto ifVar = exitDataOp.getIfExpr())
8473 deviceID = getDeviceID(devId);
8475 RTLFn = exitDataOp.getNowait()
8476 ? llvm::omp::OMPRTL___tgt_target_data_end_nowait_mapper
8477 : llvm::omp::OMPRTL___tgt_target_data_end_mapper;
8478 mapVars = exitDataOp.getMapVars();
8479 info.HasNoWait = exitDataOp.getNowait();
8482 .Case([&](omp::TargetUpdateOp updateDataOp) -> LogicalResult {
8486 if (
auto ifVar = updateDataOp.getIfExpr())
8490 deviceID = getDeviceID(devId);
8493 updateDataOp.getNowait()
8494 ? llvm::omp::OMPRTL___tgt_target_data_update_nowait_mapper
8495 : llvm::omp::OMPRTL___tgt_target_data_update_mapper;
8496 mapVars = updateDataOp.getMapVars();
8497 info.HasNoWait = updateDataOp.getNowait();
8500 .DefaultUnreachable(
"unexpected operation");
8505 if (!isOffloadEntry)
8506 ifCond = builder.getFalse();
8508 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
8509 MapInfoData mapData;
8511 builder, useDevicePtrVars, useDeviceAddrVars);
8514 MapInfosTy combinedInfo;
8515 auto genMapInfoCB = [&](InsertPointTy codeGenIP) -> MapInfosTy & {
8516 builder.restoreIP(codeGenIP);
8517 genMapInfos(builder, moduleTranslation, DL, combinedInfo, mapData,
8519 return combinedInfo;
8525 [&moduleTranslation](
8526 llvm::OpenMPIRBuilder::DeviceInfoTy type,
8530 for (
auto [arg, useDevVar] :
8531 llvm::zip_equal(blockArgs, useDeviceVars)) {
8533 auto getMapBasePtr = [](omp::MapInfoOp mapInfoOp) {
8534 return mapInfoOp.getVarPtrPtr() ? mapInfoOp.getVarPtrPtr()
8535 : mapInfoOp.getVarPtr();
8538 auto useDevMap = cast<omp::MapInfoOp>(useDevVar.getDefiningOp());
8539 for (
auto [mapClause, devicePointer, basePointer] : llvm::zip_equal(
8540 mapInfoData.MapClause, mapInfoData.DevicePointers,
8541 mapInfoData.BasePointers)) {
8542 auto mapOp = cast<omp::MapInfoOp>(mapClause);
8543 if (getMapBasePtr(mapOp) != getMapBasePtr(useDevMap) ||
8544 devicePointer != type)
8547 if (llvm::Value *devPtrInfoMap =
8548 mapper ? mapper(basePointer) : basePointer) {
8549 moduleTranslation.
mapValue(arg, devPtrInfoMap);
8556 using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy;
8557 auto bodyGenCB = [&](InsertPointTy codeGenIP, BodyGenTy bodyGenType)
8558 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
8561 builder.restoreIP(codeGenIP);
8562 assert(isa<omp::TargetDataOp>(op) &&
8563 "BodyGen requested for non TargetDataOp");
8564 auto blockArgIface = cast<omp::BlockArgOpenMPOpInterface>(op);
8565 Region ®ion = cast<omp::TargetDataOp>(op).getRegion();
8566 switch (bodyGenType) {
8567 case BodyGenTy::Priv:
8569 if (!info.DevicePtrInfoMap.empty()) {
8570 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Address,
8571 blockArgIface.getUseDeviceAddrBlockArgs(),
8572 useDeviceAddrVars, mapData,
8573 [&](llvm::Value *basePointer) -> llvm::Value * {
8574 if (!info.DevicePtrInfoMap[basePointer].second)
8576 return builder.CreateLoad(
8578 info.DevicePtrInfoMap[basePointer].second);
8580 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer,
8581 blockArgIface.getUseDevicePtrBlockArgs(), useDevicePtrVars,
8582 mapData, [&](llvm::Value *basePointer) {
8583 return info.DevicePtrInfoMap[basePointer].second;
8587 moduleTranslation)))
8588 return llvm::make_error<PreviouslyReportedError>();
8591 case BodyGenTy::DupNoPriv:
8592 if (info.DevicePtrInfoMap.empty()) {
8595 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Address,
8596 blockArgIface.getUseDeviceAddrBlockArgs(),
8597 useDeviceAddrVars, mapData);
8598 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer,
8599 blockArgIface.getUseDevicePtrBlockArgs(), useDevicePtrVars,
8603 case BodyGenTy::NoPriv:
8605 if (info.DevicePtrInfoMap.empty()) {
8607 moduleTranslation)))
8608 return llvm::make_error<PreviouslyReportedError>();
8612 return builder.saveIP();
8615 auto customMapperCB =
8617 if (!combinedInfo.Mappers[i])
8619 info.HasMapper =
true;
8621 moduleTranslation, targetDirective);
8624 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
8626 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
8628 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP = [&]() {
8629 if (isa<omp::TargetDataOp>(op))
8630 return ompBuilder->createTargetData(ompLoc, allocaIP, builder.saveIP(),
8631 deallocBlocks, deviceID, ifCond, info,
8632 genMapInfoCB, customMapperCB,
8635 return ompBuilder->createTargetData(ompLoc, allocaIP, builder.saveIP(),
8636 deallocBlocks, deviceID, ifCond, info,
8637 genMapInfoCB, customMapperCB, &RTLFn);
8643 builder.restoreIP(*afterIP);
8651 auto distributeOp = cast<omp::DistributeOp>(opInst);
8658 bool doDistributeReduction =
8662 unsigned numReductionVars = teamsOp ? teamsOp.getNumReductionVars() : 0;
8667 if (doDistributeReduction) {
8668 isByRef =
getIsByRef(teamsOp.getReductionByref());
8669 assert(isByRef.size() == teamsOp.getNumReductionVars());
8672 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
8676 llvm::cast<omp::BlockArgOpenMPOpInterface>(*teamsOp)
8677 .getReductionBlockArgs();
8680 teamsOp, reductionArgs, builder, moduleTranslation, allocaIP,
8681 reductionDecls, privateReductionVariables, reductionVariableMap,
8686 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
8688 [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
8693 moduleTranslation, allocaIP, deallocBlocks);
8696 builder.restoreIP(codeGenIP);
8700 distributeOp, builder, moduleTranslation, privVarsInfo, allocaIP);
8702 return llvm::make_error<PreviouslyReportedError>();
8707 return llvm::make_error<PreviouslyReportedError>();
8710 distributeOp, builder, moduleTranslation, privVarsInfo.
mlirVars,
8712 distributeOp.getPrivateNeedsBarrier())))
8713 return llvm::make_error<PreviouslyReportedError>();
8716 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
8719 builder, moduleTranslation);
8721 return regionBlock.takeError();
8722 builder.SetInsertPoint(*regionBlock, (*regionBlock)->begin());
8727 if (!isa_and_present<omp::WsloopOp>(distributeOp.getNestedWrapper())) {
8730 bool hasDistSchedule = distributeOp.getDistScheduleStatic();
8731 auto schedule = hasDistSchedule ? omp::ClauseScheduleKind::Distribute
8732 : omp::ClauseScheduleKind::Static;
8734 bool isOrdered = hasDistSchedule;
8735 std::optional<omp::ScheduleModifier> scheduleMod;
8736 bool isSimd =
false;
8737 llvm::omp::WorksharingLoopType workshareLoopType =
8738 llvm::omp::WorksharingLoopType::DistributeStaticLoop;
8739 bool loopNeedsBarrier =
false;
8740 llvm::Value *chunk = moduleTranslation.
lookupValue(
8741 distributeOp.getDistScheduleChunkSize());
8742 llvm::CanonicalLoopInfo *loopInfo =
8744 llvm::OpenMPIRBuilder::InsertPointOrErrorTy wsloopIP =
8745 ompBuilder->applyWorkshareLoop(
8746 ompLoc.DL, loopInfo, allocaIP, loopNeedsBarrier,
8747 convertToScheduleKind(schedule), chunk, isSimd,
8748 scheduleMod == omp::ScheduleModifier::monotonic,
8749 scheduleMod == omp::ScheduleModifier::nonmonotonic, isOrdered,
8750 workshareLoopType,
false, hasDistSchedule, chunk);
8753 return wsloopIP.takeError();
8756 distributeOp.getLoc(), privVarsInfo)))
8757 return llvm::make_error<PreviouslyReportedError>();
8759 return llvm::Error::success();
8763 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
8765 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
8766 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
8767 ompBuilder->createDistribute(ompLoc, allocaIP, deallocBlocks, bodyGenCB);
8772 builder.restoreIP(*afterIP);
8774 if (doDistributeReduction) {
8777 teamsOp, builder, moduleTranslation, allocaIP, reductionDecls,
8778 privateReductionVariables, isByRef,
8790 auto offloadMod = dyn_cast<omp::OffloadModuleInterface>(op);
8792 return op->
emitOpError() <<
"omp flags attached to non offload module op";
8796 if (offloadMod.getIsTargetDevice())
8797 ompBuilder->M.addModuleFlag(llvm::Module::Max,
"openmp-device",
8798 attribute.getOpenmpDeviceVersion());
8801 if (!offloadMod.getIsGPU())
8804 if (attribute.getNoGpuLib())
8807 ompBuilder->createGlobalFlag(attribute.getDebugKind(),
8808 "__omp_rtl_debug_kind");
8809 ompBuilder->createGlobalFlag(attribute.getAssumeTeamsOversubscription(),
8810 "__omp_rtl_assume_teams_oversubscription");
8811 ompBuilder->createGlobalFlag(attribute.getAssumeThreadsOversubscription(),
8812 "__omp_rtl_assume_threads_oversubscription");
8813 ompBuilder->createGlobalFlag(attribute.getAssumeNoThreadState(),
8814 "__omp_rtl_assume_no_thread_state");
8815 ompBuilder->createGlobalFlag(attribute.getAssumeNoNestedParallelism(),
8816 "__omp_rtl_assume_no_nested_parallelism");
8821 omp::TargetOp targetOp,
8822 llvm::OpenMPIRBuilder &ompBuilder,
8823 llvm::vfs::FileSystem &vfs,
8824 llvm::StringRef parentName =
"") {
8825 auto fileLoc = targetOp.getLoc()->findInstanceOf<
FileLineColLoc>();
8826 assert(fileLoc &&
"No file found from location");
8828 auto fileInfoCallBack = [&fileLoc]() {
8829 return std::pair<std::string, uint64_t>(
8830 llvm::StringRef(fileLoc.getFilename()), fileLoc.getLine());
8834 ompBuilder.getTargetEntryUniqueInfo(fileInfoCallBack, vfs, parentName);
8877 omp::TargetOp targetOp, MapInfoData &mapData, llvm::Argument &arg,
8878 llvm::Value *input, llvm::Value *&retVal, llvm::IRBuilderBase &builder,
8879 llvm::OpenMPIRBuilder &ompBuilder,
8881 llvm::IRBuilderBase::InsertPoint allocaIP,
8882 llvm::IRBuilderBase::InsertPoint codeGenIP,
8884 assert(ompBuilder.Config.isTargetDevice() &&
8885 "function only supported for target device codegen");
8886 builder.restoreIP(allocaIP);
8888 omp::VariableCaptureKind capture = omp::VariableCaptureKind::ByRef;
8890 ompBuilder.M.getContext());
8891 unsigned alignmentValue = 0;
8894 cast<omp::BlockArgOpenMPOpInterface>(*targetOp).getBlockArgsPairs(
8897 for (
size_t i = 0; i < mapData.MapClause.size(); ++i) {
8898 if (mapData.OriginalValue[i] == input) {
8899 auto mapOp = cast<omp::MapInfoOp>(mapData.MapClause[i]);
8900 capture = mapOp.getMapCaptureType();
8903 mapOp.getVarPtrType(), ompBuilder.M.getDataLayout());
8907 for (
auto &[val, arg] : blockArgsPairs) {
8908 if (mapOp.getResult() == val) {
8913 assert(mlirArg &&
"expected to find entry block argument for map clause");
8918 unsigned int allocaAS = ompBuilder.M.getDataLayout().getAllocaAddrSpace();
8919 unsigned int defaultAS =
8920 ompBuilder.M.getDataLayout().getProgramAddressSpace();
8923 llvm::Value *v =
nullptr;
8931 builder.SetInsertPoint(codeGenIP.getBlock()->getFirstInsertionPt());
8932 v = ompBuilder.createOMPAllocShared(builder, arg.getType());
8936 llvm::IRBuilderBase::InsertPointGuard guard(builder);
8937 for (
auto deallocIP : deallocIPs) {
8938 builder.SetInsertPoint(deallocIP.getBlock(), deallocIP.getPoint());
8939 ompBuilder.createOMPFreeShared(builder, v, arg.getType());
8943 v = builder.CreateAlloca(arg.getType(), allocaAS);
8945 if (allocaAS != defaultAS && arg.getType()->isPointerTy())
8946 v = builder.CreateAddrSpaceCast(v, builder.getPtrTy(defaultAS));
8949 builder.CreateStore(&arg, v);
8951 builder.restoreIP(codeGenIP);
8954 case omp::VariableCaptureKind::ByCopy: {
8958 case omp::VariableCaptureKind::ByRef: {
8959 llvm::LoadInst *loadInst = builder.CreateAlignedLoad(
8961 ompBuilder.M.getDataLayout().getPrefTypeAlign(v->getType()));
8976 if (v->getType()->isPointerTy() && alignmentValue) {
8977 llvm::MDBuilder MDB(builder.getContext());
8978 loadInst->setMetadata(
8979 llvm::LLVMContext::MD_align,
8980 llvm::MDNode::get(builder.getContext(),
8981 MDB.createConstant(llvm::ConstantInt::get(
8982 llvm::Type::getInt64Ty(builder.getContext()),
8989 case omp::VariableCaptureKind::This:
8990 case omp::VariableCaptureKind::VLAType:
8993 assert(
false &&
"Currently unsupported capture kind");
8997 return builder.saveIP();
9014 auto blockArgIface = llvm::cast<omp::BlockArgOpenMPOpInterface>(*targetOp);
9015 for (
auto item : llvm::zip_equal(targetOp.getHostEvalVars(),
9016 blockArgIface.getHostEvalBlockArgs())) {
9017 Value hostEvalVar = std::get<0>(item), blockArg = std::get<1>(item);
9021 .Case([&](omp::TeamsOp teamsOp) {
9022 if (teamsOp.getNumTeamsLower() == blockArg)
9023 numTeamsLower = hostEvalVar;
9024 else if (llvm::is_contained(teamsOp.getNumTeamsUpperVars(),
9026 numTeamsUpper = hostEvalVar;
9027 else if (!teamsOp.getThreadLimitVars().empty() &&
9028 teamsOp.getThreadLimit(0) == blockArg)
9029 threadLimit = hostEvalVar;
9031 llvm_unreachable(
"unsupported host_eval use");
9033 .Case([&](omp::ParallelOp parallelOp) {
9034 if (!parallelOp.getNumThreadsVars().empty() &&
9035 parallelOp.getNumThreads(0) == blockArg)
9036 numThreads = hostEvalVar;
9038 llvm_unreachable(
"unsupported host_eval use");
9040 .Case([&](omp::LoopNestOp loopOp) {
9041 auto processBounds =
9045 for (
auto [i, lb] : llvm::enumerate(opBounds)) {
9046 if (lb == blockArg) {
9049 (*outBounds)[i] = hostEvalVar;
9055 processBounds(loopOp.getLoopLowerBounds(), lowerBounds);
9056 found = processBounds(loopOp.getLoopUpperBounds(), upperBounds) ||
9058 found = processBounds(loopOp.getLoopSteps(), steps) || found;
9060 assert(found &&
"unsupported host_eval use");
9062 .DefaultUnreachable(
"unsupported host_eval use");
9074template <
typename OpTy>
9079 if (OpTy casted = dyn_cast<OpTy>(op))
9082 if (immediateParent)
9083 return dyn_cast_if_present<OpTy>(op->
getParentOp());
9092 return std::nullopt;
9095 if (
auto constAttr = dyn_cast<IntegerAttr>(constOp.getValue()))
9096 return constAttr.getInt();
9098 return std::nullopt;
9103 uint64_t sizeInBytes = sizeInBits / 8;
9107template <
typename OpTy>
9109 if (op.getNumReductionVars() > 0) {
9114 members.reserve(reductions.size());
9115 for (omp::DeclareReductionOp &red : reductions) {
9119 if (red.getByrefElementType())
9120 members.push_back(*red.getByrefElementType());
9122 members.push_back(red.getType());
9125 auto structType = mlir::LLVM::LLVMStructType::getLiteral(
9141 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &attrs,
9142 bool isTargetDevice,
bool isGPU) {
9145 Value numThreads, numTeamsLower, numTeamsUpper, threadLimit;
9146 if (!isTargetDevice) {
9154 numTeamsLower = teamsOp.getNumTeamsLower();
9156 if (!teamsOp.getNumTeamsUpperVars().empty())
9157 numTeamsUpper = teamsOp.getNumTeams(0);
9158 if (!teamsOp.getThreadLimitVars().empty())
9159 threadLimit = teamsOp.getThreadLimit(0);
9163 if (!parallelOp.getNumThreadsVars().empty())
9164 numThreads = parallelOp.getNumThreads(0);
9170 int32_t minTeamsVal = 1, maxTeamsVal = -1;
9174 if (numTeamsUpper) {
9176 minTeamsVal = maxTeamsVal = *val;
9178 minTeamsVal = maxTeamsVal = 0;
9184 minTeamsVal = maxTeamsVal = 1;
9186 minTeamsVal = maxTeamsVal = -1;
9191 auto setMaxValueFromClause = [](
Value clauseValue, int32_t &
result) {
9205 int32_t targetThreadLimitVal = -1, teamsThreadLimitVal = -1;
9206 if (!targetOp.getThreadLimitVars().empty())
9207 setMaxValueFromClause(targetOp.getThreadLimit(0), targetThreadLimitVal);
9208 setMaxValueFromClause(threadLimit, teamsThreadLimitVal);
9211 int32_t maxThreadsVal = -1;
9213 setMaxValueFromClause(numThreads, maxThreadsVal);
9221 int32_t combinedMaxThreadsVal = targetThreadLimitVal;
9222 if (combinedMaxThreadsVal < 0 ||
9223 (teamsThreadLimitVal >= 0 && teamsThreadLimitVal < combinedMaxThreadsVal))
9224 combinedMaxThreadsVal = teamsThreadLimitVal;
9226 if (combinedMaxThreadsVal < 0 ||
9227 (maxThreadsVal >= 0 && maxThreadsVal < combinedMaxThreadsVal))
9228 combinedMaxThreadsVal = maxThreadsVal;
9230 int32_t reductionDataSize = 0;
9231 if (isGPU && capturedOp) {
9238 omp::TargetExecMode execMode = targetOp.getKernelType();
9240 case omp::TargetExecMode::bare:
9241 attrs.ExecFlags = llvm::omp::OMP_TGT_EXEC_MODE_BARE;
9243 case omp::TargetExecMode::generic:
9244 attrs.ExecFlags = llvm::omp::OMP_TGT_EXEC_MODE_GENERIC;
9246 case omp::TargetExecMode::spmd:
9247 attrs.ExecFlags = llvm::omp::OMP_TGT_EXEC_MODE_SPMD;
9249 case omp::TargetExecMode::spmd_no_loop:
9250 attrs.ExecFlags = llvm::omp::OMP_TGT_EXEC_MODE_SPMD_NO_LOOP;
9253 attrs.MinTeams.front() = minTeamsVal;
9254 attrs.MaxTeams.front() = maxTeamsVal;
9255 attrs.MinThreads.front() = 1;
9256 attrs.MaxThreads.front() = combinedMaxThreadsVal;
9257 attrs.ReductionDataSize = reductionDataSize;
9269 omp::TargetOp targetOp,
Operation *capturedOp,
9270 llvm::OpenMPIRBuilder::TargetKernelRuntimeAttrs &attrs) {
9272 unsigned numLoops = loopOp ? loopOp.getNumLoops() : 0;
9274 Value numThreads, numTeamsLower, numTeamsUpper, teamsThreadLimit;
9278 teamsThreadLimit, &lowerBounds, &upperBounds, &steps);
9281 if (!targetOp.getThreadLimitVars().empty()) {
9282 Value targetThreadLimit = targetOp.getThreadLimit(0);
9283 attrs.TargetThreadLimit.front() =
9291 attrs.MinTeams.front() = builder.CreateSExtOrTrunc(
9292 moduleTranslation.
lookupValue(numTeamsLower), builder.getInt32Ty());
9295 attrs.MaxTeams.front() = builder.CreateSExtOrTrunc(
9296 moduleTranslation.
lookupValue(numTeamsUpper), builder.getInt32Ty());
9298 if (teamsThreadLimit)
9299 attrs.TeamsThreadLimit.front() = builder.CreateSExtOrTrunc(
9300 moduleTranslation.
lookupValue(teamsThreadLimit), builder.getInt32Ty());
9303 attrs.MaxThreads.front() = moduleTranslation.
lookupValue(numThreads);
9305 if (targetOp.hasHostEvalTripCount()) {
9307 attrs.LoopTripCount =
nullptr;
9312 for (
auto [loopLower, loopUpper, loopStep] :
9313 llvm::zip_equal(lowerBounds, upperBounds, steps)) {
9314 llvm::Value *lowerBound = moduleTranslation.
lookupValue(loopLower);
9315 llvm::Value *upperBound = moduleTranslation.
lookupValue(loopUpper);
9316 llvm::Value *step = moduleTranslation.
lookupValue(loopStep);
9318 if (!lowerBound || !upperBound || !step) {
9319 attrs.LoopTripCount =
nullptr;
9323 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
9324 llvm::Value *tripCount = ompBuilder->calculateCanonicalLoopTripCount(
9325 loc, lowerBound, upperBound, step,
true,
9326 loopOp.getLoopInclusive());
9328 if (!attrs.LoopTripCount) {
9329 attrs.LoopTripCount = tripCount;
9334 attrs.LoopTripCount = builder.CreateMul(attrs.LoopTripCount, tripCount,
9339 attrs.DeviceID = builder.getInt64(llvm::omp::OMP_DEVICEID_UNDEF);
9341 attrs.DeviceID = moduleTranslation.
lookupValue(devId);
9343 builder.CreateSExtOrTrunc(attrs.DeviceID, builder.getInt64Ty());
9347static llvm::omp::OMPDynGroupprivateFallbackType
9349 omp::FallbackModifier fb = fallbackAttr ? fallbackAttr.getValue()
9350 : omp::FallbackModifier::default_mem;
9352 case omp::FallbackModifier::abort:
9353 return llvm::omp::OMPDynGroupprivateFallbackType::Abort;
9354 case omp::FallbackModifier::null:
9355 return llvm::omp::OMPDynGroupprivateFallbackType::Null;
9356 case omp::FallbackModifier::default_mem:
9357 return llvm::omp::OMPDynGroupprivateFallbackType::DefaultMem;
9360 llvm_unreachable(
"unexpected dyn_groupprivate fallback type");
9366 auto targetOp = cast<omp::TargetOp>(opInst);
9371 llvm::DebugLoc outlinedFnLoc = builder.getCurrentDebugLocation();
9380 llvm::BasicBlock *parentBB = builder.GetInsertBlock();
9381 assert(parentBB &&
"No insert block is set for the builder");
9382 llvm::Function *parentLLVMFn = parentBB->getParent();
9383 assert(parentLLVMFn &&
"Parent Function must be valid");
9384 if (llvm::DISubprogram *SP = parentLLVMFn->getSubprogram())
9385 builder.SetCurrentDebugLocation(llvm::DILocation::get(
9386 parentLLVMFn->getContext(), outlinedFnLoc.getLine(),
9387 outlinedFnLoc.getCol(), SP, outlinedFnLoc.getInlinedAt()));
9395 llvm::DebugLoc outlinedFnDbgLoc;
9396 if (outlinedFnLoc && parentLLVMFn->getSubprogram())
9397 outlinedFnDbgLoc = outlinedFnLoc;
9400 bool isTargetDevice = ompBuilder->Config.isTargetDevice();
9401 bool isGPU = ompBuilder->Config.isGPU();
9404 auto argIface = cast<omp::BlockArgOpenMPOpInterface>(opInst);
9405 auto &targetRegion = targetOp.getRegion();
9422 llvm::Function *llvmOutlinedFn =
nullptr;
9423 TargetDirectiveEnumTy targetDirective =
9424 getTargetDirectiveEnumTyFromOp(&opInst);
9428 bool isOffloadEntry =
9429 isTargetDevice || !ompBuilder->Config.TargetTriples.empty();
9449 if (!targetOp.getInReductionVars().empty() && !isTargetDevice) {
9450 inRedOrigPtrs.reserve(targetOp.getInReductionVars().size());
9451 inRedMapArgIdx.reserve(targetOp.getInReductionVars().size());
9452 for (
Value v : targetOp.getInReductionVars()) {
9457 std::optional<unsigned> matchIdx;
9458 for (
auto [idx, mapV] : llvm::enumerate(targetOp.getMapVars())) {
9459 auto mapInfo = mapV.getDefiningOp<omp::MapInfoOp>();
9460 if (v != mapInfo.getVarPtr())
9463 return targetOp.emitError()
9464 <<
"in_reduction variable on omp.target has multiple matching "
9465 "map_entries entries; the redirect target is ambiguous";
9471 "TargetOp verifier guarantees a matching map_entries entry for "
9472 "each in_reduction variable");
9473 inRedMapArgIdx.push_back(*matchIdx);
9476 inRedOrigPtrs.push_back(moduleTranslation.
lookupValue(v));
9485 if (!targetOp.getPrivateVars().empty() && !targetOp.getMapVars().empty()) {
9487 std::optional<ArrayAttr> privateSyms = targetOp.getPrivateSyms();
9488 std::optional<DenseI64ArrayAttr> privateMapIndices =
9489 targetOp.getPrivateMapsAttr();
9491 for (
auto [privVarIdx, privVarSymPair] :
9492 llvm::enumerate(llvm::zip_equal(privateVars, *privateSyms))) {
9493 auto privVar = std::get<0>(privVarSymPair);
9494 auto privSym = std::get<1>(privVarSymPair);
9496 SymbolRefAttr privatizerName = llvm::cast<SymbolRefAttr>(privSym);
9497 omp::PrivateClauseOp privatizer =
9500 if (!privatizer.needsMap())
9504 targetOp.getMappedValueForPrivateVar(privVarIdx);
9505 assert(mappedValue &&
"Expected to find mapped value for a privatized "
9506 "variable that needs mapping");
9511 auto mapInfoOp = mappedValue.
getDefiningOp<omp::MapInfoOp>();
9512 [[maybe_unused]]
Type varType = mapInfoOp.getVarPtrType();
9516 if (!isa<LLVM::LLVMPointerType>(privVar.getType()))
9518 varType == privVar.getType() &&
9519 "Type of private var doesn't match the type of the mapped value");
9523 mappedPrivateVars.insert(
9525 targetRegion.getArgument(argIface.getMapBlockArgsStart() +
9526 (*privateMapIndices)[privVarIdx])});
9530 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
9531 auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
9533 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
9534 llvm::IRBuilderBase::InsertPointGuard guard(builder);
9535 builder.SetCurrentDebugLocation(llvm::DebugLoc());
9538 llvm::Function *llvmParentFn =
9540 llvmOutlinedFn = codeGenIP.getBlock()->getParent();
9541 assert(llvmParentFn && llvmOutlinedFn &&
9542 "Both parent and outlined functions must exist at this point");
9544 if (outlinedFnLoc && llvmParentFn->getSubprogram())
9545 llvmOutlinedFn->setSubprogram(outlinedFnLoc->getScope()->getSubprogram());
9547 if (
auto attr = llvmParentFn->getFnAttribute(
"target-cpu");
9548 attr.isStringAttribute())
9549 llvmOutlinedFn->addFnAttr(attr);
9551 if (
auto attr = llvmParentFn->getFnAttribute(
"target-features");
9552 attr.isStringAttribute())
9553 llvmOutlinedFn->addFnAttr(attr);
9555 for (
auto [idx, arg] : llvm::enumerate(mapBlockArgs)) {
9561 if (llvm::is_contained(inRedMapArgIdx, idx))
9563 auto mapInfoOp = cast<omp::MapInfoOp>(mapVars[idx].getDefiningOp());
9564 llvm::Value *mapOpValue =
9565 moduleTranslation.
lookupValue(mapInfoOp.getVarPtr());
9566 moduleTranslation.
mapValue(arg, mapOpValue);
9568 for (
auto [arg, mapOp] : llvm::zip_equal(hdaBlockArgs, hdaVars)) {
9569 auto mapInfoOp = cast<omp::MapInfoOp>(mapOp.getDefiningOp());
9570 llvm::Value *mapOpValue =
9571 moduleTranslation.
lookupValue(mapInfoOp.getVarPtr());
9572 moduleTranslation.
mapValue(arg, mapOpValue);
9581 privateVarsInfo, allocaIP, &mappedPrivateVars);
9584 return llvm::make_error<PreviouslyReportedError>();
9586 builder.restoreIP(codeGenIP);
9588 &mappedPrivateVars),
9591 return llvm::make_error<PreviouslyReportedError>();
9594 targetOp, builder, moduleTranslation, privateVarsInfo.
mlirVars,
9596 targetOp.getPrivateNeedsBarrier(), &mappedPrivateVars)))
9597 return llvm::make_error<PreviouslyReportedError>();
9608 if (!inRedOrigPtrs.empty()) {
9614 inRedResultPtrTys.reserve(inRedMapArgIdx.size());
9615 for (
unsigned mapArgIdx : inRedMapArgIdx)
9616 inRedResultPtrTys.push_back(
9617 moduleTranslation.
convertType(mapBlockArgs[mapArgIdx].getType()));
9619 llvm::OpenMPIRBuilder::LocationDescription bodyLoc(builder);
9620 llvm::OpenMPIRBuilder::InsertPointTy redIP =
9621 ompBuilder->createTargetInReduction(
9622 bodyLoc, inRedOrigPtrs, inRedResultPtrTys,
9623 [&](
unsigned idx, llvm::Value *priv) {
9624 moduleTranslation.
mapValue(mapBlockArgs[inRedMapArgIdx[idx]],
9627 builder.restoreIP(redIP);
9631 moduleTranslation, allocaIP, deallocBlocks);
9633 targetRegion,
"omp.target", builder, moduleTranslation);
9636 return llvm::make_error<PreviouslyReportedError>();
9638 builder.SetInsertPoint(exitBlock.get()->getTerminator());
9641 targetOp.getLoc(), privateVarsInfo)))
9642 return llvm::make_error<PreviouslyReportedError>();
9644 return builder.saveIP();
9647 StringRef parentName = parentFn.getName();
9649 llvm::TargetRegionEntryInfo entryInfo;
9655 MapInfoData mapData;
9660 MapInfosTy combinedInfos;
9662 [&](llvm::OpenMPIRBuilder::InsertPointTy codeGenIP) -> MapInfosTy & {
9663 builder.restoreIP(codeGenIP);
9664 genMapInfos(builder, moduleTranslation, dl, combinedInfos, mapData,
9669 auto *nullPtr = llvm::Constant::getNullValue(builder.getPtrTy());
9670 combinedInfos.BasePointers.push_back(nullPtr);
9671 combinedInfos.Pointers.push_back(nullPtr);
9672 combinedInfos.DevicePointers.push_back(
9673 llvm::OpenMPIRBuilder::DeviceInfoTy::None);
9674 combinedInfos.Sizes.push_back(builder.getInt64(0));
9675 combinedInfos.Types.push_back(
9676 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
9677 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
9679 combinedInfos.HasAttachPtr.push_back(
false);
9680 if (!combinedInfos.Names.empty())
9681 combinedInfos.Names.push_back(nullPtr);
9682 combinedInfos.Mappers.push_back(
nullptr);
9684 return combinedInfos;
9687 auto argAccessorCB = [&](llvm::Argument &arg, llvm::Value *input,
9688 llvm::Value *&retVal, InsertPointTy allocaIP,
9689 InsertPointTy codeGenIP,
9691 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
9692 llvm::IRBuilderBase::InsertPointGuard guard(builder);
9693 builder.SetCurrentDebugLocation(llvm::DebugLoc());
9699 if (!isTargetDevice) {
9700 retVal = cast<llvm::Value>(&arg);
9705 builder, *ompBuilder, moduleTranslation,
9706 allocaIP, codeGenIP, deallocIPs);
9709 llvm::OpenMPIRBuilder::TargetKernelRuntimeAttrs runtimeAttrs;
9710 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs defaultAttrs;
9712 cast<omp::ComposableOpInterface>(*targetOp).findCapturedOp();
9714 isTargetDevice, isGPU);
9718 if (!isTargetDevice)
9720 targetCapturedOp, runtimeAttrs);
9728 for (
auto [arg, var] : llvm::zip_equal(hostEvalBlockArgs, hostEvalVars)) {
9729 llvm::Value *value = moduleTranslation.
lookupValue(var);
9730 moduleTranslation.
mapValue(arg, value);
9732 if (!llvm::isa<llvm::Constant>(value))
9733 kernelInput.push_back(value);
9736 for (
size_t i = 0, e = mapData.OriginalValue.size(); i != e; ++i) {
9746 using MapFlags = llvm::omp::OpenMPOffloadMappingFlags;
9747 bool isAttachMap = (mapData.Types[i] & MapFlags::OMP_MAP_ATTACH) ==
9748 MapFlags::OMP_MAP_ATTACH;
9749 bool isPrivateTargetParam =
9751 (MapFlags::OMP_MAP_PRIVATE | MapFlags::OMP_MAP_TARGET_PARAM)) ==
9752 (MapFlags::OMP_MAP_PRIVATE | MapFlags::OMP_MAP_TARGET_PARAM);
9754 if (!mapData.IsDeclareTarget[i] && !mapData.IsAMember[i] &&
9755 (!isAttachMap || (isAttachMap && isPrivateTargetParam)))
9756 kernelInput.push_back(mapData.OriginalValue[i]);
9760 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
9763 llvm::OpenMPIRBuilder::DependenciesInfo dds;
9765 targetOp.getDependVars(), targetOp.getDependKinds(),
9766 targetOp.getDependIterated(), targetOp.getDependIteratedKinds(),
9767 builder, moduleTranslation, dds)))
9770 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
9772 llvm::OpenMPIRBuilder::TargetDataInfo info(
9776 auto customMapperCB =
9778 if (!combinedInfos.Mappers[i])
9780 info.HasMapper =
true;
9782 moduleTranslation, targetDirective);
9785 llvm::Value *ifCond =
nullptr;
9786 if (
Value targetIfCond = targetOp.getIfExpr())
9787 ifCond = moduleTranslation.
lookupValue(targetIfCond);
9789 Value dynGroupPrivateSize = targetOp.getDynGroupprivateSize();
9790 llvm::Value *dynSizeVal =
nullptr;
9791 if (dynGroupPrivateSize) {
9792 dynSizeVal = moduleTranslation.
lookupValue(dynGroupPrivateSize);
9793 dynSizeVal = builder.CreateIntCast(dynSizeVal, builder.getInt32Ty(),
9797 llvm::omp::OMPDynGroupprivateFallbackType fallbackType =
9800 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
9802 ompLoc, isOffloadEntry, allocaIP, builder.saveIP(), deallocBlocks,
9803 info, entryInfo, defaultAttrs, runtimeAttrs, ifCond, kernelInput,
9804 genMapInfoCB, bodyCB, argAccessorCB, customMapperCB, dds,
9805 targetOp.getNowait(), dynSizeVal, fallbackType, outlinedFnDbgLoc);
9810 builder.restoreIP(*afterIP);
9813 builder.CreateFree(dds.DepArray);
9820 llvm::OpenMPIRBuilder *ompBuilder,
9829 if (FunctionOpInterface funcOp = dyn_cast<FunctionOpInterface>(op)) {
9830 if (
auto offloadMod = dyn_cast<omp::OffloadModuleInterface>(
9832 if (!offloadMod.getIsTargetDevice())
9835 omp::DeclareTargetDeviceType declareType =
9836 attribute.getDeviceType().getValue();
9838 if (declareType == omp::DeclareTargetDeviceType::host) {
9839 llvm::Function *llvmFunc =
9841 llvmFunc->dropAllReferences();
9842 llvmFunc->eraseFromParent();
9846 ompBuilder->Builder.ClearInsertionPoint();
9847 ompBuilder->Builder.SetCurrentDebugLocation(llvm::DebugLoc());
9848 }
else if (llvm::Function *llvmFunc =
9860 if (!llvmFunc->isDeclaration() && llvmFunc->hasExternalLinkage() &&
9861 llvmFunc->getVisibility() == llvm::GlobalValue::DefaultVisibility)
9862 llvmFunc->setVisibility(llvm::GlobalValue::HiddenVisibility);
9868 if (LLVM::GlobalOp gOp = dyn_cast<LLVM::GlobalOp>(op)) {
9869 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
9870 if (
auto *gVal = llvmModule->getNamedValue(gOp.getSymName())) {
9871 auto *gVar = cast<llvm::GlobalVariable>(gVal);
9873 bool isDeclaration = gOp.isDeclaration();
9874 bool isExternallyVisible =
9877 llvm::StringRef mangledName = gOp.getSymName();
9878 mlir::omp::DeclareTargetCaptureClause captureClause =
9879 attribute.getCaptureClause().getValue();
9883 llvm::StringRef entryMangledName = mangledName;
9884 llvm::Constant *entryAddr = llvm::cast<llvm::Constant>(gVal);
9885 std::function<llvm::GlobalValue::LinkageTypes()> variableLinkage;
9887 bool requiresUSM = ompBuilder->Config.hasRequiresUnifiedSharedMemory();
9889 captureClause == omp::DeclareTargetCaptureClause::to ||
9890 captureClause == omp::DeclareTargetCaptureClause::enter;
9891 bool isHostOnly = attribute.getDeviceType().getValue() ==
9892 omp::DeclareTargetDeviceType::host;
9897 if (isToOrEnter && !isHostOnly && !requiresUSM &&
9898 gVar->hasLocalLinkage()) {
9899 gVar->setLinkage(llvm::GlobalValue::ExternalLinkage);
9900 isExternallyVisible =
true;
9904 if (ompBuilder->Config.isTargetDevice())
9905 gVar->setDSOLocal(
false);
9910 llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny &&
9911 !requiresUSM && !isDeclaration &&
9912 (gVal->hasLocalLinkage() || gVal->hasHiddenVisibility())) {
9916 entryNameStorage = (mangledName + llvm::Twine(
"_decl_tgt_entry")).str();
9917 entryMangledName = entryNameStorage;
9918 if (llvm::GlobalValue *existing =
9919 llvmModule->getNamedValue(entryMangledName)) {
9920 entryAddr = llvm::cast<llvm::Constant>(existing);
9922 entryAddr = llvm::GlobalAlias::create(
9923 gVal->getValueType(), gVal->getAddressSpace(),
9924 llvm::GlobalValue::WeakAnyLinkage, entryMangledName, entryAddr,
9926 llvm::cast<llvm::GlobalAlias>(entryAddr)->setVisibility(
9927 llvm::GlobalValue::DefaultVisibility);
9929 variableLinkage = [] {
return llvm::GlobalValue::WeakAnyLinkage; };
9933 std::vector<llvm::GlobalVariable *> generatedRefs;
9935 std::vector<llvm::Triple> targetTriple;
9936 auto targetTripleAttr = dyn_cast_or_null<mlir::StringAttr>(
9938 LLVM::LLVMDialect::getTargetTripleAttrName()));
9939 if (targetTripleAttr)
9940 targetTriple.emplace_back(targetTripleAttr.data());
9942 auto fileInfoCallBack = [&loc]() {
9943 std::string filename =
"";
9944 std::uint64_t lineNo = 0;
9947 filename = loc.getFilename().str();
9948 lineNo = loc.getLine();
9951 return std::pair<std::string, std::uint64_t>(llvm::StringRef(filename),
9955 llvm::vfs::FileSystem &vfs = moduleTranslation.
getFileSystem();
9956 ompBuilder->registerTargetGlobalVariable(
9957 captureClauseKind, deviceClause, isDeclaration, isExternallyVisible,
9958 ompBuilder->getTargetEntryUniqueInfo(fileInfoCallBack, vfs),
9959 entryMangledName, generatedRefs,
false, targetTriple,
9960 nullptr, variableLinkage, gVal->getType(),
9963 if (ompBuilder->Config.isTargetDevice() &&
9964 (captureClause == omp::DeclareTargetCaptureClause::link ||
9969 llvm::Type *ptrTy = llvm::PointerType::get(llvmModule->getContext(), 0);
9970 llvm::Constant *refPtr = ompBuilder->getAddrOfDeclareTargetVar(
9971 captureClauseKind, deviceClause, isDeclaration, isExternallyVisible,
9972 ompBuilder->getTargetEntryUniqueInfo(fileInfoCallBack, vfs),
9973 mangledName, generatedRefs,
false, targetTriple,
9982 gVar->setLinkage(llvm::GlobalValue::InternalLinkage);
9988 dyn_cast<llvm::GlobalValue>(refPtr->stripPointerCasts()))
9989 ompBuilder->registerDeclareTargetGlobalReplacement(gVal, newGV);
9996 if (ompBuilder->Config.isTargetDevice() && isHostOnly && isToOrEnter) {
9997 gVar->setLinkage(llvm::GlobalValue::ExternalLinkage);
9998 gVar->setInitializer(
nullptr);
10010class OpenMPDialectLLVMIRTranslationInterface
10011 :
public LLVMTranslationDialectInterface {
10013 using LLVMTranslationDialectInterface::LLVMTranslationDialectInterface;
10018 convertOperation(Operation *op, llvm::IRBuilderBase &builder,
10019 LLVM::ModuleTranslation &moduleTranslation)
const final;
10024 amendOperation(Operation *op, ArrayRef<llvm::Instruction *> instructions,
10025 NamedAttribute attribute,
10026 LLVM::ModuleTranslation &moduleTranslation)
const final;
10031 void registerAllocatedPtr(Value var, llvm::Value *ptr)
const {
10032 ompAllocatedPtrs[var] = ptr;
10037 llvm::Value *lookupAllocatedPtr(Value var)
const {
10038 auto it = ompAllocatedPtrs.find(var);
10039 return it != ompAllocatedPtrs.end() ? it->second :
nullptr;
10051LogicalResult OpenMPDialectLLVMIRTranslationInterface::amendOperation(
10052 Operation *op, ArrayRef<llvm::Instruction *> instructions,
10053 NamedAttribute attribute,
10054 LLVM::ModuleTranslation &moduleTranslation)
const {
10055 return llvm::StringSwitch<llvm::function_ref<LogicalResult(Attribute)>>(
10057 .Case(
"omp.is_target_device",
10058 [&](Attribute attr) {
10059 if (
auto deviceAttr = dyn_cast<BoolAttr>(attr)) {
10060 llvm::OpenMPIRBuilderConfig &config =
10062 config.setIsTargetDevice(deviceAttr.getValue());
10067 .Case(
"omp.is_gpu",
10068 [&](Attribute attr) {
10069 if (
auto gpuAttr = dyn_cast<BoolAttr>(attr)) {
10070 llvm::OpenMPIRBuilderConfig &config =
10072 config.setIsGPU(gpuAttr.getValue());
10077 .Case(
"omp.host_ir_filepath",
10078 [&](Attribute attr) {
10079 if (
auto filepathAttr = dyn_cast<StringAttr>(attr)) {
10080 llvm::OpenMPIRBuilder *ompBuilder =
10082 ompBuilder->loadOffloadInfoMetadata(
10083 moduleTranslation.
getFileSystem(), filepathAttr.getValue());
10089 [&](Attribute attr) {
10090 if (
auto rtlAttr = dyn_cast<omp::FlagsAttr>(attr))
10094 .Case(
"omp.version",
10095 [&](Attribute attr) {
10096 if (
auto versionAttr = dyn_cast<omp::VersionAttr>(attr)) {
10097 llvm::OpenMPIRBuilder *ompBuilder =
10099 ompBuilder->M.addModuleFlag(llvm::Module::Max,
"openmp",
10100 versionAttr.getVersion());
10105 .Case(
"omp.declare_target",
10106 [&](Attribute attr) {
10107 if (
auto declareTargetAttr =
10108 dyn_cast<omp::DeclareTargetAttr>(attr)) {
10109 llvm::OpenMPIRBuilder *ompBuilder =
10112 ompBuilder, moduleTranslation);
10116 .Case(
"omp.requires",
10117 [&](Attribute attr) {
10118 if (
auto requiresAttr = dyn_cast<omp::ClauseRequiresAttr>(attr)) {
10119 using Requires = omp::ClauseRequires;
10120 Requires flags = requiresAttr.getValue();
10121 llvm::OpenMPIRBuilderConfig &config =
10123 config.setHasRequiresReverseOffload(
10124 bitEnumContainsAll(flags, Requires::reverse_offload));
10125 config.setHasRequiresUnifiedAddress(
10126 bitEnumContainsAll(flags, Requires::unified_address));
10127 config.setHasRequiresUnifiedSharedMemory(
10128 bitEnumContainsAll(flags, Requires::unified_shared_memory));
10129 config.setHasRequiresDynamicAllocators(
10130 bitEnumContainsAll(flags, Requires::dynamic_allocators));
10135 .Case(
"omp.target_triples",
10136 [&](Attribute attr) {
10137 if (
auto triplesAttr = dyn_cast<ArrayAttr>(attr)) {
10138 llvm::OpenMPIRBuilderConfig &config =
10140 config.TargetTriples.clear();
10141 config.TargetTriples.reserve(triplesAttr.size());
10142 for (Attribute tripleAttr : triplesAttr) {
10143 if (
auto tripleStrAttr = dyn_cast<StringAttr>(tripleAttr))
10144 config.TargetTriples.emplace_back(tripleStrAttr.getValue());
10152 .Case(
"omp.integer_wrap_around",
10153 [&](Attribute attr) {
10154 if (
auto wrapAttr = dyn_cast<omp::IntegerWrapAroundAttr>(attr)) {
10155 llvm::OpenMPIRBuilderConfig &config =
10157 config.setNoSignedWrap(!wrapAttr.getIntegerWrapAround());
10162 .Default([](Attribute) {
10178 if (
auto declareTargetIface =
10179 llvm::dyn_cast<mlir::omp::DeclareTargetInterface>(
10180 parentFn.getOperation()))
10181 if (declareTargetIface.isDeclareTarget() &&
10182 declareTargetIface.getDeclareTargetDeviceType() !=
10183 mlir::omp::DeclareTargetDeviceType::host)
10193 llvm::Module *llvmModule) {
10194 llvm::Type *i64Ty = builder.getInt64Ty();
10195 llvm::Type *i32Ty = builder.getInt32Ty();
10196 llvm::Type *returnType = builder.getPtrTy(0);
10197 llvm::FunctionType *fnType =
10198 llvm::FunctionType::get(returnType, {i64Ty, i32Ty},
false);
10199 llvm::Function *
func = cast<llvm::Function>(
10200 llvmModule->getOrInsertFunction(
"omp_target_alloc", fnType).getCallee());
10204template <
typename T>
10205static llvm::Value *
10208 llvm::DataLayout dataLayout =
10210 llvm::Type *llvmHeapTy =
10211 moduleTranslation.
convertType(op.getMemElemTypeAttr().getValue());
10213 auto alignment = op.getMemAlignment();
10214 llvm::TypeSize typeSize = llvm::alignTo(
10215 dataLayout.getTypeStoreSize(llvmHeapTy),
10216 alignment ? *alignment : dataLayout.getABITypeAlign(llvmHeapTy).value());
10218 llvm::Value *allocSize = builder.getInt64(typeSize.getFixedValue());
10219 return builder.CreateMul(
10221 builder.CreateIntCast(moduleTranslation.
lookupValue(op.getMemArraySize()),
10222 builder.getInt64Ty(),
10229 omp::TargetAllocMemOp op) {
10230 llvm::DataLayout dataLayout =
10232 llvm::Type *llvmHeapTy = moduleTranslation.
convertType(op.getAllocatedType());
10233 llvm::TypeSize typeSize = dataLayout.getTypeAllocSize(llvmHeapTy);
10234 llvm::Value *allocSize = builder.getInt64(typeSize.getFixedValue());
10235 for (
auto typeParam : op.getTypeparams()) {
10236 allocSize = builder.CreateMul(
10238 builder.CreateIntCast(moduleTranslation.
lookupValue(typeParam),
10239 builder.getInt64Ty(),
10245static LogicalResult
10248 auto allocMemOp = cast<omp::TargetAllocMemOp>(opInst);
10253 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
10257 llvm::Value *llvmDeviceNum = moduleTranslation.
lookupValue(deviceNum);
10259 llvm::Value *allocSize =
10262 llvm::CallInst *call =
10263 builder.CreateCall(ompTargetAllocFunc, {allocSize, llvmDeviceNum});
10264 llvm::Value *resultI64 = builder.CreatePtrToInt(call, builder.getInt64Ty());
10267 moduleTranslation.
mapValue(allocMemOp.getResult(), resultI64);
10271static LogicalResult
10273 llvm::IRBuilderBase &builder,
10277 moduleTranslation.
mapValue(allocMemOp.getResult(),
10278 ompBuilder->createOMPAllocShared(builder, size));
10282static LogicalResult
10285 const OpenMPDialectLLVMIRTranslationInterface &ompIface) {
10286 auto allocateDirOp = cast<omp::AllocateDirOp>(opInst);
10289 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
10290 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
10291 llvm::DataLayout dataLayout = llvmModule->getDataLayout();
10293 std::optional<int64_t> alignAttr = allocateDirOp.getAlign();
10295 llvm::Value *allocator;
10296 if (
auto allocatorVar = allocateDirOp.getAllocator()) {
10297 allocator = moduleTranslation.
lookupValue(allocatorVar);
10298 if (allocator->getType()->isIntegerTy())
10299 allocator = builder.CreateIntToPtr(allocator, builder.getPtrTy());
10300 else if (allocator->getType()->isPointerTy())
10301 allocator = builder.CreatePointerBitCastOrAddrSpaceCast(
10302 allocator, builder.getPtrTy());
10304 allocator = llvm::ConstantPointerNull::get(builder.getPtrTy());
10307 for (
Value var : vars) {
10309 llvm::Type *typeToInspect =
10314 var, baseVar, moduleTranslation, builder, dataLayout)) {
10315 size = *dynamicSize;
10316 }
else if (typeToInspect->isArrayTy()) {
10317 size = builder.getInt64(
10318 dataLayout.getTypeAllocSize(typeToInspect).getFixedValue());
10320 size = builder.getInt64(
10321 dataLayout.getTypeAllocSize(typeToInspect).getFixedValue());
10324 uint64_t alignValue =
10325 alignAttr ? alignAttr.value()
10326 : dataLayout.getABITypeAlign(typeToInspect).value();
10327 llvm::Value *alignConst = builder.getInt64(alignValue);
10329 size = builder.CreateAdd(size, builder.getInt64(alignValue - 1),
"",
true);
10330 size = builder.CreateUDiv(size, alignConst);
10331 size = builder.CreateMul(size, alignConst,
"",
true);
10333 std::string allocName =
10334 ompBuilder->createPlatformSpecificName({
".void.addr"});
10335 llvm::CallInst *allocCall;
10336 if (alignAttr.has_value()) {
10337 allocCall = ompBuilder->createOMPAlignedAlloc(
10338 ompLoc, builder.getInt64(alignAttr.value()), size, allocator,
10342 ompBuilder->createOMPAlloc(ompLoc, size, allocator, allocName);
10345 ompIface.registerAllocatedPtr(var, allocCall);
10347 if (llvm::Value *baseLlvm = moduleTranslation.
lookupValue(baseVar)) {
10348 llvm::Value *boundPtr = builder.CreatePointerBitCastOrAddrSpaceCast(
10349 allocCall, baseLlvm->getType());
10351 }
else if (llvm::Value *varLlvm = moduleTranslation.
lookupValue(var)) {
10352 llvm::Value *boundPtr = builder.CreatePointerBitCastOrAddrSpaceCast(
10353 allocCall, varLlvm->getType());
10361static LogicalResult
10364 const OpenMPDialectLLVMIRTranslationInterface &ompIface) {
10365 auto freeOp = cast<omp::AllocateFreeOp>(opInst);
10367 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
10369 llvm::Value *allocator;
10370 if (
auto allocatorVar = freeOp.getAllocator()) {
10371 allocator = moduleTranslation.
lookupValue(allocatorVar);
10372 if (allocator->getType()->isIntegerTy())
10373 allocator = builder.CreateIntToPtr(allocator, builder.getPtrTy());
10374 else if (allocator->getType()->isPointerTy())
10375 allocator = builder.CreatePointerBitCastOrAddrSpaceCast(
10376 allocator, builder.getPtrTy());
10378 allocator = llvm::ConstantPointerNull::get(builder.getPtrTy());
10383 for (
Value var : llvm::reverse(vars)) {
10384 llvm::Value *allocPtr = ompIface.lookupAllocatedPtr(var);
10386 return opInst.
emitError(
"omp.allocate_free: no allocation recorded");
10387 ompBuilder->createOMPFree(ompLoc, allocPtr, allocator,
"");
10394 llvm::Module *llvmModule) {
10395 llvm::Type *ptrTy = builder.getPtrTy(0);
10396 llvm::Type *i32Ty = builder.getInt32Ty();
10397 llvm::Type *voidTy = builder.getVoidTy();
10398 llvm::FunctionType *fnType =
10399 llvm::FunctionType::get(voidTy, {ptrTy, i32Ty},
false);
10400 llvm::Function *
func = dyn_cast<llvm::Function>(
10401 llvmModule->getOrInsertFunction(
"omp_target_free", fnType).getCallee());
10405static LogicalResult
10408 auto freeMemOp = cast<omp::TargetFreeMemOp>(opInst);
10413 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
10414 llvm::Function *ompTragetFreeFunc =
getOmpTargetFree(builder, llvmModule);
10417 llvm::Value *llvmDeviceNum = moduleTranslation.
lookupValue(deviceNum);
10420 llvm::Value *llvmHeapref = moduleTranslation.
lookupValue(heapref);
10422 llvm::Value *intToPtr =
10423 builder.CreateIntToPtr(llvmHeapref, builder.getPtrTy(0));
10424 builder.CreateCall(ompTragetFreeFunc, {intToPtr, llvmDeviceNum});
10428static LogicalResult
10430 llvm::IRBuilderBase &builder,
10434 ompBuilder->createOMPFreeShared(
10435 builder, moduleTranslation.
lookupValue(freeMemOp.getHeapref()), size);
10440static LogicalResult
10444 auto groupprivateOp = cast<omp::GroupprivateOp>(opInst);
10449 bool isTargetDevice = ompBuilder->Config.isTargetDevice();
10453 bool shouldAllocate =
true;
10454 switch (groupprivateOp.getDeviceType().value_or(
10455 mlir::omp::DeclareTargetDeviceType::any)) {
10456 case mlir::omp::DeclareTargetDeviceType::host:
10457 shouldAllocate = !isTargetDevice;
10459 case mlir::omp::DeclareTargetDeviceType::nohost:
10460 shouldAllocate = isTargetDevice;
10462 case mlir::omp::DeclareTargetDeviceType::any:
10463 shouldAllocate =
true;
10469 &opInst, groupprivateOp.getSymNameAttr());
10472 <<
"expected symbol '" << groupprivateOp.getSymName()
10473 <<
"' to reference an LLVM global variable";
10475 llvm::GlobalValue *globalValue = moduleTranslation.
lookupGlobal(global);
10476 llvm::Type *varType = moduleTranslation.
convertType(global.getType());
10477 std::string varName = globalValue->getName().str();
10479 llvm::Value *resultPtr;
10480 if (shouldAllocate && isTargetDevice) {
10481 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
10482 llvm::Triple targetTriple(llvmModule->getTargetTriple());
10483 unsigned sharedAddressSpace;
10484 if (targetTriple.isAMDGCN())
10485 sharedAddressSpace = llvm::AMDGPUAS::LOCAL_ADDRESS;
10486 else if (targetTriple.isNVPTX())
10487 sharedAddressSpace = llvm::NVPTXAS::ADDRESS_SPACE_SHARED;
10489 return opInst.
emitError() <<
"groupprivate is not supported for target: "
10490 << targetTriple.str();
10491 llvm::GlobalVariable *sharedVar =
new llvm::GlobalVariable(
10492 *llvmModule, varType,
false,
10493 llvm::GlobalValue::InternalLinkage, llvm::PoisonValue::get(varType),
10494 varName,
nullptr, llvm::GlobalValue::NotThreadLocal,
10495 sharedAddressSpace,
10497 resultPtr = sharedVar;
10499 if (shouldAllocate && !isTargetDevice)
10500 opInst.
emitWarning(
"groupprivate directive is currently ignored on the "
10501 "host, using original global");
10502 resultPtr = globalValue;
10511LogicalResult OpenMPDialectLLVMIRTranslationInterface::convertOperation(
10512 Operation *op, llvm::IRBuilderBase &builder,
10513 LLVM::ModuleTranslation &moduleTranslation)
const {
10516 if (ompBuilder->Config.isTargetDevice() &&
10517 !isa<omp::TargetOp, omp::MapInfoOp, omp::TerminatorOp, omp::YieldOp>(
10520 return op->
emitOpError() <<
"unsupported host op found in device";
10528 bool isOutermostLoopWrapper =
10529 isa_and_present<omp::LoopWrapperInterface>(op) &&
10530 !dyn_cast_if_present<omp::LoopWrapperInterface>(op->
getParentOp());
10539 if (isa<omp::TaskloopContextOp>(op))
10540 isOutermostLoopWrapper =
true;
10541 else if (isa<omp::TaskloopWrapperOp>(op))
10542 isOutermostLoopWrapper =
false;
10544 if (isOutermostLoopWrapper)
10545 moduleTranslation.
stackPush<OpenMPLoopInfoStackFrame>();
10548 llvm::TypeSwitch<Operation *, LogicalResult>(op)
10549 .Case([&](omp::BarrierOp op) -> LogicalResult {
10553 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
10554 ompBuilder->createBarrier(builder, llvm::omp::OMPD_barrier);
10556 if (res.succeeded()) {
10559 builder.restoreIP(*afterIP);
10563 .Case([&](omp::TaskyieldOp op) {
10567 ompBuilder->createTaskyield(builder);
10570 .Case([&](omp::FlushOp op) {
10582 ompBuilder->createFlush(builder);
10585 .Case([&](omp::ErrorOp op) {
10589 llvm::Value *message =
nullptr;
10590 if (mlir::Value messageExpr = op.getMessageExpr())
10591 message = moduleTranslation.
lookupValue(messageExpr);
10592 else if (std::optional<StringRef> msg = op.getMessage();
10593 msg && !msg->empty())
10594 message = builder.CreateGlobalString(*msg);
10595 ompBuilder->createError(
10596 llvm::OpenMPIRBuilder::LocationDescription(builder),
10597 op.getSeverity() == omp::ClauseSeverity::fatal, message);
10600 .Case([&](omp::ParallelOp op) {
10603 .Case([&](omp::MaskedOp) {
10606 .Case([&](omp::MasterOp) {
10609 .Case([&](omp::CriticalOp) {
10612 .Case([&](omp::OrderedRegionOp) {
10615 .Case([&](omp::OrderedOp) {
10618 .Case([&](omp::WsloopOp) {
10621 .Case([&](omp::SimdOp) {
10624 .Case([&](omp::AtomicReadOp) {
10627 .Case([&](omp::AtomicWriteOp) {
10630 .Case([&](omp::AtomicUpdateOp op) {
10633 .Case([&](omp::AtomicCaptureOp op) {
10636 .Case([&](omp::AtomicCompareOp op) {
10639 .Case([&](omp::CancelOp op) {
10642 .Case([&](omp::CancellationPointOp op) {
10645 .Case([&](omp::SectionsOp) {
10648 .Case([&](omp::ScopeOp op) {
10651 .Case([&](omp::SingleOp op) {
10654 .Case([&](omp::TeamsOp op) {
10657 .Case([&](omp::TaskOp op) {
10660 .Case([&](omp::TaskloopWrapperOp op) {
10663 .Case([&](omp::TaskloopContextOp op) {
10666 .Case([&](omp::TaskgroupOp op) {
10669 .Case([&](omp::TaskwaitOp op) {
10672 .Case([&](omp::InteropInitOp op) {
10675 .Case([&](omp::InteropDestroyOp op) {
10678 .Case([&](omp::InteropUseOp op) {
10681 .Case<omp::YieldOp, omp::TerminatorOp, omp::DeclareMapperOp,
10682 omp::DeclareMapperInfoOp, omp::DeclareReductionOp,
10683 omp::CriticalDeclareOp>([](
auto op) {
10696 .Case([&](omp::ThreadprivateOp) {
10699 .Case<omp::TargetDataOp, omp::TargetEnterDataOp,
10700 omp::TargetExitDataOp, omp::TargetUpdateOp>([&](
auto op) {
10703 .Case([&](omp::TargetOp) {
10706 .Case([&](omp::DistributeOp) {
10709 .Case([&](omp::LoopNestOp) {
10712 .Case<omp::MapInfoOp, omp::MapBoundsOp, omp::PrivateClauseOp,
10713 omp::AffinityEntryOp, omp::IteratorOp>([&](
auto op) {
10719 .Case([&](omp::NewCliOp op) {
10724 .Case([&](omp::CanonicalLoopOp op) {
10727 .Case([&](omp::UnrollHeuristicOp op) {
10736 .Case([&](omp::UnrollFullOp op) {
10739 .Case([&](omp::UnrollPartialOp op) {
10742 .Case([&](omp::TileOp op) {
10743 return applyTile(op, builder, moduleTranslation);
10745 .Case([&](omp::FuseOp op) {
10746 return applyFuse(op, builder, moduleTranslation);
10748 .Case([&](omp::TargetAllocMemOp) {
10751 .Case([&](omp::TargetFreeMemOp) {
10754 .Case([&](omp::AllocateDirOp) {
10757 .Case([&](omp::AllocateFreeOp) {
10761 .Case([&](omp::AllocSharedMemOp op) {
10764 .Case([&](omp::FreeSharedMemOp op) {
10767 .Case([&](omp::GroupprivateOp) {
10770 .Default([&](Operation *inst) {
10772 <<
"not yet implemented: " << inst->
getName();
10775 if (isOutermostLoopWrapper)
10782 registry.
insert<omp::OpenMPDialect>();
10784 dialect->addInterfaces<OpenMPDialectLLVMIRTranslationInterface>();
if(failed(verifyVectorMemoryOp(getOperation(), memrefType, getVectorType()))) return failure()
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 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 void emitComplexAtomicCmpXchg(llvm::IRBuilderBase &builder, llvm::Value *llvmX, llvm::Type *complexTy, llvm::Value *eVal, llvm::Value *dVal, llvm::AtomicOrdering atomicOrdering, llvm::AtomicOrdering failOrdering, bool isWeak, llvm::Value *&oldComplex, llvm::Value *&cmpOk)
Emit an IEEE-754-correct cmpxchg for a complex (struct-typed) atomic compare with fcmp oeq....
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 bool isPrivatizeableAttachMap(omp::ClauseMapFlags mapType)
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 applyUnrollFull(omp::UnrollFullOp op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Apply a #pragma omp unroll full / !$omp unroll full transformation using the OpenMPIRBuilder.
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 extractAtomicComparePattern(Block &block, llvm::function_ref< llvm::Value *(mlir::Value)> materializeValue, omp::AtomicCompareOp atomicCompareOp, AtomicComparePatternInfo &info)
Extract comparison predicate, expected value (e), desired value (d), and related flags from an atomic...
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::AtomicOrdering getAtomicCompareFailureOrdering(omp::AtomicCompareOp atomicCompareOp, llvm::AtomicOrdering atomicOrdering)
Compute the cmpxchg failure ordering for an atomic compare op: use the fail clause ordering when pres...
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 ComplexComparePattern detectComplexCompareEq(Block &block)
Detect a decomposed complex equality comparison in an atomic compare region: re_x = llvm....
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 llvm::Type * getAllocatedLlvmTypeForVariable(Value var, Value baseVar, LLVM::ModuleTranslation &moduleTranslation)
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 std::optional< llvm::Value * > getDynamicAllocatedSize(Value var, Value baseVar, LLVM::ModuleTranslation &moduleTranslation, llvm::IRBuilderBase &builder, const llvm::DataLayout &dataLayout)
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.
void remapAllValuesWith(llvm::Value *oldValue, llvm::Value *newValue)
Remap old value with new value in the MLIR-to-LLVM value map so later translations use the replacemen...
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 provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
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.
detail::DenseArrayAttrImpl< int64_t > DenseI64ArrayAttr
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
Holds the extracted comparison pattern information from an atomic compare region.
llvm::omp::OMPAtomicCompareOp compareOp
Result of matching the decomposed complex equality pattern inside an atomic compare region.
llvm::Value * allocatedPtr
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
llvm::DenseMap< Value, llvm::Value * > convertedAllocators
SmallVector< llvm::Value * > llvmVars
SmallVector< AllocatorPrivateInfo > allocatorPrivates
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.