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::OpenMPIRBuilder::InsertPointOrErrorTy contInsertPoint =
1723 ompBuilder->createReductions(builder, allocaIP, reductionInfos, isByRef,
1724 isNowait, isTeamsReduction);
1729 if (!contInsertPoint->getBlock())
1730 return op->emitOpError() <<
"failed to convert reductions";
1732 llvm::OpenMPIRBuilder::InsertPointTy afterIP = *contInsertPoint;
1733 if (!isTeamsReduction) {
1734 llvm::OpenMPIRBuilder::InsertPointOrErrorTy barrierIP =
1735 ompBuilder->createBarrier(*contInsertPoint, llvm::omp::OMPD_for);
1739 afterIP = *barrierIP;
1742 tempTerminator->eraseFromParent();
1743 builder.restoreIP(afterIP);
1747 llvm::transform(reductionDecls, std::back_inserter(reductionRegions),
1748 [](omp::DeclareReductionOp reductionDecl) {
1749 return &reductionDecl.getCleanupRegion();
1752 reductionRegions, privateReductionVariables, moduleTranslation, builder,
1753 "omp.reduction.cleanup");
1756 if (useDeviceSharedMem) {
1757 for (
auto [var, reductionDecl] :
1758 llvm::zip_equal(privateReductionVariables, reductionDecls))
1759 ompBuilder->createOMPFreeShared(
1760 builder, var, moduleTranslation.
convertType(reductionDecl.getType()));
1773template <
typename OP>
1777 llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
1782 if (op.getNumReductionVars() == 0)
1788 allocaIP, reductionDecls,
1789 privateReductionVariables, reductionVariableMap,
1790 deferredStores, isByRef)))
1793 return initReductionVars(op, reductionArgs, builder, moduleTranslation,
1794 allocaIP.getBlock(), reductionDecls,
1795 privateReductionVariables, reductionVariableMap,
1796 isByRef, deferredStores);
1810 if (mappedPrivateVars ==
nullptr || !mappedPrivateVars->contains(privateVar))
1813 Value blockArg = (*mappedPrivateVars)[privateVar];
1816 assert(isa<LLVM::LLVMPointerType>(blockArgType) &&
1817 "A block argument corresponding to a mapped var should have "
1820 if (privVarType == blockArgType)
1827 if (!isa<LLVM::LLVMPointerType>(privVarType))
1828 return builder.CreateLoad(moduleTranslation.
convertType(privVarType),
1845 llvm::Type *regionArgType =
1847 if (regionArgType->isPointerTy() || !value->getType()->isPointerTy())
1850 return builder.CreateLoad(regionArgType, value);
1860 omp::PrivateClauseOp &privDecl, llvm::Value *nonPrivateVar,
1862 llvm::BasicBlock *privInitBlock,
1864 Region &initRegion = privDecl.getInitRegion();
1865 if (initRegion.
empty())
1866 return llvmPrivateVar;
1868 assert(nonPrivateVar);
1869 moduleTranslation.
mapValue(privDecl.getInitMoldArg(), nonPrivateVar);
1870 moduleTranslation.
mapValue(privDecl.getInitPrivateArg(), llvmPrivateVar);
1875 moduleTranslation, &phis)))
1876 return llvm::createStringError(
1877 "failed to inline `init` region of `omp.private`");
1879 assert(phis.size() == 1 &&
"expected one allocation to be yielded");
1896 llvm::Value *llvmPrivateVar, llvm::BasicBlock *privInitBlock,
1899 builder, moduleTranslation, privDecl,
1902 blockArg, llvmPrivateVar, privInitBlock, mappedPrivateVars);
1911 return llvm::Error::success();
1913 llvm::BasicBlock *privInitBlock = splitBB(builder,
true,
"omp.private.init");
1916 for (
auto [idx, zip] : llvm::enumerate(llvm::zip_equal(
1919 auto [privDecl, mlirPrivVar, blockArg, llvmPrivateVar] = zip;
1921 builder, moduleTranslation, privDecl, mlirPrivVar, blockArg,
1922 llvmPrivateVar, privInitBlock, mappedPrivateVars);
1925 return privVarOrErr.takeError();
1927 llvmPrivateVar = privVarOrErr.get();
1928 moduleTranslation.
mapValue(blockArg, llvmPrivateVar);
1933 return llvm::Error::success();
1939template <
typename T>
1944 const llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
1947 llvm::Instruction *allocaTerminator = allocaIP.getBlock()->getTerminator();
1948 splitBB(llvm::OpenMPIRBuilder::InsertPointTy(allocaIP.getBlock(),
1949 allocaTerminator->getIterator()),
1950 true, allocaTerminator->getStableDebugLoc(),
1951 "omp.region.after_alloca");
1953 llvm::IRBuilderBase::InsertPointGuard guard(builder);
1955 allocaTerminator = allocaIP.getBlock()->getTerminator();
1956 builder.SetInsertPoint(allocaTerminator);
1958 assert(allocaTerminator->getNumSuccessors() == 1 &&
1959 "This is an unconditional branch created by splitBB");
1961 llvm::DataLayout dataLayout = builder.GetInsertBlock()->getDataLayout();
1962 llvm::BasicBlock *afterAllocas = allocaTerminator->getSuccessor(0);
1966 unsigned int allocaAS =
1967 moduleTranslation.
getLLVMModule()->getDataLayout().getAllocaAddrSpace();
1970 .getProgramAddressSpace();
1976 if constexpr (std::is_same_v<T, omp::ParallelOp>) {
1977 allocatorVars = op.getAllocatorVars();
1978 allocateAlignments = op.getAllocateAlignmentsAttr();
1979 if (
auto privateIndices = op.getAllocatePrivateIndicesAttr())
1980 for (
auto [allocateIndex, privateIndex] :
1981 llvm::enumerate(privateIndices.asArrayRef()))
1982 allocateItemForPrivate[privateIndex] = allocateIndex;
1985 for (
auto [privateIndex, tuple] : llvm::enumerate(llvm::zip_equal(
1988 auto [privDecl, mlirPrivVar, blockArg] = tuple;
1989 llvm::Type *llvmAllocType =
1990 moduleTranslation.
convertType(privDecl.getType());
1991 builder.SetInsertPoint(allocaIP.getBlock()->getTerminator());
1992 llvm::Value *llvmPrivateVar =
nullptr;
1993 int64_t allocateIndex = allocateItemForPrivate[privateIndex];
1994 if (allocateIndex >= 0) {
1995 if (mightUseDeviceSharedMem ||
1996 op->template getParentOfType<omp::TargetOp>())
1997 return llvm::createStringError(
1998 "allocate clause on a device parallel region is not supported");
1999 if (!llvmAllocType->isSized())
2000 return llvm::createStringError(
2001 "allocate clause private type must have a fixed size");
2002 llvm::TypeSize size = dataLayout.getTypeAllocSize(llvmAllocType);
2003 if (size.isScalable())
2004 return llvm::createStringError(
2005 "allocate clause private type must have a fixed size");
2006 llvm::IntegerType *sizeTy =
2007 moduleTranslation.
getLLVMModule()->getDataLayout().getIntPtrType(
2009 if (!llvm::isUIntN(sizeTy->getBitWidth(), size.getFixedValue()))
2010 return llvm::createStringError(
2011 "OpenMP allocation size cannot be represented by the target size "
2013 llvm::Value *sizeValue =
2014 llvm::ConstantInt::get(sizeTy, size.getFixedValue());
2016 Value allocatorVar = allocatorVars[allocateIndex];
2019 return llvm::createStringError(
2020 "failed to find converted OpenMP allocator operand");
2021 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2023 allocateAlignments ? allocateAlignments[allocateIndex] : 0;
2024 if (alignment != 0) {
2028 uint64_t alignmentValue = std::max<uint64_t>(
2029 static_cast<uint64_t
>(alignment),
2030 dataLayout.getABITypeAlign(llvmAllocType).value());
2031 if (!llvm::isUIntN(sizeTy->getBitWidth(), alignmentValue))
2032 return llvm::createStringError(
2033 "OpenMP allocation alignment cannot be represented by the "
2034 "target size type");
2035 llvmPrivateVar = ompBuilder->createOMPAlignedAlloc(
2036 ompLoc, llvm::ConstantInt::get(sizeTy, alignmentValue), sizeValue,
2037 allocator->second,
"omp.private.alloc");
2039 llvmPrivateVar = ompBuilder->createOMPAlloc(
2040 ompLoc, sizeValue, allocator->second,
"omp.private.alloc");
2042 if (!llvmPrivateVar)
2043 return llvm::createStringError(
2044 "failed to create OpenMP private allocation");
2046 {llvmPrivateVar, allocator->second});
2047 }
else if (mightUseDeviceSharedMem &&
2049 llvmPrivateVar = ompBuilder->createOMPAllocShared(builder, llvmAllocType);
2051 llvmPrivateVar = builder.CreateAlloca(
2052 llvmAllocType,
nullptr,
"omp.private.alloc");
2053 if (allocaAS != defaultAS)
2054 llvmPrivateVar = builder.CreateAddrSpaceCast(
2055 llvmPrivateVar, builder.getPtrTy(defaultAS));
2058 privateVarsInfo.
llvmVars.push_back(llvmPrivateVar);
2061 return afterAllocas;
2069 if (mlir::isa<omp::SingleOp, omp::CriticalOp>(parent))
2078 if (mlir::isa<omp::ParallelOp>(parent))
2092 bool needsFirstprivate =
2093 llvm::any_of(privateDecls, [](omp::PrivateClauseOp &privOp) {
2094 return privOp.getDataSharingType() ==
2095 omp::DataSharingClauseType::FirstPrivate;
2098 if (!needsFirstprivate)
2101 llvm::BasicBlock *copyBlock =
2102 splitBB(builder,
true,
"omp.private.copy");
2105 for (
auto [decl, moldVar, llvmVar] :
2106 llvm::zip_equal(privateDecls, moldVars, llvmPrivateVars)) {
2107 if (decl.getDataSharingType() != omp::DataSharingClauseType::FirstPrivate)
2111 Region ©Region = decl.getCopyRegion();
2114 builder, moduleTranslation, decl.getCopyMoldArg(), moldVar);
2116 builder, moduleTranslation, decl.getCopyPrivateArg(), llvmVar);
2118 moduleTranslation.
mapValue(decl.getCopyMoldArg(), copyMoldVar);
2121 moduleTranslation.
mapValue(decl.getCopyPrivateArg(), copyPrivateVar);
2125 moduleTranslation)))
2126 return decl.emitError(
"failed to inline `copy` region of `omp.private`");
2140 llvm::OpenMPIRBuilder::InsertPointOrErrorTy res =
2141 ompBuilder->createBarrier(builder, llvm::omp::OMPD_barrier);
2157 llvm::transform(mlirPrivateVars, moldVars.begin(), [&](
mlir::Value mlirVar) {
2159 llvm::Value *moldVar = findAssociatedValue(
2160 mlirVar, builder, moduleTranslation, mappedPrivateVars);
2165 llvmPrivateVars, privateDecls, insertBarrier,
2169template <
typename T>
2177 std::back_inserter(privateCleanupRegions),
2178 [](omp::PrivateClauseOp privatizer) {
2179 return &privatizer.getDeallocRegion();
2183 privateVarsInfo.
llvmVars, moduleTranslation,
2184 builder,
"omp.private.dealloc",
2186 return mlir::emitError(loc,
"failed to inline `dealloc` region of an "
2187 "`omp.private` op in");
2192 for (
auto [privDecl, llvmPrivVar, blockArg] :
2196 ompBuilder->createOMPFreeShared(
2197 builder, llvmPrivVar,
2198 moduleTranslation.
convertType(privDecl.getType()));
2202 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2205 ompBuilder->createOMPFree(ompLoc, allocation.allocatedPtr,
2206 allocation.allocator);
2218 if (mlir::isa<omp::CancelOp, omp::CancellationPointOp>(child))
2235 llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder::InsertPointTy allocaIP,
2237 bool isWorksharing =
false);
2245 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2246 using StorableBodyGenCallbackTy =
2247 llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
2249 auto sectionsOp = cast<omp::SectionsOp>(opInst);
2255 assert(isByRef.size() == sectionsOp.getNumReductionVars());
2259 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
2263 sectionsOp.getNumReductionVars());
2267 cast<omp::BlockArgOpenMPOpInterface>(opInst).getReductionBlockArgs();
2270 sectionsOp, reductionArgs, builder, moduleTranslation, allocaIP,
2271 reductionDecls, privateReductionVariables, reductionVariableMap,
2275 bool isTaskReductionMod =
2276 sectionsOp.getReductionMod() == omp::ReductionModifier::task &&
2277 sectionsOp.getNumReductionVars() > 0;
2282 auto sectionOp = dyn_cast<omp::SectionOp>(op);
2286 Region ®ion = sectionOp.getRegion();
2287 auto sectionCB = [§ionsOp, ®ion, &builder, &moduleTranslation](
2288 InsertPointTy allocaIP, InsertPointTy codeGenIP,
2290 builder.restoreIP(codeGenIP);
2297 sectionsOp.getRegion().getNumArguments());
2298 for (
auto [sectionsArg, sectionArg] : llvm::zip_equal(
2299 sectionsOp.getRegion().getArguments(), region.
getArguments())) {
2300 llvm::Value *llvmVal = moduleTranslation.
lookupValue(sectionsArg);
2302 moduleTranslation.
mapValue(sectionArg, llvmVal);
2309 sectionCBs.push_back(sectionCB);
2315 if (sectionCBs.empty())
2323 if (isTaskReductionMod &&
2325 "__omp_taskred_mod_", builder, allocaIP,
2326 moduleTranslation,
true,
2328 return sectionsOp.emitError(
2329 "failed to emit task reduction modifier initialization");
2331 assert(isa<omp::SectionOp>(*sectionsOp.getRegion().op_begin()));
2336 auto privCB = [&](InsertPointTy, InsertPointTy codeGenIP, llvm::Value &,
2337 llvm::Value &vPtr, llvm::Value *&replacementValue)
2338 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
2339 replacementValue = &vPtr;
2345 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
2349 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2350 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2352 ompLoc, allocaIP, sectionCBs, privCB, finiCB, isCancellable,
2353 sectionsOp.getNowait());
2358 builder.restoreIP(*afterIP);
2361 if (isTaskReductionMod)
2367 sectionsOp, builder, moduleTranslation, allocaIP, reductionDecls,
2368 privateReductionVariables, isByRef, sectionsOp.getNowait());
2375 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2382 assert(isByRef.size() == scopeOp.getNumReductionVars());
2391 scopeOp.getNumReductionVars());
2395 cast<omp::BlockArgOpenMPOpInterface>(*scopeOp).getReductionBlockArgs();
2399 scopeOp, builder, moduleTranslation, privateVarsInfo, allocaIP);
2404 scopeOp, reductionArgs, builder, moduleTranslation, allocaIP,
2405 reductionDecls, privateReductionVariables, reductionVariableMap,
2410 [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
2412 builder.restoreIP(codeGenIP);
2418 return llvm::make_error<PreviouslyReportedError>();
2421 scopeOp, builder, moduleTranslation, privateVarsInfo.
mlirVars,
2423 scopeOp.getPrivateNeedsBarrier())))
2424 return llvm::make_error<PreviouslyReportedError>();
2431 auto finiCB = [&](InsertPointTy codeGenIP) -> llvm::Error {
2432 InsertPointTy oldIP = builder.saveIP();
2433 builder.restoreIP(codeGenIP);
2435 scopeOp.getLoc(), privateVarsInfo)))
2436 return llvm::make_error<PreviouslyReportedError>();
2437 builder.restoreIP(oldIP);
2438 return llvm::Error::success();
2441 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2442 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2443 ompBuilder->createScope(ompLoc, bodyCB, finiCB, scopeOp.getNowait());
2448 builder.restoreIP(*afterIP);
2452 scopeOp, builder, moduleTranslation, allocaIP, reductionDecls,
2453 privateReductionVariables, isByRef, scopeOp.getNowait(),
2461 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2462 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2467 auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
2469 builder.restoreIP(codegenIP);
2471 builder, moduleTranslation)
2474 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
2478 std::optional<ArrayAttr> cpFuncs = singleOp.getCopyprivateSyms();
2481 for (
size_t i = 0, e = cpVars.size(); i < e; ++i) {
2482 llvmCPVars.push_back(moduleTranslation.
lookupValue(cpVars[i]));
2484 singleOp, cast<SymbolRefAttr>((*cpFuncs)[i]));
2485 llvmCPFuncs.push_back(
2489 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2491 ompLoc, bodyCB, finiCB, singleOp.getNowait(), llvmCPVars,
2497 builder.restoreIP(*afterIP);
2501static omp::DistributeOp
2505 omp::DistributeOp distOp;
2506 WalkResult walk = teamsOp.getRegion().walk([&](omp::DistributeOp op) {
2512 if (walk.wasInterrupted() || !distOp)
2516 llvm::cast<mlir::omp::BlockArgOpenMPOpInterface>(teamsOp.getOperation());
2520 for (
auto ra : iface.getReductionBlockArgs())
2521 for (
auto &use : ra.getUses()) {
2522 auto *useOp = use.getOwner();
2524 if (mlir::isa<LLVM::DbgDeclareOp, LLVM::DbgValueOp>(useOp)) {
2525 debugUses.push_back(useOp);
2528 if (!distOp->isProperAncestor(useOp))
2535 for (
auto *use : debugUses)
2544 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2549 unsigned numReductionVars = op.getNumReductionVars();
2553 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
2559 if (doTeamsReduction) {
2560 isByRef =
getIsByRef(op.getReductionByref());
2562 assert(isByRef.size() == op.getNumReductionVars());
2565 llvm::cast<omp::BlockArgOpenMPOpInterface>(*op).getReductionBlockArgs();
2570 op, reductionArgs, builder, moduleTranslation, allocaIP,
2571 reductionDecls, privateReductionVariables, reductionVariableMap,
2576 auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
2579 moduleTranslation, allocaIP, deallocBlocks);
2580 builder.restoreIP(codegenIP);
2586 llvm::Value *numTeamsLower =
nullptr;
2587 if (
Value numTeamsLowerVar = op.getNumTeamsLower())
2588 numTeamsLower = moduleTranslation.
lookupValue(numTeamsLowerVar);
2590 llvm::Value *numTeamsUpper =
nullptr;
2591 if (!op.getNumTeamsUpperVars().empty())
2592 numTeamsUpper = moduleTranslation.
lookupValue(op.getNumTeams(0));
2594 llvm::Value *threadLimit =
nullptr;
2595 if (!op.getThreadLimitVars().empty())
2596 threadLimit = moduleTranslation.
lookupValue(op.getThreadLimit(0));
2598 llvm::Value *ifExpr =
nullptr;
2599 if (
Value ifVar = op.getIfExpr())
2602 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2603 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2605 ompLoc, bodyCB, numTeamsLower, numTeamsUpper, threadLimit, ifExpr);
2610 builder.restoreIP(*afterIP);
2611 if (doTeamsReduction) {
2614 op, builder, moduleTranslation, allocaIP, reductionDecls,
2615 privateReductionVariables, isByRef,
2621static llvm::omp::RTLDependenceKindTy
2624 case mlir::omp::ClauseTaskDepend::taskdependin:
2625 return llvm::omp::RTLDependenceKindTy::DepIn;
2629 case mlir::omp::ClauseTaskDepend::taskdependout:
2630 case mlir::omp::ClauseTaskDepend::taskdependinout:
2631 return llvm::omp::RTLDependenceKindTy::DepInOut;
2632 case mlir::omp::ClauseTaskDepend::taskdependmutexinoutset:
2633 return llvm::omp::RTLDependenceKindTy::DepMutexInOutSet;
2634 case mlir::omp::ClauseTaskDepend::taskdependinoutset:
2635 return llvm::omp::RTLDependenceKindTy::DepInOutSet;
2637 llvm_unreachable(
"unhandled depend kind");
2641 std::optional<ArrayAttr> dependKinds,
OperandRange dependVars,
2644 if (dependVars.empty())
2646 for (
auto dep : llvm::zip(dependVars, dependKinds->getValue())) {
2648 cast<mlir::omp::ClauseTaskDependAttr>(std::get<1>(dep)).getValue();
2650 llvm::Value *depVal = moduleTranslation.
lookupValue(std::get<0>(dep));
2651 llvm::OpenMPIRBuilder::DependData dd(type, depVal->getType(), depVal);
2652 dds.emplace_back(dd);
2664 llvm::IRBuilderBase &llvmBuilder, llvm::OpenMPIRBuilder &ompBuilder,
2666 auto finiCB = [&](llvm::OpenMPIRBuilder::InsertPointTy ip) -> llvm::Error {
2667 llvm::IRBuilderBase::InsertPointGuard guard(llvmBuilder);
2671 llvmBuilder.restoreIP(ip);
2677 cancelTerminators.push_back(llvmBuilder.CreateBr(ip.getBlock()));
2678 return llvm::Error::success();
2683 ompBuilder.pushFinalizationCB(
2693 llvm::OpenMPIRBuilder &ompBuilder,
2694 const llvm::OpenMPIRBuilder::InsertPointTy &afterIP) {
2695 ompBuilder.popFinalizationCB();
2696 llvm::BasicBlock *constructFini = afterIP.getBlock()->getSinglePredecessor();
2697 for (llvm::UncondBrInst *cancelBranch : cancelTerminators)
2698 cancelBranch->setSuccessor(constructFini);
2704class TaskContextStructManager {
2706 TaskContextStructManager(llvm::IRBuilderBase &builder,
2707 LLVM::ModuleTranslation &moduleTranslation,
2708 MutableArrayRef<omp::PrivateClauseOp> privateDecls)
2709 : builder{builder}, moduleTranslation{moduleTranslation},
2710 privateDecls{privateDecls} {}
2716 void generateTaskContextStruct();
2722 void createGEPsToPrivateVars();
2728 SmallVector<llvm::Value *>
2729 createGEPsToPrivateVars(llvm::Value *altStructPtr)
const;
2732 void freeStructPtr();
2734 MutableArrayRef<llvm::Value *> getLLVMPrivateVarGEPs() {
2735 return llvmPrivateVarGEPs;
2738 llvm::Value *getStructPtr() {
return structPtr; }
2741 llvm::IRBuilderBase &builder;
2742 LLVM::ModuleTranslation &moduleTranslation;
2743 MutableArrayRef<omp::PrivateClauseOp> privateDecls;
2746 SmallVector<llvm::Type *> privateVarTypes;
2750 SmallVector<llvm::Value *> llvmPrivateVarGEPs;
2753 llvm::Value *structPtr =
nullptr;
2755 llvm::Type *structTy =
nullptr;
2766 llvm::SmallVector<llvm::Value *> lowerBounds;
2767 llvm::SmallVector<llvm::Value *> upperBounds;
2768 llvm::SmallVector<llvm::Value *> steps;
2769 llvm::SmallVector<llvm::Value *> trips;
2771 llvm::Value *totalTrips;
2773 llvm::Value *lookUpAsI64(mlir::Value val,
const LLVM::ModuleTranslation &mt,
2774 llvm::IRBuilderBase &builder) {
2778 if (v->getType()->isIntegerTy(64))
2780 if (v->getType()->isIntegerTy())
2781 return builder.CreateSExtOrTrunc(v, builder.getInt64Ty());
2786 IteratorInfo(mlir::omp::IteratorOp itersOp,
2787 mlir::LLVM::ModuleTranslation &moduleTranslation,
2788 llvm::IRBuilderBase &builder) {
2789 dims = itersOp.getLoopLowerBounds().size();
2790 lowerBounds.resize(dims);
2791 upperBounds.resize(dims);
2795 for (
unsigned d = 0; d < dims; ++d) {
2796 llvm::Value *lb = lookUpAsI64(itersOp.getLoopLowerBounds()[d],
2797 moduleTranslation, builder);
2798 llvm::Value *ub = lookUpAsI64(itersOp.getLoopUpperBounds()[d],
2799 moduleTranslation, builder);
2801 lookUpAsI64(itersOp.getLoopSteps()[d], moduleTranslation, builder);
2802 assert(lb && ub && st &&
2803 "Expect lowerBounds, upperBounds, and steps in IteratorOp");
2804 assert((!llvm::isa<llvm::ConstantInt>(st) ||
2805 !llvm::cast<llvm::ConstantInt>(st)->isZero()) &&
2806 "Expect non-zero step in IteratorOp");
2808 lowerBounds[d] = lb;
2809 upperBounds[d] = ub;
2813 llvm::Value *diff = builder.CreateSub(ub, lb);
2814 llvm::Value *
div = builder.CreateSDiv(diff, st);
2815 trips[d] = builder.CreateAdd(
2816 div, llvm::ConstantInt::get(builder.getInt64Ty(), 1));
2819 totalTrips = llvm::ConstantInt::get(builder.getInt64Ty(), 1);
2820 for (
unsigned d = 0; d < dims; ++d)
2821 totalTrips = builder.CreateMul(totalTrips, trips[d]);
2824 unsigned getDims()
const {
return dims; }
2825 llvm::ArrayRef<llvm::Value *> getLowerBounds()
const {
return lowerBounds; }
2826 llvm::ArrayRef<llvm::Value *> getUpperBounds()
const {
return upperBounds; }
2827 llvm::ArrayRef<llvm::Value *> getSteps()
const {
return steps; }
2828 llvm::ArrayRef<llvm::Value *> getTrips()
const {
return trips; }
2829 llvm::Value *getTotalTrips()
const {
return totalTrips; }
2834void TaskContextStructManager::generateTaskContextStruct() {
2835 if (privateDecls.empty())
2837 privateVarTypes.reserve(privateDecls.size());
2839 for (omp::PrivateClauseOp &privOp : privateDecls) {
2842 if (!privOp.readsFromMold())
2844 Type mlirType = privOp.getType();
2845 privateVarTypes.push_back(moduleTranslation.
convertType(mlirType));
2848 if (privateVarTypes.empty())
2851 structTy = llvm::StructType::get(moduleTranslation.
getLLVMContext(),
2854 llvm::DataLayout dataLayout =
2855 builder.GetInsertBlock()->getModule()->getDataLayout();
2856 llvm::Type *intPtrTy = builder.getIntPtrTy(dataLayout);
2857 llvm::Constant *allocSize = llvm::ConstantExpr::getSizeOf(structTy);
2860 structPtr = builder.CreateMalloc(intPtrTy, structTy, allocSize,
2862 "omp.task.context_ptr");
2865SmallVector<llvm::Value *> TaskContextStructManager::createGEPsToPrivateVars(
2866 llvm::Value *altStructPtr)
const {
2867 SmallVector<llvm::Value *> ret;
2870 ret.reserve(privateDecls.size());
2871 llvm::Value *zero = builder.getInt32(0);
2873 for (
auto privDecl : privateDecls) {
2874 if (!privDecl.readsFromMold()) {
2876 ret.push_back(
nullptr);
2879 llvm::Value *iVal = builder.getInt32(i);
2880 llvm::Value *gep = builder.CreateGEP(structTy, altStructPtr, {zero, iVal});
2887void TaskContextStructManager::createGEPsToPrivateVars() {
2889 assert(privateVarTypes.empty());
2893 llvmPrivateVarGEPs = createGEPsToPrivateVars(structPtr);
2896void TaskContextStructManager::freeStructPtr() {
2900 llvm::IRBuilderBase::InsertPointGuard guard{builder};
2902 builder.SetInsertPoint(builder.GetInsertBlock()->getTerminator());
2903 builder.CreateFree(structPtr);
2907 llvm::OpenMPIRBuilder &ompBuilder,
2908 llvm::Value *affinityList, llvm::Value *
index,
2909 llvm::Value *addr, llvm::Value *len) {
2910 llvm::StructType *kmpTaskAffinityInfoTy =
2911 ompBuilder.getKmpTaskAffinityInfoTy();
2912 llvm::Value *entry = builder.CreateInBoundsGEP(
2913 kmpTaskAffinityInfoTy, affinityList,
index,
"omp.affinity.entry");
2915 addr = builder.CreatePtrToInt(addr, kmpTaskAffinityInfoTy->getElementType(0));
2916 len = builder.CreateIntCast(len, kmpTaskAffinityInfoTy->getElementType(1),
2918 llvm::Value *flags = builder.getInt32(0);
2920 builder.CreateStore(addr,
2921 builder.CreateStructGEP(kmpTaskAffinityInfoTy, entry, 0));
2922 builder.CreateStore(len,
2923 builder.CreateStructGEP(kmpTaskAffinityInfoTy, entry, 1));
2924 builder.CreateStore(flags,
2925 builder.CreateStructGEP(kmpTaskAffinityInfoTy, entry, 2));
2929 llvm::IRBuilderBase &builder,
2931 llvm::Value *affinityList) {
2932 for (
auto [i, affinityVar] : llvm::enumerate(affinityVars)) {
2933 auto entryOp = affinityVar.getDefiningOp<mlir::omp::AffinityEntryOp>();
2934 assert(entryOp &&
"affinity item must be omp.affinity_entry");
2936 llvm::Value *addr = moduleTranslation.
lookupValue(entryOp.getAddr());
2937 llvm::Value *len = moduleTranslation.
lookupValue(entryOp.getLen());
2938 assert(addr && len &&
"expect affinity addr and len to be non-null");
2940 affinityList, builder.getInt64(i), addr, len);
2944static mlir::LogicalResult
2947 llvm::IRBuilderBase &builder,
2949 llvm::Value *tmp = linearIV;
2950 for (
int d = (
int)iterInfo.getDims() - 1; d >= 0; --d) {
2951 llvm::Value *trip = iterInfo.getTrips()[d];
2953 llvm::Value *idx = builder.CreateURem(tmp, trip);
2955 tmp = builder.CreateUDiv(tmp, trip);
2958 llvm::Value *physIV = builder.CreateAdd(
2959 iterInfo.getLowerBounds()[d],
2960 builder.CreateMul(idx, iterInfo.getSteps()[d]),
"omp.it.phys_iv");
2966 moduleTranslation.
mapBlock(&iteratorRegionBlock, builder.GetInsertBlock());
2967 if (mlir::failed(moduleTranslation.
convertBlock(iteratorRegionBlock,
2970 return mlir::failure();
2972 return mlir::success();
2978static mlir::LogicalResult
2981 IteratorInfo &iterInfo, llvm::StringRef loopName,
2986 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
2988 auto bodyGen = [&](llvm::OpenMPIRBuilder::InsertPointTy bodyIP,
2989 llvm::Value *linearIV) -> llvm::Error {
2990 llvm::IRBuilderBase::InsertPointGuard guard(builder);
2991 builder.restoreIP(bodyIP);
2994 builder, moduleTranslation))) {
2995 return llvm::make_error<llvm::StringError>(
2996 "failed to convert iterator region", llvm::inconvertibleErrorCode());
3000 mlir::dyn_cast<mlir::omp::YieldOp>(iteratorRegionBlock.
getTerminator());
3001 assert(yield && yield.getResults().size() == 1 &&
3002 "expect omp.yield in iterator region to have one result");
3004 genStoreEntry(linearIV, yield);
3010 return llvm::Error::success();
3013 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
3015 loc, iterInfo.getTotalTrips(), bodyGen, loopName);
3019 builder.restoreIP(*afterIP);
3021 return mlir::success();
3024static mlir::LogicalResult
3027 llvm::OpenMPIRBuilder::AffinityData &ad) {
3029 if (taskOp.getAffinityVars().empty() && taskOp.getIterated().empty()) {
3032 return mlir::success();
3036 llvm::StructType *kmpTaskAffinityInfoTy =
3039 auto allocateAffinityList = [&](llvm::Value *count) -> llvm::Value * {
3040 llvm::IRBuilderBase::InsertPointGuard guard(builder);
3041 if (llvm::isa<llvm::Constant>(count) || llvm::isa<llvm::Argument>(count))
3043 return builder.CreateAlloca(kmpTaskAffinityInfoTy, count,
3044 "omp.affinity_list");
3047 auto createAffinity =
3048 [&](llvm::Value *count,
3049 llvm::Value *info) -> llvm::OpenMPIRBuilder::AffinityData {
3050 llvm::OpenMPIRBuilder::AffinityData ad{};
3051 ad.Count = builder.CreateTrunc(count, builder.getInt32Ty());
3053 builder.CreatePointerBitCastOrAddrSpaceCast(info, builder.getPtrTy(0));
3057 if (!taskOp.getAffinityVars().empty()) {
3058 llvm::Value *count = llvm::ConstantInt::get(
3059 builder.getInt64Ty(), taskOp.getAffinityVars().size());
3060 llvm::Value *list = allocateAffinityList(count);
3063 ads.emplace_back(createAffinity(count, list));
3066 if (!taskOp.getIterated().empty()) {
3067 for (
auto [i, iter] : llvm::enumerate(taskOp.getIterated())) {
3068 auto itersOp = iter.getDefiningOp<omp::IteratorOp>();
3069 assert(itersOp &&
"iterated value must be defined by omp.iterator");
3070 IteratorInfo iterInfo(itersOp, moduleTranslation, builder);
3071 llvm::Value *affList = allocateAffinityList(iterInfo.getTotalTrips());
3073 itersOp, builder, moduleTranslation, iterInfo,
"iterator",
3074 [&](llvm::Value *linearIV, mlir::omp::YieldOp yield) {
3075 auto entryOp = yield.getResults()[0]
3076 .getDefiningOp<mlir::omp::AffinityEntryOp>();
3077 assert(entryOp &&
"expect yield produce an affinity entry");
3084 affList, linearIV, addr, len);
3086 return llvm::failure();
3087 ads.emplace_back(createAffinity(iterInfo.getTotalTrips(), affList));
3091 llvm::Value *totalAffinityCount = builder.getInt32(0);
3092 for (
const auto &affinity : ads)
3093 totalAffinityCount = builder.CreateAdd(
3095 builder.CreateIntCast(affinity.Count, builder.getInt32Ty(),
3098 llvm::Value *affinityInfo = ads.front().Info;
3099 if (ads.size() > 1) {
3100 llvm::StructType *kmpTaskAffinityInfoTy =
3102 llvm::Value *affinityInfoElemSize = builder.getInt64(
3103 moduleTranslation.
getLLVMModule()->getDataLayout().getTypeAllocSize(
3104 kmpTaskAffinityInfoTy));
3106 llvm::Value *packedAffinityInfo = allocateAffinityList(totalAffinityCount);
3107 llvm::Value *packedAffinityInfoOffset = builder.getInt32(0);
3108 for (
const auto &affinity : ads) {
3109 llvm::Value *affinityCount = builder.CreateIntCast(
3110 affinity.Count, builder.getInt32Ty(),
false);
3111 llvm::Value *affinityCountInt64 = builder.CreateIntCast(
3112 affinityCount, builder.getInt64Ty(),
false);
3113 llvm::Value *affinityInfoSize =
3114 builder.CreateMul(affinityCountInt64, affinityInfoElemSize);
3116 llvm::Value *packedAffinityInfoIndex = builder.CreateIntCast(
3117 packedAffinityInfoOffset, kmpTaskAffinityInfoTy->getElementType(0),
3119 packedAffinityInfoIndex = builder.CreateInBoundsGEP(
3120 kmpTaskAffinityInfoTy, packedAffinityInfo, packedAffinityInfoIndex);
3122 builder.CreateMemCpy(
3123 packedAffinityInfoIndex, llvm::Align(1),
3124 builder.CreatePointerBitCastOrAddrSpaceCast(
3125 affinity.Info, builder.getPtrTy(packedAffinityInfoIndex->getType()
3126 ->getPointerAddressSpace())),
3127 llvm::Align(1), affinityInfoSize);
3129 packedAffinityInfoOffset =
3130 builder.CreateAdd(packedAffinityInfoOffset, affinityCount);
3133 affinityInfo = packedAffinityInfo;
3136 ad.Count = totalAffinityCount;
3137 ad.Info = affinityInfo;
3139 return mlir::success();
3145static mlir::LogicalResult
3148 std::optional<ArrayAttr> dependIteratedKinds,
3149 llvm::IRBuilderBase &builder,
3151 llvm::OpenMPIRBuilder::DependenciesInfo &taskDeps) {
3152 if (dependIterated.empty()) {
3155 return mlir::success();
3159 llvm::Type *dependInfoTy = ompBuilder.DependInfo;
3160 unsigned numLocator = dependVars.size();
3163 llvm::Value *totalCount =
3164 llvm::ConstantInt::get(builder.getInt64Ty(), numLocator);
3167 for (
auto iter : dependIterated) {
3168 auto itersOp = iter.getDefiningOp<mlir::omp::IteratorOp>();
3169 assert(itersOp &&
"depend_iterated value must be defined by omp.iterator");
3170 iterInfos.emplace_back(itersOp, moduleTranslation, builder);
3172 builder.CreateAdd(totalCount, iterInfos.back().getTotalTrips());
3177 llvm::Constant *allocSize = llvm::ConstantExpr::getSizeOf(dependInfoTy);
3178 llvm::Value *depArray =
3179 builder.CreateMalloc(ompBuilder.SizeTy, dependInfoTy, allocSize,
3180 totalCount,
nullptr,
".dep.arr.addr");
3183 if (numLocator > 0) {
3186 for (
auto [i, dd] : llvm::enumerate(dds)) {
3187 llvm::Value *idx = llvm::ConstantInt::get(builder.getInt64Ty(), i);
3188 llvm::Value *entry =
3189 builder.CreateInBoundsGEP(dependInfoTy, depArray, idx);
3190 ompBuilder.emitTaskDependency(builder, entry, dd);
3195 llvm::Value *offset =
3196 llvm::ConstantInt::get(builder.getInt64Ty(), numLocator);
3197 for (
auto [i, iterInfo] : llvm::enumerate(iterInfos)) {
3198 auto kindAttr = cast<mlir::omp::ClauseTaskDependAttr>(
3199 dependIteratedKinds->getValue()[i]);
3200 llvm::omp::RTLDependenceKindTy rtlKind =
3203 auto itersOp = dependIterated[i].getDefiningOp<mlir::omp::IteratorOp>();
3205 itersOp, builder, moduleTranslation, iterInfo,
"dep_iterator",
3206 [&](llvm::Value *linearIV, mlir::omp::YieldOp yield) {
3208 moduleTranslation.
lookupValue(yield.getResults()[0]);
3209 llvm::Value *idx = builder.CreateAdd(offset, linearIV);
3210 llvm::Value *entry =
3211 builder.CreateInBoundsGEP(dependInfoTy, depArray, idx);
3212 ompBuilder.emitTaskDependency(
3214 llvm::OpenMPIRBuilder::DependData{rtlKind, addr->getType(),
3217 return mlir::failure();
3220 offset = builder.CreateAdd(offset, iterInfo.getTotalTrips());
3223 taskDeps.DepArray = depArray;
3224 taskDeps.NumDeps = builder.CreateTrunc(totalCount, builder.getInt32Ty());
3225 return mlir::success();
3232 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
3237 TaskContextStructManager taskStructMgr{builder, moduleTranslation,
3249 InsertPointTy allocaIP =
3254 assert(builder.GetInsertPoint() == builder.GetInsertBlock()->end());
3255 llvm::BasicBlock *taskStartBlock = llvm::BasicBlock::Create(
3256 builder.getContext(),
"omp.task.start",
3257 builder.GetInsertBlock()->getParent());
3258 llvm::Instruction *branchToTaskStartBlock = builder.CreateBr(taskStartBlock);
3259 builder.SetInsertPoint(branchToTaskStartBlock);
3262 llvm::BasicBlock *copyBlock =
3263 splitBB(builder,
true,
"omp.private.copy");
3264 llvm::BasicBlock *initBlock =
3265 splitBB(builder,
true,
"omp.private.init");
3281 moduleTranslation, allocaIP, deallocBlocks);
3284 builder.SetInsertPoint(initBlock->getTerminator());
3287 taskStructMgr.generateTaskContextStruct();
3294 taskStructMgr.createGEPsToPrivateVars();
3296 for (
auto [privDecl, mlirPrivVar, blockArg, llvmPrivateVarAlloc] :
3299 taskStructMgr.getLLVMPrivateVarGEPs())) {
3301 if (!privDecl.readsFromMold())
3303 assert(llvmPrivateVarAlloc &&
3304 "reads from mold so shouldn't have been skipped");
3307 initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar,
3308 blockArg, llvmPrivateVarAlloc, initBlock);
3309 if (!privateVarOrErr)
3310 return handleError(privateVarOrErr, *taskOp.getOperation());
3319 [[maybe_unused]] llvm::Value *llvmPrivateVar = llvmPrivateVarAlloc;
3320 if ((privateVarOrErr.get() != llvmPrivateVarAlloc) &&
3321 !mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
3322 builder.CreateStore(privateVarOrErr.get(), llvmPrivateVarAlloc);
3324 llvmPrivateVar = builder.CreateLoad(privateVarOrErr.get()->getType(),
3325 llvmPrivateVarAlloc);
3327 assert(llvmPrivateVar->getType() ==
3328 moduleTranslation.
convertType(blockArg.getType()));
3338 taskOp, builder, moduleTranslation, privateVarsInfo.
mlirVars,
3339 taskStructMgr.getLLVMPrivateVarGEPs(), privateVarsInfo.
privatizers,
3340 taskOp.getPrivateNeedsBarrier())))
3341 return llvm::failure();
3343 llvm::OpenMPIRBuilder::AffinityData ad;
3345 return llvm::failure();
3355 taskOp.getOperation(), taskOp.getInReductionSyms(),
"omp.task",
3356 "in_reduction", inRedDecls)))
3359 inRedOrigPtrs.reserve(inRedDecls.size());
3360 for (
Value v : taskOp.getInReductionVars())
3361 inRedOrigPtrs.push_back(moduleTranslation.
lookupValue(v));
3364 builder.SetInsertPoint(taskStartBlock);
3367 [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
3372 moduleTranslation, allocaIP, deallocBlocks);
3375 builder.restoreIP(codegenIP);
3377 llvm::BasicBlock *privInitBlock =
nullptr;
3379 for (
auto [i, zip] : llvm::enumerate(llvm::zip_equal(
3382 auto [blockArg, privDecl, mlirPrivVar] = zip;
3384 if (privDecl.readsFromMold())
3387 llvm::IRBuilderBase::InsertPointGuard guard(builder);
3388 llvm::Type *llvmAllocType =
3389 moduleTranslation.
convertType(privDecl.getType());
3390 builder.SetInsertPoint(allocaIP.getBlock()->getTerminator());
3391 llvm::Value *llvmPrivateVar = builder.CreateAlloca(
3392 llvmAllocType,
nullptr,
"omp.private.alloc");
3395 initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar,
3396 blockArg, llvmPrivateVar, privInitBlock);
3397 if (!privateVarOrError)
3398 return privateVarOrError.takeError();
3399 moduleTranslation.
mapValue(blockArg, privateVarOrError.get());
3400 privateVarsInfo.
llvmVars[i] = privateVarOrError.get();
3403 taskStructMgr.createGEPsToPrivateVars();
3404 for (
auto [i, llvmPrivVar] :
3405 llvm::enumerate(taskStructMgr.getLLVMPrivateVarGEPs())) {
3407 assert(privateVarsInfo.
llvmVars[i] &&
3408 "This is added in the loop above");
3411 privateVarsInfo.
llvmVars[i] = llvmPrivVar;
3416 for (
auto [blockArg, llvmPrivateVar, privateDecl] :
3420 if (!privateDecl.readsFromMold())
3423 if (!mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
3424 llvmPrivateVar = builder.CreateLoad(
3425 moduleTranslation.
convertType(blockArg.getType()), llvmPrivateVar);
3427 assert(llvmPrivateVar->getType() ==
3428 moduleTranslation.
convertType(blockArg.getType()));
3429 moduleTranslation.
mapValue(blockArg, llvmPrivateVar);
3440 if (!inRedDecls.empty()) {
3441 auto iface = cast<omp::BlockArgOpenMPOpInterface>(taskOp.getOperation());
3444 llvm::LLVMContext &llvmCtx = m->getContext();
3445 llvm::OpenMPIRBuilder::LocationDescription bodyLoc(builder);
3446 uint32_t srcLocSize;
3447 llvm::Constant *srcLocStr =
3448 ompB.getOrCreateSrcLocStr(bodyLoc, srcLocSize);
3449 llvm::Value *bodyIdent = ompB.getOrCreateIdent(srcLocStr, srcLocSize);
3452 ompB.updateToLocation(bodyLoc);
3453 llvm::Value *bodyGtid = ompB.getOrCreateThreadID(bodyIdent);
3454 llvm::FunctionCallee getThData = ompB.getOrCreateRuntimeFunction(
3455 *m, llvm::omp::OMPRTL___kmpc_task_reduction_get_th_data);
3456 llvm::Type *ptrTy = llvm::PointerType::getUnqual(llvmCtx);
3457 llvm::Value *nullDesc = llvm::ConstantPointerNull::get(ptrTy);
3459 for (
auto [blockArg, origPtr] :
3460 llvm::zip_equal(inRedBlockArgs, inRedOrigPtrs)) {
3467 llvm::Value *lookupPtr = origPtr;
3468 if (
auto *origPtrTy =
3469 llvm::dyn_cast<llvm::PointerType>(lookupPtr->getType());
3470 origPtrTy && origPtrTy->getAddressSpace() != 0)
3471 lookupPtr = builder.CreateAddrSpaceCast(lookupPtr, ptrTy);
3472 llvm::Value *priv = builder.CreateCall(
3473 getThData, {bodyGtid, nullDesc, lookupPtr},
"omp.inred.priv");
3474 if (
auto *argPtrTy = llvm::dyn_cast<llvm::PointerType>(
3475 moduleTranslation.
convertType(blockArg.getType()));
3476 argPtrTy && argPtrTy->getAddressSpace() != 0)
3477 priv = builder.CreateAddrSpaceCast(priv, argPtrTy);
3478 moduleTranslation.
mapValue(blockArg, priv);
3483 taskOp.getRegion(),
"omp.task.region", builder, moduleTranslation);
3484 if (failed(
handleError(continuationBlockOrError, *taskOp)))
3485 return llvm::make_error<PreviouslyReportedError>();
3487 builder.SetInsertPoint(continuationBlockOrError.get()->getTerminator());
3490 taskOp.getLoc(), privateVarsInfo)))
3491 return llvm::make_error<PreviouslyReportedError>();
3494 taskStructMgr.freeStructPtr();
3496 return llvm::Error::success();
3505 llvm::omp::Directive::OMPD_taskgroup);
3507 llvm::OpenMPIRBuilder::DependenciesInfo dependencies;
3508 if (failed(
buildDependData(taskOp.getDependVars(), taskOp.getDependKinds(),
3509 taskOp.getDependIterated(),
3510 taskOp.getDependIteratedKinds(), builder,
3511 moduleTranslation, dependencies)))
3514 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
3515 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
3517 ompLoc, allocaIP, deallocBlocks, bodyCB, !taskOp.getUntied(),
3519 moduleTranslation.
lookupValue(taskOp.getIfExpr()), dependencies, ad,
3520 taskOp.getMergeable(),
3521 moduleTranslation.
lookupValue(taskOp.getEventHandle()),
3522 moduleTranslation.
lookupValue(taskOp.getPriority()));
3530 builder.restoreIP(*afterIP);
3532 if (dependencies.DepArray)
3533 builder.CreateFree(dependencies.DepArray);
3542 llvm::IRBuilderBase &builder,
3550 loopWrapperOp.getRegion(),
"omp.taskloop.wrapper.region", builder,
3553 if (failed(
handleError(continuationBlockOrError, opInst)))
3556 builder.SetInsertPoint(continuationBlockOrError.get());
3564static llvm::Expected<llvm::Value *>
3567 llvm::IRBuilderBase &builder) {
3568 if (llvm::Value *mapped = moduleTranslation.
lookupValue(value))
3573 return llvm::make_error<llvm::StringError>(
3574 "value is a block argument and is not mapped",
3575 llvm::inconvertibleErrorCode());
3577 return llvm::make_error<llvm::StringError>(
3578 "unsupported op defining taskloop loop bound",
3579 llvm::inconvertibleErrorCode());
3589 if (!operandOrError)
3590 return operandOrError.takeError();
3591 moduleTranslation.
mapValue(operand, *operandOrError);
3592 mappingsToRemove.push_back(operand);
3596 return llvm::make_error<llvm::StringError>(
3597 "failed to convert op defining taskloop loop bound",
3598 llvm::inconvertibleErrorCode());
3601 assert(
result &&
"expected conversion of loop bound op to produce a value");
3605 mappingsToRemove.push_back(resultValue);
3607 for (
Value mappedValue : mappingsToRemove)
3616 llvm::Value *&lbVal, llvm::Value *&ubVal,
3617 llvm::Value *&stepVal) {
3625 return firstLbOrErr.takeError();
3627 llvm::Type *boundType = (*firstLbOrErr)->getType();
3628 ubVal = builder.getIntN(boundType->getIntegerBitWidth(), 1);
3629 if (loopOp.getCollapseNumLoops() > 1) {
3647 for (uint64_t i = 0; i < loopOp.getCollapseNumLoops(); i++) {
3649 i == 0 ? std::move(firstLbOrErr)
3653 return lbOrErr.takeError();
3655 upperBounds[i], moduleTranslation, builder);
3657 return ubOrErr.takeError();
3661 return stepOrErr.takeError();
3663 llvm::Value *loopLb = *lbOrErr;
3664 llvm::Value *loopUb = *ubOrErr;
3665 llvm::Value *loopStep = *stepOrErr;
3671 llvm::Value *loopLbMinusOne = builder.CreateSub(
3672 loopLb, builder.getIntN(boundType->getIntegerBitWidth(), 1));
3673 llvm::Value *loopUbMinusOne = builder.CreateSub(
3674 loopUb, builder.getIntN(boundType->getIntegerBitWidth(), 1));
3675 llvm::Value *boundsCmp = builder.CreateICmpSLT(loopLb, loopUb);
3676 llvm::Value *ubMinusLb = builder.CreateSub(loopUb, loopLbMinusOne);
3677 llvm::Value *lbMinusUb = builder.CreateSub(loopLb, loopUbMinusOne);
3678 llvm::Value *loopTripCount =
3679 builder.CreateSelect(boundsCmp, ubMinusLb, lbMinusUb);
3680 loopTripCount = builder.CreateBinaryIntrinsic(
3681 llvm::Intrinsic::abs, loopTripCount, builder.getFalse());
3685 llvm::Value *loopTripCountDivStep =
3686 builder.CreateSDiv(loopTripCount, loopStep);
3687 loopTripCountDivStep = builder.CreateBinaryIntrinsic(
3688 llvm::Intrinsic::abs, loopTripCountDivStep, builder.getFalse());
3689 llvm::Value *loopTripCountRem =
3690 builder.CreateSRem(loopTripCount, loopStep);
3691 loopTripCountRem = builder.CreateBinaryIntrinsic(
3692 llvm::Intrinsic::abs, loopTripCountRem, builder.getFalse());
3693 llvm::Value *needsRoundUp = builder.CreateICmpNE(
3695 builder.getIntN(loopTripCountRem->getType()->getIntegerBitWidth(),
3698 builder.CreateAdd(loopTripCountDivStep,
3699 builder.CreateZExtOrTrunc(
3700 needsRoundUp, loopTripCountDivStep->getType()));
3701 ubVal = builder.CreateMul(ubVal, loopTripCount);
3703 lbVal = builder.getIntN(boundType->getIntegerBitWidth(), 1);
3704 stepVal = builder.getIntN(boundType->getIntegerBitWidth(), 1);
3709 return ubOrErr.takeError();
3713 return stepOrErr.takeError();
3714 lbVal = *firstLbOrErr;
3716 stepVal = *stepOrErr;
3719 assert(lbVal !=
nullptr &&
"Expected value for lbVal");
3720 assert(ubVal !=
nullptr &&
"Expected value for ubVal");
3721 assert(stepVal !=
nullptr &&
"Expected value for stepVal");
3722 return llvm::Error::success();
3728 llvm::IRBuilderBase &builder,
3730 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
3732 omp::TaskloopWrapperOp loopWrapperOp = contextOp.getLoopOp();
3740 TaskContextStructManager taskStructMgr{builder, moduleTranslation,
3744 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
3747 assert(builder.GetInsertPoint() == builder.GetInsertBlock()->end());
3748 llvm::BasicBlock *taskloopStartBlock = llvm::BasicBlock::Create(
3749 builder.getContext(),
"omp.taskloop.wrapper.start",
3750 builder.GetInsertBlock()->getParent());
3751 llvm::Instruction *branchToTaskloopStartBlock =
3752 builder.CreateBr(taskloopStartBlock);
3753 builder.SetInsertPoint(branchToTaskloopStartBlock);
3755 llvm::BasicBlock *copyBlock =
3756 splitBB(builder,
true,
"omp.private.copy");
3757 llvm::BasicBlock *initBlock =
3758 splitBB(builder,
true,
"omp.private.init");
3761 moduleTranslation, allocaIP, deallocBlocks);
3764 builder.SetInsertPoint(initBlock->getTerminator());
3767 taskStructMgr.generateTaskContextStruct();
3768 taskStructMgr.createGEPsToPrivateVars();
3770 llvmFirstPrivateVars.resize(privateVarsInfo.
blockArgs.size());
3772 for (
auto [i, zip] : llvm::enumerate(llvm::zip_equal(
3774 privateVarsInfo.
blockArgs, taskStructMgr.getLLVMPrivateVarGEPs()))) {
3775 auto [privDecl, mlirPrivVar, blockArg, llvmPrivateVarAlloc] = zip;
3777 if (!privDecl.readsFromMold())
3779 assert(llvmPrivateVarAlloc &&
3780 "reads from mold so shouldn't have been skipped");
3783 initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar,
3784 blockArg, llvmPrivateVarAlloc, initBlock);
3785 if (!privateVarOrErr)
3786 return handleError(privateVarOrErr, *contextOp.getOperation());
3788 llvmFirstPrivateVars[i] = privateVarOrErr.get();
3790 llvm::IRBuilderBase::InsertPointGuard guard(builder);
3791 builder.SetInsertPoint(builder.GetInsertBlock()->getTerminator());
3793 [[maybe_unused]] llvm::Value *llvmPrivateVar = llvmPrivateVarAlloc;
3794 if ((privateVarOrErr.get() != llvmPrivateVarAlloc) &&
3795 !mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
3796 builder.CreateStore(privateVarOrErr.get(), llvmPrivateVarAlloc);
3798 llvmPrivateVar = builder.CreateLoad(privateVarOrErr.get()->getType(),
3799 llvmPrivateVarAlloc);
3801 assert(llvmPrivateVar->getType() ==
3802 moduleTranslation.
convertType(blockArg.getType()));
3808 contextOp, builder, moduleTranslation, privateVarsInfo.
mlirVars,
3809 taskStructMgr.getLLVMPrivateVarGEPs(), privateVarsInfo.
privatizers,
3810 contextOp.getPrivateNeedsBarrier())))
3811 return llvm::failure();
3821 contextOp.getOperation(), contextOp.getReductionSyms(),
3822 "omp.taskloop.context",
"reduction", redDecls)))
3826 contextOp.getOperation(), contextOp.getInReductionSyms(),
3827 "omp.taskloop.context",
"in_reduction", inRedDecls)))
3833 redOrigPtrs.reserve(redDecls.size());
3834 for (
Value v : contextOp.getReductionVars())
3835 redOrigPtrs.push_back(moduleTranslation.
lookupValue(v));
3837 inRedOrigPtrs.reserve(inRedDecls.size());
3838 for (
Value v : contextOp.getInReductionVars())
3839 inRedOrigPtrs.push_back(moduleTranslation.
lookupValue(v));
3843 builder.SetInsertPoint(taskloopStartBlock);
3845 llvm::OpenMPIRBuilder &ompBuilderRef = *moduleTranslation.
getOpenMPBuilder();
3852 bool implicitTaskgroup = !redDecls.empty();
3853 llvm::Value *redDesc =
nullptr;
3854 if (implicitTaskgroup) {
3855 llvm::OpenMPIRBuilder::LocationDescription redLoc(builder);
3856 uint32_t srcLocSize;
3857 llvm::Constant *srcLocStr =
3858 ompBuilderRef.getOrCreateSrcLocStr(redLoc, srcLocSize);
3859 llvm::Value *ident = ompBuilderRef.getOrCreateIdent(srcLocStr, srcLocSize);
3862 ompBuilderRef.updateToLocation(redLoc);
3863 llvm::Value *outerGtid = ompBuilderRef.getOrCreateThreadID(ident);
3864 llvm::FunctionCallee taskgroupFn = ompBuilderRef.getOrCreateRuntimeFunction(
3865 *module, llvm::omp::OMPRTL___kmpc_taskgroup);
3866 builder.CreateCall(taskgroupFn, {ident, outerGtid});
3869 "__omp_taskloop_taskred_", builder,
3870 allocaIP, moduleTranslation);
3875 auto loopOp = cast<omp::LoopNestOp>(loopWrapperOp.getWrappedLoop());
3876 llvm::Value *lbVal =
nullptr;
3877 llvm::Value *ubVal =
nullptr;
3878 llvm::Value *stepVal =
nullptr;
3880 loopOp, builder, moduleTranslation, lbVal, ubVal, stepVal))
3884 [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
3889 moduleTranslation, allocaIP, deallocBlocks);
3892 builder.restoreIP(codegenIP);
3894 llvm::BasicBlock *privInitBlock =
nullptr;
3896 for (
auto [i, zip] : llvm::enumerate(llvm::zip_equal(
3899 auto [blockArg, privDecl, mlirPrivVar] = zip;
3901 if (privDecl.readsFromMold())
3904 llvm::IRBuilderBase::InsertPointGuard guard(builder);
3905 llvm::Type *llvmAllocType =
3906 moduleTranslation.
convertType(privDecl.getType());
3907 builder.SetInsertPoint(allocaIP.getBlock()->getTerminator());
3908 llvm::Value *llvmPrivateVar = builder.CreateAlloca(
3909 llvmAllocType,
nullptr,
"omp.private.alloc");
3912 initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar,
3913 blockArg, llvmPrivateVar, privInitBlock);
3914 if (!privateVarOrError)
3915 return privateVarOrError.takeError();
3916 moduleTranslation.
mapValue(blockArg, privateVarOrError.get());
3917 privateVarsInfo.
llvmVars[i] = privateVarOrError.get();
3920 taskStructMgr.createGEPsToPrivateVars();
3921 for (
auto [i, llvmPrivVar] :
3922 llvm::enumerate(taskStructMgr.getLLVMPrivateVarGEPs())) {
3924 assert(privateVarsInfo.
llvmVars[i] &&
3925 "This is added in the loop above");
3928 privateVarsInfo.
llvmVars[i] = llvmPrivVar;
3933 for (
auto [blockArg, llvmPrivateVar, privateDecl] :
3937 if (!privateDecl.readsFromMold())
3940 if (!mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
3941 llvmPrivateVar = builder.CreateLoad(
3942 moduleTranslation.
convertType(blockArg.getType()), llvmPrivateVar);
3944 assert(llvmPrivateVar->getType() ==
3945 moduleTranslation.
convertType(blockArg.getType()));
3946 moduleTranslation.
mapValue(blockArg, llvmPrivateVar);
3958 if (!redDecls.empty() || !inRedDecls.empty()) {
3960 cast<omp::BlockArgOpenMPOpInterface>(contextOp.getOperation());
3963 llvm::LLVMContext &llvmCtx = m->getContext();
3964 llvm::OpenMPIRBuilder::LocationDescription bodyLoc(builder);
3965 uint32_t srcLocSize;
3966 llvm::Constant *srcLocStr =
3967 ompB.getOrCreateSrcLocStr(bodyLoc, srcLocSize);
3968 llvm::Value *bodyIdent = ompB.getOrCreateIdent(srcLocStr, srcLocSize);
3971 ompB.updateToLocation(bodyLoc);
3972 llvm::Value *bodyGtid = ompB.getOrCreateThreadID(bodyIdent);
3973 llvm::FunctionCallee getThData = ompB.getOrCreateRuntimeFunction(
3974 *m, llvm::omp::OMPRTL___kmpc_task_reduction_get_th_data);
3975 llvm::Type *ptrTy = llvm::PointerType::getUnqual(llvmCtx);
3985 auto remapReductionArg = [&](
BlockArgument blockArg, llvm::Value *desc,
3986 llvm::Value *origPtr,
3987 const llvm::Twine &name) {
3988 if (
auto *origPtrTy =
3989 llvm::dyn_cast<llvm::PointerType>(origPtr->getType());
3990 origPtrTy && origPtrTy->getAddressSpace() != 0)
3991 origPtr = builder.CreateAddrSpaceCast(origPtr, ptrTy);
3993 builder.CreateCall(getThData, {bodyGtid, desc, origPtr}, name);
3994 if (
auto *argPtrTy = llvm::dyn_cast<llvm::PointerType>(
3996 argPtrTy && argPtrTy->getAddressSpace() != 0)
3997 priv = builder.CreateAddrSpaceCast(priv, argPtrTy);
3998 moduleTranslation.
mapValue(blockArg, priv);
4002 for (
auto [blockArg, origPtr] :
4003 llvm::zip_equal(redBlockArgs, redOrigPtrs))
4004 remapReductionArg(blockArg, redDesc, origPtr,
"omp.taskred.priv");
4006 llvm::Value *nullDesc = llvm::ConstantPointerNull::get(ptrTy);
4007 for (
auto [blockArg, origPtr] :
4008 llvm::zip_equal(inRedBlockArgs, inRedOrigPtrs))
4009 remapReductionArg(blockArg, nullDesc, origPtr,
"omp.inred.priv");
4015 contextOp.getRegion(),
"omp.taskloop.context.region", builder,
4018 if (failed(
handleError(continuationBlockOrError, opInst)))
4019 return llvm::make_error<PreviouslyReportedError>();
4021 builder.SetInsertPoint(continuationBlockOrError.get()->getTerminator());
4029 contextOp.getLoc(), privateVarsInfo)))
4030 return llvm::make_error<PreviouslyReportedError>();
4033 taskStructMgr.freeStructPtr();
4035 return llvm::Error::success();
4041 auto taskDupCB = [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
4042 llvm::Value *destPtr, llvm::Value *srcPtr)
4044 llvm::IRBuilderBase::InsertPointGuard guard(builder);
4045 builder.restoreIP(codegenIP);
4048 builder.getPtrTy(srcPtr->getType()->getPointerAddressSpace());
4050 builder.CreateLoad(ptrTy, srcPtr,
"omp.taskloop.context.src");
4052 TaskContextStructManager &srcStructMgr = taskStructMgr;
4053 TaskContextStructManager destStructMgr(builder, moduleTranslation,
4055 destStructMgr.generateTaskContextStruct();
4056 llvm::Value *dest = destStructMgr.getStructPtr();
4057 dest->setName(
"omp.taskloop.context.dest");
4058 builder.CreateStore(dest, destPtr);
4061 srcStructMgr.createGEPsToPrivateVars(src);
4063 destStructMgr.createGEPsToPrivateVars(dest);
4066 for (
auto [privDecl, mold, blockArg, llvmPrivateVarAlloc] :
4067 llvm::zip_equal(privateVarsInfo.
privatizers, srcGEPs,
4070 if (!privDecl.readsFromMold())
4072 assert(llvmPrivateVarAlloc &&
4073 "reads from mold so shouldn't have been skipped");
4076 builder, moduleTranslation, privDecl.getInitMoldArg(), mold);
4078 builder, moduleTranslation, privDecl, moldArg, blockArg,
4079 llvmPrivateVarAlloc, builder.GetInsertBlock());
4080 if (!privateVarOrErr)
4081 return privateVarOrErr.takeError();
4090 [[maybe_unused]] llvm::Value *llvmPrivateVar = llvmPrivateVarAlloc;
4091 if ((privateVarOrErr.get() != llvmPrivateVarAlloc) &&
4092 !mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
4093 builder.CreateStore(privateVarOrErr.get(), llvmPrivateVarAlloc);
4095 llvmPrivateVar = builder.CreateLoad(privateVarOrErr.get()->getType(),
4096 llvmPrivateVarAlloc);
4098 assert(llvmPrivateVar->getType() ==
4099 moduleTranslation.
convertType(blockArg.getType()));
4107 moduleTranslation, srcGEPs, destGEPs,
4109 contextOp.getPrivateNeedsBarrier())))
4110 return llvm::make_error<PreviouslyReportedError>();
4112 return builder.saveIP();
4120 llvm::Value *ifCond =
nullptr;
4121 llvm::Value *grainsize =
nullptr;
4123 mlir::Value grainsizeVal = contextOp.getGrainsize();
4124 mlir::Value numTasksVal = contextOp.getNumTasks();
4125 if (
Value ifVar = contextOp.getIfExpr())
4128 grainsize = moduleTranslation.
lookupValue(grainsizeVal);
4130 }
else if (numTasksVal) {
4131 grainsize = moduleTranslation.
lookupValue(numTasksVal);
4135 llvm::OpenMPIRBuilder::TaskDupCallbackTy taskDupOrNull =
nullptr;
4136 if (taskStructMgr.getStructPtr())
4137 taskDupOrNull = taskDupCB;
4147 llvm::omp::Directive::OMPD_taskgroup);
4149 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4150 bool effectiveNoGroup = contextOp.getNogroup() || implicitTaskgroup;
4151 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
4153 ompLoc, allocaIP, deallocBlocks, bodyCB, loopInfo, lbVal, ubVal,
4154 stepVal, contextOp.getUntied(), ifCond, grainsize, effectiveNoGroup,
4155 sched, moduleTranslation.
lookupValue(contextOp.getFinal()),
4156 contextOp.getMergeable(),
4157 moduleTranslation.
lookupValue(contextOp.getPriority()),
4158 loopOp.getCollapseNumLoops(), taskDupOrNull,
4159 taskStructMgr.getStructPtr());
4166 builder.restoreIP(*afterIP);
4170 if (implicitTaskgroup) {
4171 llvm::OpenMPIRBuilder::LocationDescription endLoc(builder);
4172 uint32_t srcLocSize;
4173 llvm::Constant *srcLocStr =
4174 ompBuilder.getOrCreateSrcLocStr(endLoc, srcLocSize);
4175 llvm::Value *ident = ompBuilder.getOrCreateIdent(srcLocStr, srcLocSize);
4178 ompBuilder.updateToLocation(endLoc);
4179 llvm::Value *outerGtid = ompBuilder.getOrCreateThreadID(ident);
4180 llvm::FunctionCallee endTgFn = ompBuilder.getOrCreateRuntimeFunction(
4182 llvm::omp::OMPRTL___kmpc_end_taskgroup);
4183 builder.CreateCall(endTgFn, {ident, outerGtid});
4194static llvm::Function *
4197 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
4198 llvm::LLVMContext &ctx = llvmModule->getContext();
4199 llvm::Type *voidTy = llvm::Type::getVoidTy(ctx);
4200 llvm::Type *ptrTy = llvm::PointerType::getUnqual(ctx);
4201 llvm::FunctionType *fty =
4202 llvm::FunctionType::get(voidTy, {ptrTy, ptrTy},
false);
4203 llvm::Function *fn =
4204 llvm::Function::Create(fty, llvm::GlobalValue::InternalLinkage,
4205 baseName +
".red.init", llvmModule);
4206 fn->setDoesNotRecurse();
4207 fn->getArg(0)->setName(
"priv");
4208 fn->getArg(1)->setName(
"orig");
4210 llvm::BasicBlock *entry = llvm::BasicBlock::Create(ctx,
"entry", fn);
4211 llvm::IRBuilder<>
b(entry);
4218 Value moldArg = decl.getInitializerMoldArg();
4219 llvm::Value *origVal = fn->getArg(1);
4220 if (!isa<LLVM::LLVMPointerType>(moldArg.
getType()))
4222 fn->getArg(1),
"omp.orig");
4223 moduleTranslation.
mapValue(moldArg, origVal);
4226 "omp.taskred.init",
b, moduleTranslation,
4228 fn->eraseFromParent();
4231 assert(phis.size() == 1 &&
4232 "expected one value yielded from reduction initializer");
4233 b.CreateStore(phis[0], fn->getArg(0));
4236 moduleTranslation.
forgetMapping(decl.getInitializerRegion());
4244static llvm::Function *
4247 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
4248 llvm::LLVMContext &ctx = llvmModule->getContext();
4249 llvm::Type *voidTy = llvm::Type::getVoidTy(ctx);
4250 llvm::Type *ptrTy = llvm::PointerType::getUnqual(ctx);
4251 llvm::FunctionType *fty =
4252 llvm::FunctionType::get(voidTy, {ptrTy, ptrTy},
false);
4253 llvm::Function *fn =
4254 llvm::Function::Create(fty, llvm::GlobalValue::InternalLinkage,
4255 baseName +
".red.comb", llvmModule);
4256 fn->setDoesNotRecurse();
4257 fn->getArg(0)->setName(
"lhs");
4258 fn->getArg(1)->setName(
"rhs");
4260 llvm::BasicBlock *entry = llvm::BasicBlock::Create(ctx,
"entry", fn);
4261 llvm::IRBuilder<>
b(entry);
4263 llvm::Type *elemTy = moduleTranslation.
convertType(decl.getType());
4264 Block &combBlock = decl.getReductionRegion().
front();
4266 "expected two arguments in declare_reduction combiner");
4267 llvm::Value *lhsVal =
b.CreateLoad(elemTy, fn->getArg(0),
"omp.lhs");
4268 llvm::Value *rhsVal =
b.CreateLoad(elemTy, fn->getArg(1),
"omp.rhs");
4274 "omp.taskred.comb",
b, moduleTranslation,
4276 fn->eraseFromParent();
4279 assert(phis.size() == 1 &&
4280 "expected one value yielded from reduction combiner");
4281 b.CreateStore(phis[0], fn->getArg(0));
4307 llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder::InsertPointTy allocaIP,
4309 bool isWorksharing) {
4310 assert(redDecls.size() == origPtrs.size() &&
4311 "expected one orig pointer per reduction decl");
4313 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
4314 llvm::LLVMContext &ctx = llvmModule->getContext();
4315 const llvm::DataLayout &dl = llvmModule->getDataLayout();
4317 llvm::Type *ptrTy = llvm::PointerType::getUnqual(ctx);
4318 llvm::Type *i32Ty = llvm::Type::getInt32Ty(ctx);
4319 llvm::Type *sizeTy =
4320 llvm::Type::getIntNTy(ctx, dl.getPointerSizeInBits(0));
4324 llvm::StructType *redInputTy =
4325 llvm::StructType::getTypeByName(ctx,
"kmp_taskred_input_t");
4327 redInputTy = llvm::StructType::create(
4328 ctx, {ptrTy, ptrTy, sizeTy, ptrTy, ptrTy, ptrTy, i32Ty},
4329 "kmp_taskred_input_t");
4331 unsigned n = redDecls.size();
4332 llvm::ArrayType *arrTy = llvm::ArrayType::get(redInputTy, n);
4335 llvm::AllocaInst *arrAlloca;
4337 llvm::IRBuilderBase::InsertPointGuard guard(builder);
4338 builder.restoreIP(allocaIP);
4340 builder.CreateAlloca(arrTy,
nullptr,
".taskred.input");
4344 llvm::Value *zero = builder.getInt32(0);
4345 for (
unsigned i = 0; i < n; ++i) {
4346 omp::DeclareReductionOp decl = redDecls[i];
4347 llvm::Value *orig = origPtrs[i];
4348 if (
auto *origPtrTy = llvm::dyn_cast<llvm::PointerType>(orig->getType());
4349 origPtrTy && origPtrTy->getAddressSpace() != 0)
4350 orig = builder.CreateAddrSpaceCast(orig, ptrTy);
4351 llvm::Type *elemTy = moduleTranslation.
convertType(decl.getType());
4352 uint64_t size = dl.getTypeAllocSize(elemTy).getFixedValue();
4354 std::string baseName =
4355 (llvm::Twine(helperNamePrefix) + decl.getSymName()).str();
4356 llvm::Function *initFn =
4358 llvm::Function *combFn =
4360 if (!initFn || !combFn)
4362 llvm::Value *elemPtr = builder.CreateInBoundsGEP(
4363 arrTy, arrAlloca, {zero, builder.getInt32(i)},
".taskred.elem");
4364 auto storeField = [&](
unsigned fieldIdx, llvm::Value *val) {
4365 llvm::Value *fieldPtr =
4366 builder.CreateStructGEP(redInputTy, elemPtr, fieldIdx);
4367 builder.CreateStore(val, fieldPtr);
4369 storeField(0, orig);
4370 storeField(1, orig);
4371 storeField(2, llvm::ConstantInt::get(sizeTy, size));
4372 storeField(3, initFn);
4373 storeField(4, llvm::ConstantPointerNull::get(ptrTy));
4374 storeField(5, combFn);
4375 storeField(6, llvm::ConstantInt::get(i32Ty, 0));
4379 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4380 uint32_t srcLocSize;
4381 llvm::Constant *srcLocStr =
4382 ompBuilder->getOrCreateSrcLocStr(ompLoc, srcLocSize);
4383 llvm::Value *ident = ompBuilder->getOrCreateIdent(srcLocStr, srcLocSize);
4384 ompBuilder->updateToLocation(ompLoc);
4385 llvm::Value *gtid = ompBuilder->getOrCreateThreadID(ident);
4389 llvm::FunctionCallee modInit = ompBuilder->getOrCreateRuntimeFunction(
4390 *llvmModule, llvm::omp::OMPRTL___kmpc_taskred_modifier_init);
4391 return builder.CreateCall(modInit,
4393 builder.getInt32(isWorksharing ? 1 : 0),
4394 builder.getInt32(n), arrAlloca},
4398 llvm::FunctionCallee taskredInit = ompBuilder->getOrCreateRuntimeFunction(
4399 *llvmModule, llvm::omp::OMPRTL___kmpc_taskred_init);
4400 return builder.CreateCall(taskredInit, {gtid, builder.getInt32(n), arrAlloca},
4411 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
4412 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4413 uint32_t srcLocSize;
4414 llvm::Constant *srcLocStr =
4415 ompBuilder->getOrCreateSrcLocStr(ompLoc, srcLocSize);
4416 llvm::Value *ident = ompBuilder->getOrCreateIdent(srcLocStr, srcLocSize);
4417 ompBuilder->updateToLocation(ompLoc);
4418 llvm::Value *gtid = ompBuilder->getOrCreateThreadID(ident);
4419 llvm::FunctionCallee fini = ompBuilder->getOrCreateRuntimeFunction(
4420 *llvmModule, llvm::omp::OMPRTL___kmpc_task_reduction_modifier_fini);
4421 builder.CreateCall(fini,
4422 {ident, gtid, builder.getInt32(isWorksharing ? 1 : 0)});
4429 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4438 if (
auto syms = tgOp.getTaskReductionSyms()) {
4439 redDecls.reserve(syms->size());
4440 for (
auto sym : syms->getAsRange<SymbolRefAttr>()) {
4444 return tgOp.emitError()
4445 <<
"failed to resolve task_reduction declare_reduction symbol "
4446 << sym.getRootReference() <<
" in omp.taskgroup";
4447 if (decl.getInitializerRegion().front().getNumArguments() != 1)
4448 return tgOp.emitError(
"not yet implemented: task_reduction with "
4449 "two-argument initializer in omp.taskgroup");
4450 if (!decl.getCleanupRegion().empty())
4451 return tgOp.emitError(
"not yet implemented: task_reduction with "
4452 "cleanup region in omp.taskgroup");
4453 if (decl.getReductionRegion().empty())
4454 return tgOp.emitError(
"task_reduction declare_reduction is missing a "
4456 redDecls.push_back(decl);
4461 [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
4463 builder.restoreIP(codegenIP);
4465 if (!redDecls.empty()) {
4467 origPtrs.reserve(redDecls.size());
4468 for (
Value v : tgOp.getTaskReductionVars())
4469 origPtrs.push_back(moduleTranslation.
lookupValue(v));
4471 builder, allocaIP, moduleTranslation))
4472 return llvm::createStringError(
4473 llvm::inconvertibleErrorCode(),
4474 "failed to emit task_reduction initialization for omp.taskgroup");
4482 for (
auto [i, blockArg] :
4483 llvm::enumerate(tgOp.getRegion().getArguments())) {
4485 moduleTranslation.
lookupValue(tgOp.getTaskReductionVars()[i]);
4486 moduleTranslation.
mapValue(blockArg, orig);
4490 builder, moduleTranslation)
4495 InsertPointTy allocaIP =
4497 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4498 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
4500 ompLoc, allocaIP, deallocBlocks, bodyCB);
4505 builder.restoreIP(*afterIP);
4512 if (!initOp.getDependVars().empty() || initOp.getDependKinds() ||
4513 !initOp.getDependIterated().empty() || initOp.getDependIteratedKinds())
4514 return initOp.emitError()
4515 <<
"not yet implemented: Unhandled clause depend in "
4516 << omp::InteropInitOp::getOperationName() <<
" operation";
4519 llvm::Value *interopVar =
4520 moduleTranslation.
lookupValue(initOp.getInteropVar());
4521 llvm::Value *device = initOp.getDevice()
4522 ? moduleTranslation.
lookupValue(initOp.getDevice())
4526 llvm::Value *numDeps = llvm::ConstantInt::get(builder.getInt32Ty(), 0);
4527 llvm::Value *depArray = llvm::ConstantPointerNull::get(builder.getPtrTy());
4528 bool hasNowait = initOp.getNowait();
4535 bool hasTarget =
false, hasTargetSync =
false;
4537 switch (cast<omp::InteropTypeAttr>(typeAttr).getValue()) {
4538 case omp::InteropType::target:
4541 case omp::InteropType::targetsync:
4542 hasTargetSync =
true;
4546 llvm::omp::OMPInteropType interopType =
4547 (!hasTarget && hasTargetSync) ? llvm::omp::OMPInteropType::TargetSync
4548 : llvm::omp::OMPInteropType::Target;
4549 ompBuilder->createOMPInteropInit(builder, interopVar, interopType, device,
4550 numDeps, depArray, hasNowait);
4556 llvm::IRBuilderBase &builder,
4558 if (!destroyOp.getDependVars().empty() || destroyOp.getDependKinds() ||
4559 !destroyOp.getDependIterated().empty() ||
4560 destroyOp.getDependIteratedKinds())
4561 return destroyOp.emitError()
4562 <<
"not yet implemented: Unhandled clause depend in "
4563 << omp::InteropDestroyOp::getOperationName() <<
" operation";
4566 llvm::Value *interopVar =
4567 moduleTranslation.
lookupValue(destroyOp.getInteropVar());
4568 llvm::Value *device =
4569 destroyOp.getDevice()
4570 ? moduleTranslation.
lookupValue(destroyOp.getDevice())
4573 llvm::Value *numDeps = llvm::ConstantInt::get(builder.getInt32Ty(), 0);
4574 llvm::Value *depArray = llvm::ConstantPointerNull::get(builder.getPtrTy());
4575 bool hasNowait = destroyOp.getNowait();
4577 ompBuilder->createOMPInteropDestroy(builder, interopVar, device, numDeps,
4578 depArray, hasNowait);
4585 if (!useOp.getDependVars().empty() || useOp.getDependKinds() ||
4586 !useOp.getDependIterated().empty() || useOp.getDependIteratedKinds())
4587 return useOp.emitError()
4588 <<
"not yet implemented: Unhandled clause depend in "
4589 << omp::InteropUseOp::getOperationName() <<
" operation";
4592 llvm::Value *interopVar =
4593 moduleTranslation.
lookupValue(useOp.getInteropVar());
4594 llvm::Value *device = useOp.getDevice()
4595 ? moduleTranslation.
lookupValue(useOp.getDevice())
4598 llvm::Value *numDeps = llvm::ConstantInt::get(builder.getInt32Ty(), 0);
4599 llvm::Value *depArray = llvm::ConstantPointerNull::get(builder.getPtrTy());
4600 bool hasNowait = useOp.getNowait();
4602 ompBuilder->createOMPInteropUse(builder, interopVar, device, numDeps,
4603 depArray, hasNowait);
4613 llvm::OpenMPIRBuilder::DependenciesInfo dds;
4615 twOp.getDependVars(), twOp.getDependKinds(), twOp.getDependIterated(),
4616 twOp.getDependIteratedKinds(), builder, moduleTranslation, dds))) {
4622 builder.CreateFree(dds.DepArray);
4633 auto wsloopOp = cast<omp::WsloopOp>(opInst);
4637 auto loopOp = cast<omp::LoopNestOp>(wsloopOp.getWrappedLoop());
4639 assert(isByRef.size() == wsloopOp.getNumReductionVars());
4643 wsloopOp.getScheduleKind().value_or(omp::ClauseScheduleKind::Static);
4646 llvm::Value *step = moduleTranslation.
lookupValue(loopOp.getLoopSteps()[0]);
4647 llvm::Type *ivType = step->getType();
4648 llvm::Value *chunk =
nullptr;
4649 if (wsloopOp.getScheduleChunk()) {
4650 llvm::Value *chunkVar =
4651 moduleTranslation.
lookupValue(wsloopOp.getScheduleChunk());
4652 chunk = builder.CreateSExtOrTrunc(chunkVar, ivType);
4655 omp::DistributeOp distributeOp =
nullptr;
4656 llvm::Value *distScheduleChunk =
nullptr;
4657 bool hasDistSchedule =
false;
4658 if (llvm::isa_and_present<omp::DistributeOp>(opInst.
getParentOp())) {
4659 distributeOp = cast<omp::DistributeOp>(opInst.
getParentOp());
4660 hasDistSchedule = distributeOp.getDistScheduleStatic();
4661 if (distributeOp.getDistScheduleChunkSize()) {
4662 llvm::Value *chunkVar = moduleTranslation.
lookupValue(
4663 distributeOp.getDistScheduleChunkSize());
4664 distScheduleChunk = builder.CreateSExtOrTrunc(chunkVar, ivType);
4673 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
4677 wsloopOp.getNumReductionVars());
4680 wsloopOp, builder, moduleTranslation, privateVarsInfo, allocaIP);
4687 cast<omp::BlockArgOpenMPOpInterface>(opInst).getReductionBlockArgs();
4692 moduleTranslation, allocaIP, reductionDecls,
4693 privateReductionVariables, reductionVariableMap,
4694 deferredStores, isByRef)))
4703 wsloopOp, builder, moduleTranslation, privateVarsInfo.
mlirVars,
4705 wsloopOp.getPrivateNeedsBarrier())))
4708 assert(afterAllocas.get()->getSinglePredecessor());
4709 if (failed(initReductionVars(wsloopOp, reductionArgs, builder,
4711 afterAllocas.get()->getSinglePredecessor(),
4712 reductionDecls, privateReductionVariables,
4713 reductionVariableMap, isByRef, deferredStores)))
4719 bool isTaskReductionMod =
4720 wsloopOp.getReductionMod() == omp::ReductionModifier::task &&
4721 wsloopOp.getNumReductionVars() > 0;
4722 if (isTaskReductionMod &&
4724 "__omp_taskred_mod_", builder, allocaIP,
4725 moduleTranslation,
true,
4727 return wsloopOp.emitError(
4728 "failed to emit task reduction modifier initialization");
4731 bool isOrdered = wsloopOp.getOrdered().has_value();
4732 std::optional<omp::ScheduleModifier> scheduleMod = wsloopOp.getScheduleMod();
4733 bool isSimd = wsloopOp.getScheduleSimd();
4734 bool loopNeedsBarrier = !wsloopOp.getNowait();
4739 llvm::omp::WorksharingLoopType workshareLoopType =
4740 llvm::isa_and_present<omp::DistributeOp>(opInst.
getParentOp())
4741 ? llvm::omp::WorksharingLoopType::DistributeForStaticLoop
4742 : llvm::omp::WorksharingLoopType::ForStaticLoop;
4746 llvm::omp::Directive::OMPD_for);
4748 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4751 LinearClauseProcessor linearClauseProcessor;
4753 if (!wsloopOp.getLinearVars().empty()) {
4754 auto linearVarTypes = wsloopOp.getLinearVarTypes().value();
4756 linearClauseProcessor.registerType(moduleTranslation, linearVarType);
4758 for (
auto [idx, linearVar] : llvm::enumerate(wsloopOp.getLinearVars()))
4759 linearClauseProcessor.createLinearVar(
4760 builder, moduleTranslation, moduleTranslation.
lookupValue(linearVar),
4762 for (
mlir::Value linearStep : wsloopOp.getLinearStepVars())
4763 linearClauseProcessor.initLinearStep(moduleTranslation, linearStep);
4767 wsloopOp.getRegion(),
"omp.wsloop.region", builder, moduleTranslation);
4775 if (!wsloopOp.getLinearVars().empty()) {
4776 linearClauseProcessor.initLinearVar(builder, moduleTranslation,
4777 loopInfo->getPreheader());
4778 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterBarrierIP =
4780 builder, llvm::omp::OMPD_barrier);
4783 builder.restoreIP(*afterBarrierIP);
4784 linearClauseProcessor.updateLinearVar(builder, loopInfo->getBody(),
4785 loopInfo->getIndVar());
4786 linearClauseProcessor.splitLinearFiniBB(builder, loopInfo->getExit());
4789 builder.SetInsertPoint(*regionBlock, (*regionBlock)->begin());
4792 bool noLoopMode =
false;
4793 omp::TargetOp targetOp = wsloopOp->getParentOfType<mlir::omp::TargetOp>();
4795 targetOp.getKernelType() == omp::TargetExecMode::spmd_no_loop) {
4797 cast<omp::ComposableOpInterface>(*targetOp).findCapturedOp();
4801 if (loopOp == targetCapturedOp)
4805 for (
size_t index = 0;
index < wsloopOp.getLinearVars().size();
index++)
4806 linearClauseProcessor.rewriteInPlace(builder, loopInfo->getBody(),
4807 loopInfo->getLatch(),
index);
4809 llvm::OpenMPIRBuilder::InsertPointOrErrorTy wsloopIP =
4810 ompBuilder->applyWorkshareLoop(
4811 ompLoc.DL, loopInfo, allocaIP, loopNeedsBarrier,
4812 convertToScheduleKind(schedule), chunk, isSimd,
4813 scheduleMod == omp::ScheduleModifier::monotonic,
4814 scheduleMod == omp::ScheduleModifier::nonmonotonic, isOrdered,
4815 workshareLoopType, noLoopMode, hasDistSchedule, distScheduleChunk);
4821 if (!wsloopOp.getLinearVars().empty()) {
4822 llvm::OpenMPIRBuilder::InsertPointTy oldIP = builder.saveIP();
4823 assert(loopInfo->getLastIter() &&
4824 "`lastiter` in CanonicalLoopInfo is nullptr");
4825 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterBarrierIP =
4826 linearClauseProcessor.finalizeLinearVar(builder, moduleTranslation,
4827 loopInfo->getLastIter());
4831 builder.restoreIP(oldIP);
4838 if (isTaskReductionMod)
4844 wsloopOp, builder, moduleTranslation, allocaIP, reductionDecls,
4845 privateReductionVariables, isByRef, wsloopOp.getNowait(),
4850 wsloopOp.getLoc(), privateVarsInfo);
4857 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4859 assert(isByRef.size() == opInst.getNumReductionVars());
4867 for (
Value allocatorVar : opInst.getAllocatorVars()) {
4871 llvm::Value *allocator = moduleTranslation.
lookupValue(allocatorVar);
4873 return opInst.emitError(
"failed to translate OpenMP allocator operand");
4874 if (allocator->getType()->isIntegerTy())
4875 allocator = builder.CreateIntToPtr(allocator, builder.getPtrTy());
4876 else if (allocator->getType()->isPointerTy())
4877 allocator = builder.CreatePointerBitCastOrAddrSpaceCast(
4878 allocator, builder.getPtrTy());
4880 return opInst.emitError(
4881 "OpenMP allocator operand must have integer or pointer type");
4890 opInst.getNumReductionVars());
4896 bool isTaskReductionMod =
4897 opInst.getReductionMod() == omp::ReductionModifier::task &&
4898 opInst.getNumReductionVars() > 0;
4901 [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
4904 opInst, builder, moduleTranslation, privateVarsInfo, allocaIP);
4906 return llvm::make_error<PreviouslyReportedError>();
4912 cast<omp::BlockArgOpenMPOpInterface>(*opInst).getReductionBlockArgs();
4915 InsertPointTy(allocaIP.getBlock(),
4916 allocaIP.getBlock()->getTerminator()->getIterator());
4919 opInst, reductionArgs, builder, moduleTranslation, allocaIP,
4920 reductionDecls, privateReductionVariables, reductionVariableMap,
4921 deferredStores, isByRef)))
4922 return llvm::make_error<PreviouslyReportedError>();
4924 assert(afterAllocas.get()->getSinglePredecessor());
4925 builder.restoreIP(codeGenIP);
4931 return llvm::make_error<PreviouslyReportedError>();
4934 opInst, builder, moduleTranslation, privateVarsInfo.
mlirVars,
4936 opInst.getPrivateNeedsBarrier())))
4937 return llvm::make_error<PreviouslyReportedError>();
4940 initReductionVars(opInst, reductionArgs, builder, moduleTranslation,
4941 afterAllocas.get()->getSinglePredecessor(),
4942 reductionDecls, privateReductionVariables,
4943 reductionVariableMap, isByRef, deferredStores)))
4944 return llvm::make_error<PreviouslyReportedError>();
4949 if (isTaskReductionMod &&
4951 "__omp_taskred_mod_", builder, allocaIP,
4952 moduleTranslation,
true,
4954 return llvm::createStringError(
4955 "failed to emit task reduction modifier initialization");
4960 moduleTranslation, allocaIP, deallocBlocks);
4964 opInst.getRegion(),
"omp.par.region", builder, moduleTranslation);
4966 return regionBlock.takeError();
4969 if (opInst.getNumReductionVars() > 0) {
4974 owningReductionGenRefDataPtrGens;
4976 collectReductionInfo(opInst, builder, moduleTranslation, reductionDecls,
4978 owningReductionGenRefDataPtrGens,
4979 privateReductionVariables, reductionInfos, isByRef);
4982 builder.SetInsertPoint((*regionBlock)->getTerminator());
4986 if (isTaskReductionMod)
4991 llvm::UnreachableInst *tempTerminator = builder.CreateUnreachable();
4992 builder.SetInsertPoint(tempTerminator);
4994 llvm::OpenMPIRBuilder::InsertPointOrErrorTy contInsertPoint =
4995 ompBuilder->createReductions(builder, allocaIP, reductionInfos,
4999 if (!contInsertPoint)
5000 return contInsertPoint.takeError();
5002 if (!contInsertPoint->getBlock())
5003 return llvm::make_error<PreviouslyReportedError>();
5005 tempTerminator->eraseFromParent();
5006 builder.restoreIP(*contInsertPoint);
5009 return llvm::Error::success();
5012 auto privCB = [](InsertPointTy allocaIP, InsertPointTy codeGenIP,
5013 llvm::Value &, llvm::Value &val, llvm::Value *&replVal) {
5022 auto finiCB = [&](InsertPointTy codeGenIP) -> llvm::Error {
5023 InsertPointTy oldIP = builder.saveIP();
5024 builder.restoreIP(codeGenIP);
5029 llvm::transform(reductionDecls, std::back_inserter(reductionCleanupRegions),
5030 [](omp::DeclareReductionOp reductionDecl) {
5031 return &reductionDecl.getCleanupRegion();
5034 reductionCleanupRegions, privateReductionVariables,
5035 moduleTranslation, builder,
"omp.reduction.cleanup")))
5036 return llvm::createStringError(
5037 "failed to inline `cleanup` region of `omp.declare_reduction`");
5040 opInst.getLoc(), privateVarsInfo)))
5041 return llvm::make_error<PreviouslyReportedError>();
5045 if (isCancellable) {
5046 auto IPOrErr = ompBuilder->createBarrier(
5047 llvm::OpenMPIRBuilder::LocationDescription(builder),
5048 llvm::omp::Directive::OMPD_unknown,
5052 return IPOrErr.takeError();
5055 builder.restoreIP(oldIP);
5056 return llvm::Error::success();
5059 llvm::Value *ifCond =
nullptr;
5060 if (
auto ifVar = opInst.getIfExpr())
5062 llvm::Value *numThreads =
nullptr;
5063 if (!opInst.getNumThreadsVars().empty())
5064 numThreads = moduleTranslation.
lookupValue(opInst.getNumThreads(0));
5065 auto pbKind = llvm::omp::OMP_PROC_BIND_default;
5066 if (
auto bind = opInst.getProcBindKind())
5070 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
5072 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5074 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
5075 ompBuilder->createParallel(ompLoc, allocaIP, deallocBlocks, bodyGenCB,
5076 privCB, finiCB, ifCond, numThreads, pbKind,
5082 builder.restoreIP(*afterIP);
5087static llvm::omp::OrderKind
5090 return llvm::omp::OrderKind::OMP_ORDER_unknown;
5092 case omp::ClauseOrderKind::Concurrent:
5093 return llvm::omp::OrderKind::OMP_ORDER_concurrent;
5095 llvm_unreachable(
"Unknown ClauseOrderKind kind");
5103 auto simdOp = cast<omp::SimdOp>(opInst);
5111 cast<omp::BlockArgOpenMPOpInterface>(opInst).getReductionBlockArgs();
5114 simdOp.getNumReductionVars());
5119 assert(isByRef.size() == simdOp.getNumReductionVars());
5121 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
5125 simdOp, builder, moduleTranslation, privateVarsInfo, allocaIP);
5130 LinearClauseProcessor linearClauseProcessor;
5131 if (linearClauseProcessor.initLinearIV(simdOp).failed())
5134 if (!simdOp.getLinearVars().empty()) {
5135 auto linearVarTypes = simdOp.getLinearVarTypes().value();
5137 linearClauseProcessor.registerType(moduleTranslation, linearVarType);
5138 for (
auto [idx, linearVar] : llvm::enumerate(simdOp.getLinearVars())) {
5139 bool isImplicit =
false;
5140 for (
auto [mlirPrivVar, llvmPrivateVar] : llvm::zip_equal(
5144 if (linearVar == mlirPrivVar) {
5146 linearClauseProcessor.createLinearVar(builder, moduleTranslation,
5147 llvmPrivateVar, idx);
5153 linearClauseProcessor.createLinearVar(
5154 builder, moduleTranslation,
5157 for (
mlir::Value linearStep : simdOp.getLinearStepVars())
5158 linearClauseProcessor.initLinearStep(moduleTranslation, linearStep);
5162 moduleTranslation, allocaIP, reductionDecls,
5163 privateReductionVariables, reductionVariableMap,
5164 deferredStores, isByRef)))
5175 assert(afterAllocas.get()->getSinglePredecessor());
5176 if (failed(initReductionVars(simdOp, reductionArgs, builder,
5178 afterAllocas.get()->getSinglePredecessor(),
5179 reductionDecls, privateReductionVariables,
5180 reductionVariableMap, isByRef, deferredStores)))
5183 llvm::ConstantInt *simdlen =
nullptr;
5184 if (std::optional<uint64_t> simdlenVar = simdOp.getSimdlen())
5185 simdlen = builder.getInt64(simdlenVar.value());
5187 llvm::ConstantInt *safelen =
nullptr;
5188 if (std::optional<uint64_t> safelenVar = simdOp.getSafelen())
5189 safelen = builder.getInt64(safelenVar.value());
5191 llvm::MapVector<llvm::Value *, llvm::Value *> alignedVars;
5194 llvm::BasicBlock *sourceBlock = builder.GetInsertBlock();
5195 std::optional<ArrayAttr> alignmentValues = simdOp.getAlignments();
5197 for (
size_t i = 0; i < operands.size(); ++i) {
5198 llvm::Value *alignment =
nullptr;
5199 llvm::Value *llvmVal = moduleTranslation.
lookupValue(operands[i]);
5200 llvm::Type *ty = llvmVal->getType();
5202 auto intAttr = cast<IntegerAttr>((*alignmentValues)[i]);
5203 alignment = builder.getInt64(intAttr.getInt());
5204 assert(ty->isPointerTy() &&
"Invalid type for aligned variable");
5205 assert(alignment &&
"Invalid alignment value");
5209 if (!intAttr.getValue().isPowerOf2())
5212 auto curInsert = builder.saveIP();
5213 builder.SetInsertPoint(sourceBlock);
5214 llvmVal = builder.CreateLoad(ty, llvmVal);
5215 builder.restoreIP(curInsert);
5216 alignedVars[llvmVal] = alignment;
5220 simdOp.getRegion(),
"omp.simd.region", builder, moduleTranslation);
5227 if (simdOp.getLinearVars().size()) {
5228 linearClauseProcessor.initLinearVar(builder, moduleTranslation,
5229 loopInfo->getPreheader());
5231 linearClauseProcessor.updateLinearVar(builder, loopInfo->getBody(),
5232 loopInfo->getIndVar());
5234 builder.SetInsertPoint(*regionBlock, (*regionBlock)->begin());
5236 for (
size_t index = 0;
index < simdOp.getLinearVars().size();
index++)
5237 linearClauseProcessor.rewriteInPlace(builder, loopInfo->getBody(),
5238 loopInfo->getLatch(),
index);
5240 ompBuilder->applySimd(loopInfo, alignedVars,
5242 ? moduleTranslation.
lookupValue(simdOp.getIfExpr())
5244 order, simdlen, safelen);
5246 linearClauseProcessor.updateLinearIV(builder, moduleTranslation);
5247 linearClauseProcessor.emitStoresForLinearVar(builder);
5253 for (
auto [i, tuple] : llvm::enumerate(
5254 llvm::zip(reductionDecls, isByRef, simdOp.getReductionVars(),
5255 privateReductionVariables))) {
5256 auto [decl, byRef, reductionVar, privateReductionVar] = tuple;
5258 OwningReductionGen gen =
makeReductionGen(decl, builder, moduleTranslation);
5259 llvm::Value *originalVariable = moduleTranslation.
lookupValue(reductionVar);
5260 llvm::Type *reductionType = moduleTranslation.
convertType(decl.getType());
5264 llvm::Value *redValue = originalVariable;
5267 builder.CreateLoad(reductionType, redValue,
"red.value." + Twine(i));
5268 llvm::Value *privateRedValue = builder.CreateLoad(
5269 reductionType, privateReductionVar,
"red.private.value." + Twine(i));
5270 llvm::Value *reduced;
5272 auto res = gen(builder.saveIP(), redValue, privateRedValue, reduced);
5275 builder.restoreIP(res.get());
5279 builder.CreateStore(reduced, originalVariable);
5284 llvm::transform(reductionDecls, std::back_inserter(reductionRegions),
5285 [](omp::DeclareReductionOp reductionDecl) {
5286 return &reductionDecl.getCleanupRegion();
5289 moduleTranslation, builder,
5290 "omp.reduction.cleanup")))
5302 auto loopOp = cast<omp::LoopNestOp>(opInst);
5308 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5313 auto bodyGen = [&](llvm::OpenMPIRBuilder::InsertPointTy ip,
5314 llvm::Value *iv) -> llvm::Error {
5317 loopOp.getRegion().front().getArgument(loopInfos.size()), iv);
5322 bodyInsertPoints.push_back(ip);
5324 if (loopInfos.size() != loopOp.getNumLoops() - 1)
5325 return llvm::Error::success();
5328 builder.restoreIP(ip);
5330 loopOp.getRegion(),
"omp.loop_nest.region", builder, moduleTranslation);
5332 return regionBlock.takeError();
5334 builder.SetInsertPoint(*regionBlock, (*regionBlock)->begin());
5335 return llvm::Error::success();
5343 for (
unsigned i = 0, e = loopOp.getNumLoops(); i < e; ++i) {
5344 llvm::Value *lowerBound =
5345 moduleTranslation.
lookupValue(loopOp.getLoopLowerBounds()[i]);
5346 llvm::Value *upperBound =
5347 moduleTranslation.
lookupValue(loopOp.getLoopUpperBounds()[i]);
5348 llvm::Value *step = moduleTranslation.
lookupValue(loopOp.getLoopSteps()[i]);
5353 llvm::OpenMPIRBuilder::LocationDescription loc = ompLoc;
5354 llvm::OpenMPIRBuilder::InsertPointTy computeIP = ompLoc.IP;
5356 loc = llvm::OpenMPIRBuilder::LocationDescription(bodyInsertPoints.back(),
5358 computeIP = loopInfos.front()->getPreheaderIP();
5362 ompBuilder->createCanonicalLoop(
5363 loc, bodyGen, lowerBound, upperBound, step,
5364 true, loopOp.getLoopInclusive(), computeIP);
5369 loopInfos.push_back(*loopResult);
5372 llvm::OpenMPIRBuilder::InsertPointTy afterIP =
5373 loopInfos.front()->getAfterIP();
5376 if (
const auto &tiles = loopOp.getTileSizes()) {
5377 llvm::Type *ivType = loopInfos.front()->getIndVarType();
5380 for (
auto tile : tiles.value()) {
5381 llvm::Value *tileVal = llvm::ConstantInt::get(ivType,
tile);
5382 tileSizes.push_back(tileVal);
5385 std::vector<llvm::CanonicalLoopInfo *> newLoops =
5386 ompBuilder->tileLoops(ompLoc.DL, loopInfos, tileSizes);
5390 llvm::BasicBlock *afterBB = newLoops.front()->getAfter();
5391 llvm::BasicBlock *afterAfterBB = afterBB->getSingleSuccessor();
5392 afterIP = {afterAfterBB, afterAfterBB->begin()};
5396 for (
const auto &newLoop : newLoops)
5397 loopInfos.push_back(newLoop);
5401 const auto &numCollapse = loopOp.getCollapseNumLoops();
5403 loopInfos.begin(), loopInfos.begin() + (numCollapse));
5405 auto newTopLoopInfo =
5406 ompBuilder->collapseLoops(ompLoc.DL, collapseLoopInfos, {});
5408 assert(newTopLoopInfo &&
"New top loop information is missing");
5409 moduleTranslation.
stackWalk<OpenMPLoopInfoStackFrame>(
5410 [&](OpenMPLoopInfoStackFrame &frame) {
5411 frame.loopInfo = newTopLoopInfo;
5419 builder.restoreIP(afterIP);
5429 llvm::OpenMPIRBuilder::LocationDescription loopLoc(builder);
5430 Value loopIV = op.getInductionVar();
5431 Value loopTC = op.getTripCount();
5433 llvm::Value *llvmTC = moduleTranslation.
lookupValue(loopTC);
5436 ompBuilder->createCanonicalLoop(
5438 [&](llvm::OpenMPIRBuilder::InsertPointTy ip, llvm::Value *llvmIV) {
5441 moduleTranslation.
mapValue(loopIV, llvmIV);
5443 builder.restoreIP(ip);
5448 return bodyGenStatus.takeError();
5450 llvmTC,
"omp.loop");
5452 return op.emitError(llvm::toString(llvmOrError.takeError()));
5454 llvm::CanonicalLoopInfo *llvmCLI = *llvmOrError;
5455 llvm::IRBuilderBase::InsertPoint afterIP = llvmCLI->getAfterIP();
5456 builder.restoreIP(afterIP);
5459 if (
Value cli = op.getCli())
5472 Value applyee = op.getApplyee();
5473 assert(applyee &&
"Loop to apply unrolling on required");
5475 llvm::CanonicalLoopInfo *consBuilderCLI =
5477 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
5478 ompBuilder->unrollLoopHeuristic(loc.DL, consBuilderCLI);
5491 Value applyee = op.getApplyee();
5492 assert(applyee &&
"Loop to apply unrolling on required");
5494 llvm::CanonicalLoopInfo *consBuilderCLI =
5496 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
5497 ompBuilder->unrollLoopFull(loc.DL, consBuilderCLI);
5510 Value applyee = op.getApplyee();
5511 assert(applyee &&
"Loop to apply unrolling on required");
5513 llvm::CanonicalLoopInfo *consBuilderCLI =
5515 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
5519 int32_t factor =
static_cast<int32_t
>(op.getUnrollFactor());
5520 ompBuilder->unrollLoopPartial(loc.DL, consBuilderCLI, factor,
5529static LogicalResult
applyTile(omp::TileOp op, llvm::IRBuilderBase &builder,
5532 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
5537 for (
Value size : op.getSizes()) {
5538 llvm::Value *translatedSize = moduleTranslation.
lookupValue(size);
5539 assert(translatedSize &&
5540 "sizes clause arguments must already be translated");
5541 translatedSizes.push_back(translatedSize);
5544 for (
Value applyee : op.getApplyees()) {
5545 llvm::CanonicalLoopInfo *consBuilderCLI =
5547 assert(applyee &&
"Canonical loop must already been translated");
5548 translatedLoops.push_back(consBuilderCLI);
5551 auto generatedLoops =
5552 ompBuilder->tileLoops(loc.DL, translatedLoops, translatedSizes);
5553 if (!op.getGeneratees().empty()) {
5554 for (
auto [mlirLoop,
genLoop] :
5555 zip_equal(op.getGeneratees(), generatedLoops))
5560 for (
Value applyee : op.getApplyees())
5568static LogicalResult
applyFuse(omp::FuseOp op, llvm::IRBuilderBase &builder,
5571 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
5575 for (
size_t i = 0; i < op.getApplyees().size(); i++) {
5576 Value applyee = op.getApplyees()[i];
5577 llvm::CanonicalLoopInfo *consBuilderCLI =
5579 assert(applyee &&
"Canonical loop must already been translated");
5580 if (op.getFirst().has_value() && i < op.getFirst().value() - 1)
5581 beforeFuse.push_back(consBuilderCLI);
5582 else if (op.getCount().has_value() &&
5583 i >= op.getFirst().value() + op.getCount().value() - 1)
5584 afterFuse.push_back(consBuilderCLI);
5586 toFuse.push_back(consBuilderCLI);
5589 (op.getGeneratees().empty() ||
5590 beforeFuse.size() + afterFuse.size() + 1 == op.getGeneratees().size()) &&
5591 "Wrong number of generatees");
5594 auto generatedLoop = ompBuilder->fuseLoops(loc.DL, toFuse);
5595 if (!op.getGeneratees().empty()) {
5597 for (; i < beforeFuse.size(); i++)
5598 moduleTranslation.
mapOmpLoop(op.getGeneratees()[i], beforeFuse[i]);
5599 moduleTranslation.
mapOmpLoop(op.getGeneratees()[i++], generatedLoop);
5600 for (; i < afterFuse.size(); i++)
5601 moduleTranslation.
mapOmpLoop(op.getGeneratees()[i], afterFuse[i]);
5605 for (
Value applyee : op.getApplyees())
5612static llvm::AtomicOrdering
5615 return llvm::AtomicOrdering::Monotonic;
5618 case omp::ClauseMemoryOrderKind::Seq_cst:
5619 return llvm::AtomicOrdering::SequentiallyConsistent;
5620 case omp::ClauseMemoryOrderKind::Acq_rel:
5621 return llvm::AtomicOrdering::AcquireRelease;
5622 case omp::ClauseMemoryOrderKind::Acquire:
5623 return llvm::AtomicOrdering::Acquire;
5624 case omp::ClauseMemoryOrderKind::Release:
5625 return llvm::AtomicOrdering::Release;
5626 case omp::ClauseMemoryOrderKind::Relaxed:
5627 return llvm::AtomicOrdering::Monotonic;
5629 llvm_unreachable(
"Unknown ClauseMemoryOrderKind kind");
5636static llvm::AtomicOrdering
5638 llvm::AtomicOrdering atomicOrdering) {
5639 if (atomicCompareOp.getFailMemoryOrder())
5641 return llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(atomicOrdering);
5648 auto readOp = cast<omp::AtomicReadOp>(opInst);
5653 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
5656 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5659 llvm::Value *x = moduleTranslation.
lookupValue(readOp.getX());
5660 llvm::Value *v = moduleTranslation.
lookupValue(readOp.getV());
5662 llvm::Type *elementType =
5663 moduleTranslation.
convertType(readOp.getElementType());
5665 llvm::OpenMPIRBuilder::AtomicOpValue V = {v, elementType,
false,
false};
5666 llvm::OpenMPIRBuilder::AtomicOpValue X = {x, elementType,
false,
false};
5667 builder.restoreIP(ompBuilder->createAtomicRead(ompLoc, X, V, AO, allocaIP));
5675 auto writeOp = cast<omp::AtomicWriteOp>(opInst);
5680 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
5683 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5685 llvm::Value *expr = moduleTranslation.
lookupValue(writeOp.getExpr());
5686 llvm::Value *dest = moduleTranslation.
lookupValue(writeOp.getX());
5687 llvm::Type *ty = moduleTranslation.
convertType(writeOp.getExpr().getType());
5688 llvm::OpenMPIRBuilder::AtomicOpValue x = {dest, ty,
false,
5691 ompBuilder->createAtomicWrite(ompLoc, x, expr, ao, allocaIP));
5699 .Case([&](LLVM::AddOp) {
return llvm::AtomicRMWInst::BinOp::Add; })
5700 .Case([&](LLVM::SubOp) {
return llvm::AtomicRMWInst::BinOp::Sub; })
5701 .Case([&](LLVM::AndOp) {
return llvm::AtomicRMWInst::BinOp::And; })
5702 .Case([&](LLVM::OrOp) {
return llvm::AtomicRMWInst::BinOp::Or; })
5703 .Case([&](LLVM::XOrOp) {
return llvm::AtomicRMWInst::BinOp::Xor; })
5704 .Case([&](LLVM::UMaxOp) {
return llvm::AtomicRMWInst::BinOp::UMax; })
5705 .Case([&](LLVM::UMinOp) {
return llvm::AtomicRMWInst::BinOp::UMin; })
5706 .Case([&](LLVM::FAddOp) {
return llvm::AtomicRMWInst::BinOp::FAdd; })
5707 .Case([&](LLVM::FSubOp) {
return llvm::AtomicRMWInst::BinOp::FSub; })
5708 .Default(llvm::AtomicRMWInst::BinOp::BAD_BINOP);
5712 bool &isIgnoreDenormalMode,
5713 bool &isFineGrainedMemory,
5714 bool &isRemoteMemory) {
5715 isIgnoreDenormalMode =
false;
5716 isFineGrainedMemory =
false;
5717 isRemoteMemory =
false;
5718 if (atomicUpdateOp &&
5719 atomicUpdateOp->hasAttr(atomicUpdateOp.getAtomicControlAttrName())) {
5720 mlir::omp::AtomicControlAttr atomicControlAttr =
5721 atomicUpdateOp.getAtomicControlAttr();
5722 isIgnoreDenormalMode = atomicControlAttr.getIgnoreDenormalMode();
5723 isFineGrainedMemory = atomicControlAttr.getFineGrainedMemory();
5724 isRemoteMemory = atomicControlAttr.getRemoteMemory();
5731 llvm::IRBuilderBase &builder,
5738 auto &innerOpList = opInst.getRegion().front().getOperations();
5739 bool isXBinopExpr{
false};
5740 llvm::AtomicRMWInst::BinOp binop;
5742 llvm::Value *llvmExpr =
nullptr;
5743 llvm::Value *llvmX =
nullptr;
5744 llvm::Type *llvmXElementType =
nullptr;
5745 if (innerOpList.size() == 2) {
5751 opInst.getRegion().getArgument(0))) {
5752 return opInst.emitError(
"no atomic update operation with region argument"
5753 " as operand found inside atomic.update region");
5756 isXBinopExpr = innerOp.
getOperand(0) == opInst.getRegion().getArgument(0);
5758 llvmExpr = moduleTranslation.
lookupValue(mlirExpr);
5762 binop = llvm::AtomicRMWInst::BinOp::BAD_BINOP;
5764 llvmX = moduleTranslation.
lookupValue(opInst.getX());
5766 opInst.getRegion().getArgument(0).getType());
5767 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {llvmX, llvmXElementType,
5771 llvm::AtomicOrdering atomicOrdering =
5776 [&opInst, &moduleTranslation](
5777 llvm::Value *atomicx,
5780 moduleTranslation.
mapValue(*opInst.getRegion().args_begin(), atomicx);
5781 moduleTranslation.
mapBlock(&bb, builder.GetInsertBlock());
5782 if (failed(moduleTranslation.
convertBlock(bb,
true, builder)))
5783 return llvm::make_error<PreviouslyReportedError>();
5785 omp::YieldOp yieldop = dyn_cast<omp::YieldOp>(bb.
getTerminator());
5786 assert(yieldop && yieldop.getResults().size() == 1 &&
5787 "terminator must be omp.yield op and it must have exactly one "
5789 return moduleTranslation.
lookupValue(yieldop.getResults()[0]);
5792 bool isIgnoreDenormalMode;
5793 bool isFineGrainedMemory;
5794 bool isRemoteMemory;
5799 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5800 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
5801 ompBuilder->createAtomicUpdate(ompLoc, allocaIP, llvmAtomicX, llvmExpr,
5802 atomicOrdering, binop, updateFn,
5803 isXBinopExpr, isIgnoreDenormalMode,
5804 isFineGrainedMemory, isRemoteMemory);
5809 builder.restoreIP(*afterIP);
5815static std::optional<llvm::omp::OMPAtomicCompareOp>
5817 switch (predicate) {
5818 case LLVM::ICmpPredicate::eq:
5819 return llvm::omp::OMPAtomicCompareOp::EQ;
5820 case LLVM::ICmpPredicate::slt:
5821 case LLVM::ICmpPredicate::ult:
5822 return llvm::omp::OMPAtomicCompareOp::MIN;
5823 case LLVM::ICmpPredicate::sgt:
5824 case LLVM::ICmpPredicate::ugt:
5825 return llvm::omp::OMPAtomicCompareOp::MAX;
5827 return std::nullopt;
5833static std::optional<llvm::omp::OMPAtomicCompareOp>
5835 switch (predicate) {
5836 case LLVM::FCmpPredicate::oeq:
5837 case LLVM::FCmpPredicate::ueq:
5838 return llvm::omp::OMPAtomicCompareOp::EQ;
5839 case LLVM::FCmpPredicate::olt:
5840 case LLVM::FCmpPredicate::ult:
5841 return llvm::omp::OMPAtomicCompareOp::MIN;
5842 case LLVM::FCmpPredicate::ogt:
5843 case LLVM::FCmpPredicate::ugt:
5844 return llvm::omp::OMPAtomicCompareOp::MAX;
5846 return std::nullopt;
5873 if (
auto extractOp = v.getDefiningOp<LLVM::ExtractValueOp>())
5874 return extractOp.getContainer();
5878 if (!isa<LLVM::AndOp, LLVM::OrOp>(op))
5882 if (!lhsFcmp || !rhsFcmp)
5884 mlir::Value lhsAgg0 = traceToAggregate(lhsFcmp.getOperand(0));
5885 mlir::Value lhsAgg1 = traceToAggregate(lhsFcmp.getOperand(1));
5886 bool lhsXIsOp0 = (lhsAgg0 == block.
getArgument(0));
5887 bool lhsXIsOp1 = (lhsAgg1 == block.
getArgument(0));
5888 if (!lhsXIsOp0 && !lhsXIsOp1)
5890 mlir::Value eAggregate = lhsXIsOp0 ? lhsAgg1 : lhsAgg0;
5894 result.isNE = isa<LLVM::OrOp>(op);
5895 result.eAggregate = eAggregate;
5896 result.isXBinopExpr = lhsXIsOp0;
5908 llvm::Value *llvmX, llvm::Type *complexTy,
5909 llvm::Value *eVal, llvm::Value *dVal,
5910 llvm::AtomicOrdering atomicOrdering,
5911 llvm::AtomicOrdering failOrdering,
5912 bool isWeak, llvm::Value *&oldComplex,
5913 llvm::Value *&cmpOk) {
5914 const llvm::DataLayout &DL =
5915 builder.GetInsertBlock()->getModule()->getDataLayout();
5916 unsigned totalBits = DL.getTypeStoreSizeInBits(complexTy).getFixedValue();
5917 llvm::IntegerType *intTy =
5918 llvm::IntegerType::get(builder.getContext(), totalBits);
5919 llvm::Align complexAlign = DL.getABITypeAlign(complexTy);
5920 llvm::Align intAlign = DL.getABITypeAlign(intTy);
5921 llvm::Align maxAlign = std::max(complexAlign, intAlign);
5924 llvm::AllocaInst *dAlloca =
5925 builder.CreateAlloca(complexTy,
nullptr,
"cmplx.d");
5926 dAlloca->setAlignment(maxAlign);
5927 builder.CreateAlignedStore(dVal, dAlloca, maxAlign);
5929 builder.CreateAlignedLoad(intTy, dAlloca, maxAlign,
"cmplx.d.int");
5934 llvm::LoadInst *xCurr =
5935 builder.CreateAlignedLoad(intTy, llvmX, maxAlign,
"cmplx.x.load");
5936 xCurr->setAtomic(failOrdering);
5937 llvm::AllocaInst *xAlloca =
5938 builder.CreateAlloca(complexTy,
nullptr,
"cmplx.x");
5939 xAlloca->setAlignment(maxAlign);
5940 builder.CreateAlignedStore(xCurr, xAlloca, maxAlign);
5941 llvm::Value *xStruct =
5942 builder.CreateAlignedLoad(complexTy, xAlloca, maxAlign,
"cmplx.x.val");
5947 llvm::Value *reX = builder.CreateExtractValue(xStruct, 0);
5948 llvm::Value *imX = builder.CreateExtractValue(xStruct, 1);
5949 llvm::Value *reE = builder.CreateExtractValue(eVal, 0);
5950 llvm::Value *imE = builder.CreateExtractValue(eVal, 1);
5951 llvm::Value *reEq = builder.CreateFCmpOEQ(reX, reE,
"cmplx.re.eq");
5952 llvm::Value *imEq = builder.CreateFCmpOEQ(imX, imE,
"cmplx.im.eq");
5953 llvm::Value *fpEqual = builder.CreateAnd(reEq, imEq,
"cmplx.eq");
5958 llvm::BasicBlock *curBB = builder.GetInsertBlock();
5959 llvm::Function *fn = curBB->getParent();
5960 llvm::BasicBlock *swapBB =
5961 llvm::BasicBlock::Create(builder.getContext(),
"cmplx.atomic.swap", fn);
5962 llvm::BasicBlock *exitBB =
5963 llvm::BasicBlock::Create(builder.getContext(),
"cmplx.atomic.exit", fn);
5964 builder.CreateCondBr(fpEqual, swapBB, exitBB);
5966 builder.SetInsertPoint(swapBB);
5967 llvm::AtomicCmpXchgInst *cmpXchg = builder.CreateAtomicCmpXchg(
5968 llvmX, xCurr, dInt, maxAlign, atomicOrdering, failOrdering);
5969 cmpXchg->setWeak(isWeak);
5970 llvm::Value *oldSwap = builder.CreateExtractValue(cmpXchg, 0);
5971 llvm::Value *okSwap = builder.CreateExtractValue(cmpXchg, 1);
5972 builder.CreateBr(exitBB);
5975 builder.SetInsertPoint(exitBB);
5976 llvm::PHINode *oldIntPHI = builder.CreatePHI(intTy, 2,
"cmplx.old.int");
5977 oldIntPHI->addIncoming(oldSwap, swapBB);
5978 oldIntPHI->addIncoming(xCurr, curBB);
5979 llvm::PHINode *okPHI = builder.CreatePHI(builder.getInt1Ty(), 2,
"cmplx.ok");
5980 okPHI->addIncoming(okSwap, swapBB);
5981 okPHI->addIncoming(builder.getFalse(), curBB);
5984 llvm::AllocaInst *oldAlloca =
5985 builder.CreateAlloca(complexTy,
nullptr,
"cmplx.old");
5986 oldAlloca->setAlignment(maxAlign);
5987 builder.CreateAlignedStore(oldIntPHI, oldAlloca, maxAlign);
5988 oldComplex = builder.CreateAlignedLoad(complexTy, oldAlloca, maxAlign,
5996 llvm::omp::OMPAtomicCompareOp
compareOp = llvm::omp::OMPAtomicCompareOp::EQ;
6016 return atomicCompareOp.emitError(
6017 "unsupported comparison predicate (NE) for complex atomic compare");
6018 info.
compareOp = llvm::omp::OMPAtomicCompareOp::EQ;
6020 info.
eVal = materializeValue(cplx.eAggregate);
6022 if (
auto selectOp = dyn_cast<LLVM::SelectOp>(op)) {
6023 info.
dVal = materializeValue(selectOp.getTrueValue());
6033 if (
auto icmpOp = dyn_cast<LLVM::ICmpOp>(op);
6034 icmpOp && icmpOp.getOperand(0) != block.
getArgument(0) &&
6040 .Case<LLVM::ICmpOp>([&](LLVM::ICmpOp icmpOp) -> LogicalResult {
6044 return atomicCompareOp.emitError(
6045 "unsupported comparison predicate in atomic compare");
6047 LLVM::ICmpPredicate pred = icmpOp.getPredicate();
6048 info.
isSigned = (pred == LLVM::ICmpPredicate::slt ||
6049 pred == LLVM::ICmpPredicate::sgt ||
6050 pred == LLVM::ICmpPredicate::sle ||
6051 pred == LLVM::ICmpPredicate::sge);
6055 : icmpOp.getOperand(0);
6056 info.
eVal = materializeValue(eOperand);
6059 .Case<LLVM::FCmpOp>([&](LLVM::FCmpOp fcmpOp) -> LogicalResult {
6063 return atomicCompareOp.emitError(
6064 "unsupported comparison predicate in atomic compare");
6069 : fcmpOp.getOperand(0);
6070 info.
eVal = materializeValue(eOperand);
6073 .Case<LLVM::SelectOp>([&](LLVM::SelectOp selectOp) {
6075 info.
dVal = materializeValue(selectOp.getTrueValue());
6078 .Case<mlir::arith::MaxSIOp, mlir::arith::MinSIOp,
6079 mlir::arith::MaxUIOp, mlir::arith::MinUIOp,
6080 mlir::arith::MaximumFOp, mlir::arith::MinimumFOp,
6081 LLVM::SMaxOp, LLVM::SMinOp, LLVM::UMaxOp, LLVM::UMinOp,
6082 LLVM::MaxNumOp, LLVM::MinNumOp>([&](
Operation *) {
6087 bool isMax = isa<mlir::arith::MaxSIOp, mlir::arith::MaxUIOp,
6088 mlir::arith::MaximumFOp, LLVM::SMaxOp,
6089 LLVM::UMaxOp, LLVM::MaxNumOp>(op);
6090 info.
compareOp = isMax ? llvm::omp::OMPAtomicCompareOp::MIN
6091 : llvm::omp::OMPAtomicCompareOp::MAX;
6092 info.
isSigned = isa<mlir::arith::MaxSIOp, mlir::arith::MinSIOp,
6093 LLVM::SMaxOp, LLVM::SMinOp>(op);
6097 info.
eVal = materializeValue(eOperand);
6111 llvm::IRBuilderBase &builder,
6117 omp::AtomicUpdateOp atomicUpdateOp = atomicCaptureOp.getAtomicUpdateOp();
6118 omp::AtomicWriteOp atomicWriteOp = atomicCaptureOp.getAtomicWriteOp();
6119 omp::AtomicCompareOp atomicCompareOp = atomicCaptureOp.getAtomicCompareOp();
6123 if (atomicCompareOp) {
6124 omp::AtomicReadOp atomicReadOp = atomicCaptureOp.getAtomicReadOp();
6125 assert(atomicReadOp &&
"expected atomic.read in capture+compare");
6127 Region ®ion = atomicCompareOp.getRegion();
6130 llvm::Type *llvmXElementType =
6132 llvm::Value *llvmX = moduleTranslation.
lookupValue(atomicCompareOp.getX());
6133 llvm::Value *llvmV = moduleTranslation.
lookupValue(atomicReadOp.getV());
6135 bool isSigned =
false;
6136 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {
6137 llvmX, llvmXElementType, isSigned,
false};
6138 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicV = {
6139 llvmV, llvmXElementType,
false,
false};
6140 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicR = {
nullptr,
nullptr,
false,
6143 llvm::AtomicOrdering atomicOrdering =
6147 auto isAtomicComparePatternOp = [](
Operation &op) {
6148 return llvm::isa<LLVM::ICmpOp, LLVM::FCmpOp, LLVM::SelectOp, LLVM::AndOp,
6149 LLVM::OrOp, LLVM::SMaxOp, LLVM::SMinOp, LLVM::UMaxOp,
6150 LLVM::UMinOp, LLVM::MaxNumOp, LLVM::MinNumOp,
6151 mlir::arith::MaxSIOp, mlir::arith::MinSIOp,
6152 mlir::arith::MaxUIOp, mlir::arith::MinUIOp,
6153 mlir::arith::MaximumFOp, mlir::arith::MinimumFOp>(op);
6156 if (isAtomicComparePatternOp(op))
6158 bool allOperandsMapped =
6160 return moduleTranslation.lookupValue(v) != nullptr;
6162 if (!allOperandsMapped)
6165 return atomicCompareOp.emitError(
6166 "failed to translate operation inside atomic compare region");
6169 auto materializeValue = [&](
mlir::Value val) -> llvm::Value * {
6170 if (llvm::Value *existing = moduleTranslation.
lookupValue(val))
6173 if (loadOp->getParentRegion() == ®ion) {
6174 llvm::Value *loadAddr =
6178 llvm::Type *loadType =
6179 moduleTranslation.
convertType(loadOp.getResult().getType());
6180 return builder.CreateLoad(loadType, loadAddr);
6189 atomicCompareOp, patternInfo)))
6192 llvm::omp::OMPAtomicCompareOp compareOp = patternInfo.
compareOp;
6193 llvm::Value *eVal = patternInfo.
eVal;
6194 llvm::Value *dVal = patternInfo.
dVal;
6199 return atomicCompareOp.emitError(
6200 "failed to extract expected value (e) from atomic compare region");
6203 if (yieldOp.getResults().empty())
6204 return atomicCompareOp.emitError(
6205 "failed to extract desired value (d) from atomic compare region");
6206 dVal = materializeValue(yieldOp.getResults()[0]);
6209 llvmAtomicX.IsSigned = isSigned;
6211 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6212 bool isReadFirst = isa<omp::AtomicReadOp>(atomicCaptureOp.getFirstOp());
6213 bool isPostfixCapture = !isReadFirst;
6214 bool isFailOnly = atomicCaptureOp.getFailOnly();
6222 if (llvmXElementType->isStructTy()) {
6223 llvm::Value *oldComplex =
nullptr;
6224 llvm::Value *cmpOk =
nullptr;
6225 llvm::AtomicOrdering failOrdering =
6228 atomicOrdering, failOrdering,
6229 atomicCompareOp.getWeak(), oldComplex, cmpOk);
6233 llvm::Value *cmpFailed = builder.CreateNot(cmpOk);
6234 llvm::BasicBlock *curBB = builder.GetInsertBlock();
6235 llvm::Function *fn = curBB->getParent();
6236 llvm::BasicBlock *contBB = llvm::BasicBlock::Create(
6237 builder.getContext(),
"omp.atomic.cont", fn);
6238 llvm::BasicBlock *exitBB = llvm::BasicBlock::Create(
6239 builder.getContext(),
"omp.atomic.exit", fn);
6240 builder.CreateCondBr(cmpFailed, contBB, exitBB);
6241 builder.SetInsertPoint(contBB);
6242 builder.CreateStore(oldComplex, llvmAtomicV.Var,
6243 llvmAtomicV.IsVolatile);
6244 builder.CreateBr(exitBB);
6245 builder.SetInsertPoint(exitBB);
6246 }
else if (isPostfixCapture) {
6248 llvm::Value *newComplex = builder.CreateSelect(cmpOk, dVal, oldComplex);
6249 builder.CreateStore(newComplex, llvmAtomicV.Var,
6250 llvmAtomicV.IsVolatile);
6253 builder.CreateStore(oldComplex, llvmAtomicV.Var,
6254 llvmAtomicV.IsVolatile);
6258 if (atomicOrdering == llvm::AtomicOrdering::Release ||
6259 atomicOrdering == llvm::AtomicOrdering::AcquireRelease ||
6260 atomicOrdering == llvm::AtomicOrdering::SequentiallyConsistent) {
6261 llvm::OpenMPIRBuilder::LocationDescription flushLoc(builder);
6262 ompBuilder->createFlush(flushLoc);
6273 bool isMinMax = compareOp != llvm::omp::OMPAtomicCompareOp::EQ;
6275 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicVForCall = llvmAtomicV;
6282 bool minMaxManualCapture = isMinMax && (isPostfixCapture || isFailOnly);
6283 bool eqPostfixManualCapture = !isMinMax && isPostfixCapture && !isFailOnly;
6284 if (minMaxManualCapture || eqPostfixManualCapture)
6285 llvmAtomicVForCall = {
nullptr,
nullptr,
false,
false};
6289 bool builderFailOnly = isFailOnly && !isMinMax;
6296 bool isPostfixUpdate = !builderFailOnly;
6298 bool isWeak = atomicCompareOp.getWeak();
6299 bool savedHandleFPNegZero = ompBuilder->setHandleFPNegZero(
true);
6300 llvm::AtomicOrdering failureOrdering =
6302 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
6303 ompBuilder->createAtomicCompare(
6304 ompLoc, llvmAtomicX, llvmAtomicVForCall, llvmAtomicR, eVal, dVal,
6305 atomicOrdering, compareOp, isXBinopExpr, isPostfixUpdate,
6306 builderFailOnly, failureOrdering, isWeak);
6307 ompBuilder->setHandleFPNegZero(savedHandleFPNegZero);
6309 if (failed(
handleError(afterIP, *atomicCaptureOp)))
6312 builder.restoreIP(*afterIP);
6321 if (isMinMax && (isPostfixCapture || isFailOnly)) {
6322 llvm::BasicBlock *curBB = builder.GetInsertBlock();
6323 llvm::AtomicRMWInst *rmw =
nullptr;
6324 for (
auto &inst : llvm::reverse(*curBB)) {
6325 if (
auto *r = dyn_cast<llvm::AtomicRMWInst>(&inst)) {
6330 assert(rmw &&
"expected atomicrmw for min/max compare capture");
6331 llvm::Value *oldVal = rmw;
6332 llvm::Value *
rhs = rmw->getValOperand();
6338 llvm::CmpInst::Predicate updatePred;
6339 switch (rmw->getOperation()) {
6340 case llvm::AtomicRMWInst::Min:
6341 updatePred = llvm::CmpInst::ICMP_SGT;
6343 case llvm::AtomicRMWInst::Max:
6344 updatePred = llvm::CmpInst::ICMP_SLT;
6346 case llvm::AtomicRMWInst::UMin:
6347 updatePred = llvm::CmpInst::ICMP_UGT;
6349 case llvm::AtomicRMWInst::UMax:
6350 updatePred = llvm::CmpInst::ICMP_ULT;
6352 case llvm::AtomicRMWInst::FMin:
6353 updatePred = llvm::CmpInst::FCMP_OGT;
6355 case llvm::AtomicRMWInst::FMax:
6356 updatePred = llvm::CmpInst::FCMP_OLT;
6360 "unexpected atomicrmw op for min/max compare capture");
6362 llvm::Value *updated = builder.CreateCmp(updatePred, oldVal,
rhs);
6363 llvm::Value *failed = builder.CreateNot(updated);
6364 llvm::Function *fn = curBB->getParent();
6365 llvm::BasicBlock *contBB = llvm::BasicBlock::Create(
6366 builder.getContext(),
"omp.atomic.cont", fn);
6367 llvm::BasicBlock *exitBB = llvm::BasicBlock::Create(
6368 builder.getContext(),
"omp.atomic.exit", fn);
6369 builder.CreateCondBr(failed, contBB, exitBB);
6370 builder.SetInsertPoint(contBB);
6371 builder.CreateStore(oldVal, llvmAtomicV.Var, llvmAtomicV.IsVolatile);
6372 builder.CreateBr(exitBB);
6373 builder.SetInsertPoint(exitBB);
6375 llvm::Intrinsic::ID id;
6376 switch (rmw->getOperation()) {
6377 case llvm::AtomicRMWInst::Min:
6378 id = llvm::Intrinsic::smin;
6380 case llvm::AtomicRMWInst::Max:
6381 id = llvm::Intrinsic::smax;
6383 case llvm::AtomicRMWInst::UMin:
6384 id = llvm::Intrinsic::umin;
6386 case llvm::AtomicRMWInst::UMax:
6387 id = llvm::Intrinsic::umax;
6389 case llvm::AtomicRMWInst::FMin:
6390 id = llvm::Intrinsic::minnum;
6392 case llvm::AtomicRMWInst::FMax:
6393 id = llvm::Intrinsic::maxnum;
6397 "unexpected atomicrmw op for min/max compare capture");
6399 llvm::Value *newVal = builder.CreateBinaryIntrinsic(
id, oldVal,
rhs);
6400 builder.CreateStore(newVal, llvmAtomicV.Var, llvmAtomicV.IsVolatile);
6406 if (!isMinMax && isPostfixCapture && !isFailOnly) {
6407 llvm::BasicBlock *curBB = builder.GetInsertBlock();
6408 llvm::Value *oldVal =
nullptr;
6409 llvm::Value *successVal =
nullptr;
6413 for (
auto &inst : llvm::reverse(*curBB)) {
6414 if (isa<llvm::AtomicCmpXchgInst>(&inst)) {
6415 oldVal = builder.CreateExtractValue(&inst, 0);
6416 successVal = builder.CreateExtractValue(&inst, 1);
6427 for (
auto &inst : *curBB) {
6428 auto *phi = dyn_cast<llvm::PHINode>(&inst);
6431 if (phi->getType()->isIntegerTy(1))
6434 for (
auto &inst : *curBB) {
6435 if (
auto *bc = dyn_cast<llvm::BitCastInst>(&inst)) {
6442 assert(oldVal &&
"expected cmpxchg or PHI+bitcast for compare capture");
6443 assert(successVal &&
"expected success flag for compare capture");
6444 llvm::Value *newVal = builder.CreateSelect(successVal, dVal, oldVal);
6445 builder.CreateStore(newVal, llvmAtomicV.Var, llvmAtomicV.IsVolatile);
6452 bool isXBinopExpr =
false, isPostfixUpdate =
false;
6453 llvm::AtomicRMWInst::BinOp binop = llvm::AtomicRMWInst::BinOp::BAD_BINOP;
6455 assert((atomicUpdateOp || atomicWriteOp) &&
6456 "internal op must be an atomic.update or atomic.write op");
6458 if (atomicWriteOp) {
6459 isPostfixUpdate =
true;
6460 mlirExpr = atomicWriteOp.getExpr();
6462 isPostfixUpdate = atomicCaptureOp.getSecondOp() ==
6463 atomicCaptureOp.getAtomicUpdateOp().getOperation();
6464 auto &innerOpList = atomicUpdateOp.getRegion().front().getOperations();
6467 if (innerOpList.size() == 2) {
6470 atomicUpdateOp.getRegion().getArgument(0))) {
6471 return atomicUpdateOp.emitError(
6472 "no atomic update operation with region argument"
6473 " as operand found inside atomic.update region");
6477 innerOp.
getOperand(0) == atomicUpdateOp.getRegion().getArgument(0);
6480 binop = llvm::AtomicRMWInst::BinOp::BAD_BINOP;
6484 llvm::Value *llvmExpr = moduleTranslation.
lookupValue(mlirExpr);
6485 llvm::Value *llvmX =
6486 moduleTranslation.
lookupValue(atomicCaptureOp.getAtomicReadOp().getX());
6487 llvm::Value *llvmV =
6488 moduleTranslation.
lookupValue(atomicCaptureOp.getAtomicReadOp().getV());
6489 llvm::Type *llvmXElementType = moduleTranslation.
convertType(
6490 atomicCaptureOp.getAtomicReadOp().getElementType());
6491 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {llvmX, llvmXElementType,
6494 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicV = {llvmV, llvmXElementType,
6498 llvm::AtomicOrdering atomicOrdering =
6502 [&](llvm::Value *atomicx,
6505 return moduleTranslation.
lookupValue(atomicWriteOp.getExpr());
6506 Block &bb = *atomicUpdateOp.getRegion().
begin();
6507 moduleTranslation.
mapValue(*atomicUpdateOp.getRegion().args_begin(),
6509 moduleTranslation.
mapBlock(&bb, builder.GetInsertBlock());
6510 if (failed(moduleTranslation.
convertBlock(bb,
true, builder)))
6511 return llvm::make_error<PreviouslyReportedError>();
6513 omp::YieldOp yieldop = dyn_cast<omp::YieldOp>(bb.
getTerminator());
6514 assert(yieldop && yieldop.getResults().size() == 1 &&
6515 "terminator must be omp.yield op and it must have exactly one "
6517 return moduleTranslation.
lookupValue(yieldop.getResults()[0]);
6520 bool isIgnoreDenormalMode;
6521 bool isFineGrainedMemory;
6522 bool isRemoteMemory;
6524 isFineGrainedMemory, isRemoteMemory);
6527 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6528 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
6529 ompBuilder->createAtomicCapture(
6530 ompLoc, allocaIP, llvmAtomicX, llvmAtomicV, llvmExpr, atomicOrdering,
6531 binop, updateFn, atomicUpdateOp, isPostfixUpdate, isXBinopExpr,
6532 isIgnoreDenormalMode, isFineGrainedMemory, isRemoteMemory);
6534 if (failed(
handleError(afterIP, *atomicCaptureOp)))
6537 builder.restoreIP(*afterIP);
6559 llvm::IRBuilderBase &builder,
6565 Region ®ion = atomicCompareOp.getRegion();
6569 llvm::Type *llvmXElementType =
6571 if (!llvmXElementType)
6572 return atomicCompareOp.emitError(
6573 "unable to determine element type for atomic compare");
6575 llvm::Value *llvmX = moduleTranslation.
lookupValue(atomicCompareOp.getX());
6580 bool isSigned =
false;
6581 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {llvmX, llvmXElementType,
6585 llvm::AtomicOrdering atomicOrdering =
6588 auto isAtomicComparePatternOp = [](
Operation &op) {
6589 return llvm::isa<LLVM::ICmpOp, LLVM::FCmpOp, LLVM::SelectOp, LLVM::AndOp,
6590 LLVM::OrOp, LLVM::SMaxOp, LLVM::SMinOp, LLVM::UMaxOp,
6591 LLVM::UMinOp, LLVM::MaxNumOp, LLVM::MinNumOp,
6592 mlir::arith::MaxSIOp, mlir::arith::MinSIOp,
6593 mlir::arith::MaxUIOp, mlir::arith::MinUIOp,
6594 mlir::arith::MaximumFOp, mlir::arith::MinimumFOp>(op);
6614 if (isAtomicComparePatternOp(op))
6619 return moduleTranslation.lookupValue(v) != nullptr;
6621 if (!allOperandsMapped)
6625 return atomicCompareOp.emitError(
6626 "failed to translate operation inside atomic compare region");
6631 auto materializeValue = [&](
mlir::Value val) -> llvm::Value * {
6633 if (llvm::Value *existing = moduleTranslation.
lookupValue(val))
6638 if (loadOp->getParentRegion() == ®ion) {
6639 llvm::Value *loadAddr = moduleTranslation.
lookupValue(loadOp.getAddr());
6642 llvm::Type *loadType =
6643 moduleTranslation.
convertType(loadOp.getResult().getType());
6644 return builder.CreateLoad(loadType, loadAddr);
6652 llvm::omp::OMPAtomicCompareOp compareOp = llvm::omp::OMPAtomicCompareOp::EQ;
6653 llvm::Value *eVal =
nullptr;
6654 llvm::Value *dVal =
nullptr;
6655 bool isXBinopExpr =
false;
6661 if (isComplexPattern) {
6664 return atomicCompareOp.emitError(
6665 "unsupported comparison predicate (NE) for complex atomic compare");
6666 compareOp = llvm::omp::OMPAtomicCompareOp::EQ;
6671 if (isComplexPattern) {
6674 if (
auto selectOp = dyn_cast<LLVM::SelectOp>(op)) {
6675 dVal = materializeValue(selectOp.getTrueValue());
6681 if (yieldOp.getResults().empty())
6682 return atomicCompareOp.emitError(
6683 "failed to extract desired value (d) from atomic compare region");
6684 dVal = materializeValue(yieldOp.getResults()[0]);
6687 llvm::Value *oldComplex =
nullptr;
6688 llvm::Value *cmpOk =
nullptr;
6689 llvm::AtomicOrdering failOrdering =
6692 atomicOrdering, failOrdering,
6693 atomicCompareOp.getWeak(), oldComplex, cmpOk);
6699 if (atomicOrdering == llvm::AtomicOrdering::Release ||
6700 atomicOrdering == llvm::AtomicOrdering::AcquireRelease ||
6701 atomicOrdering == llvm::AtomicOrdering::SequentiallyConsistent) {
6702 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6703 ompBuilder->createFlush(ompLoc);
6709 atomicCompareOp, patternInfo)))
6712 eVal = patternInfo.
eVal;
6713 dVal = patternInfo.
dVal;
6719 return atomicCompareOp.emitError(
6720 "failed to extract expected value (e) from atomic compare region");
6724 if (yieldOp.getResults().empty())
6725 return atomicCompareOp.emitError(
6726 "failed to extract desired value (d) from atomic compare region");
6727 dVal = materializeValue(yieldOp.getResults()[0]);
6730 llvmAtomicX.IsSigned = isSigned;
6732 llvm::OpenMPIRBuilder::AtomicOpValue vOpVal = {
nullptr,
nullptr,
false,
6734 llvm::OpenMPIRBuilder::AtomicOpValue rOpVal = {
nullptr,
nullptr,
false,
6736 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6738 bool isWeak = atomicCompareOp.getWeak();
6740 bool savedHandleFPNegZero = ompBuilder->setHandleFPNegZero(
true);
6741 llvm::AtomicOrdering failureOrdering =
6743 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
6744 ompBuilder->createAtomicCompare(
6745 ompLoc, llvmAtomicX, vOpVal, rOpVal, eVal, dVal, atomicOrdering,
6746 compareOp, isXBinopExpr,
false,
6747 false, failureOrdering, isWeak);
6748 ompBuilder->setHandleFPNegZero(savedHandleFPNegZero);
6750 if (failed(
handleError(afterIP, *atomicCompareOp)))
6753 builder.restoreIP(*afterIP);
6758 omp::ClauseCancellationConstructType directive) {
6759 switch (directive) {
6760 case omp::ClauseCancellationConstructType::Loop:
6761 return llvm::omp::Directive::OMPD_for;
6762 case omp::ClauseCancellationConstructType::Parallel:
6763 return llvm::omp::Directive::OMPD_parallel;
6764 case omp::ClauseCancellationConstructType::Sections:
6765 return llvm::omp::Directive::OMPD_sections;
6766 case omp::ClauseCancellationConstructType::Taskgroup:
6767 return llvm::omp::Directive::OMPD_taskgroup;
6769 llvm_unreachable(
"Unhandled cancellation construct type");
6778 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6781 llvm::Value *ifCond =
nullptr;
6782 if (
Value ifVar = op.getIfExpr())
6785 llvm::omp::Directive cancelledDirective =
6788 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
6789 ompBuilder->createCancel(ompLoc, ifCond, cancelledDirective);
6791 if (failed(
handleError(afterIP, *op.getOperation())))
6794 builder.restoreIP(afterIP.get());
6801 llvm::IRBuilderBase &builder,
6806 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6809 llvm::omp::Directive cancelledDirective =
6812 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
6813 ompBuilder->createCancellationPoint(ompLoc, cancelledDirective);
6815 if (failed(
handleError(afterIP, *op.getOperation())))
6818 builder.restoreIP(afterIP.get());
6828 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6830 auto threadprivateOp = cast<omp::ThreadprivateOp>(opInst);
6835 Value symAddr = threadprivateOp.getSymAddr();
6838 if (
auto asCast = dyn_cast<LLVM::AddrSpaceCastOp>(symOp))
6841 if (!isa<LLVM::AddressOfOp>(symOp))
6842 return opInst.
emitError(
"Addressing symbol not found");
6843 LLVM::AddressOfOp addressOfOp = dyn_cast<LLVM::AddressOfOp>(symOp);
6845 LLVM::GlobalOp global =
6846 addressOfOp.getGlobal(moduleTranslation.
symbolTable());
6847 llvm::GlobalValue *globalValue = moduleTranslation.
lookupGlobal(global);
6848 llvm::Type *type = globalValue->getValueType();
6849 llvm::TypeSize typeSize =
6850 builder.GetInsertBlock()->getModule()->getDataLayout().getTypeStoreSize(
6852 llvm::ConstantInt *size = builder.getInt64(typeSize.getFixedValue());
6853 llvm::Value *callInst = ompBuilder->createCachedThreadPrivate(
6854 ompLoc, globalValue, size, global.getSymName() +
".cache");
6860static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind
6862 switch (deviceClause) {
6863 case mlir::omp::DeclareTargetDeviceType::host:
6864 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseHost;
6866 case mlir::omp::DeclareTargetDeviceType::nohost:
6867 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNoHost;
6869 case mlir::omp::DeclareTargetDeviceType::any:
6870 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny;
6873 llvm_unreachable(
"unhandled device clause");
6876static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind
6878 mlir::omp::DeclareTargetCaptureClause captureClause) {
6879 switch (captureClause) {
6880 case mlir::omp::DeclareTargetCaptureClause::to:
6881 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo;
6882 case mlir::omp::DeclareTargetCaptureClause::link:
6883 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink;
6884 case mlir::omp::DeclareTargetCaptureClause::enter:
6885 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter;
6886 case mlir::omp::DeclareTargetCaptureClause::none:
6887 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
6889 llvm_unreachable(
"unhandled capture clause");
6894 if (
auto addrCast = dyn_cast_if_present<LLVM::AddrSpaceCastOp>(op))
6896 if (
auto addressOfOp = dyn_cast_if_present<LLVM::AddressOfOp>(op)) {
6897 auto modOp = addressOfOp->getParentOfType<mlir::ModuleOp>();
6898 return modOp.lookupSymbol(addressOfOp.getGlobalName());
6905 if (
auto addrCast = dyn_cast_if_present<LLVM::AddrSpaceCastOp>(op))
6906 value = addrCast.getOperand();
6923static llvm::SmallString<64>
6925 llvm::OpenMPIRBuilder &ompBuilder,
6926 llvm::vfs::FileSystem &vfs) {
6928 llvm::raw_svector_ostream os(suffix);
6931 auto fileInfoCallBack = [&loc]() {
6932 return std::pair<std::string, uint64_t>(
6933 llvm::StringRef(loc.getFilename()), loc.getLine());
6938 ompBuilder.getTargetEntryUniqueInfo(fileInfoCallBack, vfs).FileID);
6940 os <<
"_decl_tgt_ref_ptr";
6946 if (
auto declareTargetGlobal =
6947 dyn_cast_if_present<omp::DeclareTargetInterface>(
6949 if (declareTargetGlobal.getDeclareTargetCaptureClause() ==
6950 omp::DeclareTargetCaptureClause::link)
6956 if (
auto declareTargetGlobal =
6957 dyn_cast_if_present<omp::DeclareTargetInterface>(
6959 if (declareTargetGlobal.getDeclareTargetCaptureClause() ==
6960 omp::DeclareTargetCaptureClause::to ||
6961 declareTargetGlobal.getDeclareTargetCaptureClause() ==
6962 omp::DeclareTargetCaptureClause::enter)
6980 ompBuilder->Config.hasRequiresUnifiedSharedMemory())) {
6984 if (gOp.getSymName().contains(suffix))
6989 (gOp.getSymName().str() + suffix.str()).str());
6997struct MapInfosTy : llvm::OpenMPIRBuilder::MapInfosTy {
6998 SmallVector<Operation *, 4> Mappers;
7001 void append(MapInfosTy &curInfo) {
7002 Mappers.append(curInfo.Mappers.begin(), curInfo.Mappers.end());
7003 llvm::OpenMPIRBuilder::MapInfosTy::append(curInfo);
7012struct MapInfoData : MapInfosTy {
7013 llvm::SmallVector<bool, 4> IsDeclareTarget;
7014 llvm::SmallVector<bool, 4> IsAMember;
7016 llvm::SmallVector<bool, 4> IsAMapping;
7017 llvm::SmallVector<mlir::Operation *, 4> MapClause;
7018 llvm::SmallVector<llvm::Value *, 4> OriginalValue;
7021 llvm::SmallVector<llvm::Type *, 4> BaseType;
7024 void append(MapInfoData &CurInfo) {
7025 IsDeclareTarget.append(CurInfo.IsDeclareTarget.begin(),
7026 CurInfo.IsDeclareTarget.end());
7027 MapClause.append(CurInfo.MapClause.begin(), CurInfo.MapClause.end());
7028 OriginalValue.append(CurInfo.OriginalValue.begin(),
7029 CurInfo.OriginalValue.end());
7030 BaseType.append(CurInfo.BaseType.begin(), CurInfo.BaseType.end());
7031 MapInfosTy::append(CurInfo);
7035enum class TargetDirectiveEnumTy : uint32_t {
7039 TargetEnterData = 3,
7044static TargetDirectiveEnumTy getTargetDirectiveEnumTyFromOp(Operation *op) {
7045 return llvm::TypeSwitch<Operation *, TargetDirectiveEnumTy>(op)
7046 .Case([](omp::TargetDataOp) {
return TargetDirectiveEnumTy::TargetData; })
7047 .Case([](omp::TargetEnterDataOp) {
7048 return TargetDirectiveEnumTy::TargetEnterData;
7050 .Case([&](omp::TargetExitDataOp) {
7051 return TargetDirectiveEnumTy::TargetExitData;
7053 .Case([&](omp::TargetUpdateOp) {
7054 return TargetDirectiveEnumTy::TargetUpdate;
7056 .Case([&](omp::TargetOp) {
return TargetDirectiveEnumTy::Target; })
7057 .Default([&](Operation *op) {
return TargetDirectiveEnumTy::None; });
7064 if (
auto nestedArrTy = llvm::dyn_cast_if_present<LLVM::LLVMArrayType>(
7065 arrTy.getElementType()))
7079 if (mapOp.getVarPtrPtr())
7103 llvm::Value *basePointer,
7104 llvm::Type *baseType,
7105 llvm::IRBuilderBase &builder,
7107 if (
auto memberClause =
7108 mlir::dyn_cast_if_present<mlir::omp::MapInfoOp>(clauseOp)) {
7113 if (!memberClause.getBounds().empty()) {
7114 llvm::Value *elementCount = builder.getInt64(1);
7115 for (
auto bounds : memberClause.getBounds()) {
7116 if (
auto boundOp = mlir::dyn_cast_if_present<mlir::omp::MapBoundsOp>(
7117 bounds.getDefiningOp())) {
7122 elementCount = builder.CreateMul(
7126 moduleTranslation.
lookupValue(boundOp.getUpperBound()),
7127 moduleTranslation.
lookupValue(boundOp.getLowerBound())),
7128 builder.getInt64(1)));
7135 if (
auto arrTy = llvm::dyn_cast_if_present<LLVM::LLVMArrayType>(type))
7143 llvm::Value *sizeCalc = builder.CreateMul(
7144 elementCount, builder.getInt64(underlyingTypeSzInBits / 8),
7182 return builder.CreateSelect(
7183 builder.CreateICmpEQ(sizeCalc, builder.getInt64(0)),
7184 builder.getInt64(1), sizeCalc);
7198static llvm::omp::OpenMPOffloadMappingFlags
7200 const bool hasExplicitMap =
7201 (mlirFlags &
~omp::ClauseMapFlags::is_device_ptr) !=
7202 omp::ClauseMapFlags::none;
7204 llvm::omp::OpenMPOffloadMappingFlags mapType =
7205 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7207 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::to))
7208 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
7210 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::from))
7211 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7213 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::always))
7214 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
7216 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::del))
7217 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
7219 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::return_param))
7220 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
7222 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::priv))
7223 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRIVATE;
7225 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::literal))
7226 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL;
7228 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::implicit))
7229 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
7231 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::close))
7232 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
7234 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::present))
7235 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
7237 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::ompx_hold))
7238 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
7240 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::attach))
7241 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH;
7243 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::is_device_ptr)) {
7244 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7245 if (!hasExplicitMap)
7246 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL;
7256 ArrayRef<Value> useDevAddrOperands = {},
7257 ArrayRef<Value> hasDevAddrOperands = {}) {
7259 auto checkRefPtrOrPteeMapWithAttach = [](omp::ClauseMapFlags mapType) {
7261 bitEnumContainsAll(mapType, omp::ClauseMapFlags::ref_ptr) ||
7262 bitEnumContainsAll(mapType, omp::ClauseMapFlags::ref_ptee);
7263 return hasRefType &&
7264 bitEnumContainsAll(mapType, omp::ClauseMapFlags::attach);
7267 auto checkIsAMember = [](
const auto &mapVars,
auto mapOp) {
7275 for (Value mapValue : mapVars) {
7276 auto map = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
7277 for (
auto member : map.getMembers())
7278 if (member == mapOp)
7285 for (Value mapValue : mapVars) {
7286 auto mapOp = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
7287 bool isRefPtrOrPteeMapWithAttach =
7288 checkRefPtrOrPteeMapWithAttach(mapOp.getMapType());
7289 Value offloadPtr = (mapOp.getVarPtrPtr() && !isRefPtrOrPteeMapWithAttach)
7290 ? mapOp.getVarPtrPtr()
7291 : mapOp.getVarPtr();
7292 mapData.OriginalValue.push_back(moduleTranslation.
lookupValue(offloadPtr));
7293 mapData.Pointers.push_back(
7294 isRefPtrOrPteeMapWithAttach
7295 ? moduleTranslation.
lookupValue(mapOp.getVarPtrPtr())
7296 : mapData.OriginalValue.back());
7298 if (llvm::Value *refPtr =
7300 mapData.IsDeclareTarget.push_back(
true);
7301 mapData.BasePointers.push_back(refPtr);
7303 mapData.IsDeclareTarget.push_back(
true);
7304 mapData.BasePointers.push_back(mapData.OriginalValue.back());
7306 mapData.IsDeclareTarget.push_back(
false);
7307 mapData.BasePointers.push_back(mapData.OriginalValue.back());
7313 mapData.BaseType.push_back(moduleTranslation.
convertType(
7314 mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtrType().value()
7315 : mapOp.getVarPtrType()));
7322 mlir::Type sizeType = (isRefPtrOrPteeMapWithAttach || !mapOp.getVarPtrPtr())
7323 ? mapOp.getVarPtrType()
7324 : mapOp.getVarPtrPtrType().value();
7326 dl, sizeType, isRefPtrOrPteeMapWithAttach ?
nullptr : mapOp,
7327 mapData.Pointers.back(), moduleTranslation.
convertType(sizeType),
7328 builder, moduleTranslation));
7329 mapData.MapClause.push_back(mapOp.getOperation());
7332 mapData.HasAttachPtr.push_back(
false);
7333 mapData.Names.push_back(LLVM::createMappingInformation(
7335 mapData.DevicePointers.push_back(llvm::OpenMPIRBuilder::DeviceInfoTy::None);
7336 if (mapOp.getMapperId())
7337 mapData.Mappers.push_back(
7339 mapOp, mapOp.getMapperIdAttr()));
7341 mapData.Mappers.push_back(
nullptr);
7342 mapData.IsAMapping.push_back(
true);
7343 mapData.IsAMember.push_back(checkIsAMember(mapVars, mapOp));
7346 auto findMapInfo = [&mapData](llvm::Value *val,
7347 llvm::OpenMPIRBuilder::DeviceInfoTy devInfoTy,
7348 size_t memberCount) {
7351 for (llvm::Value *basePtr : mapData.OriginalValue) {
7352 auto mapOp = cast<omp::MapInfoOp>(mapData.MapClause[index]);
7363 (mapData.Types[index] &
7364 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH) ==
7365 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH;
7366 if (!isAttachMap && basePtr == val && mapData.IsAMapping[index] &&
7367 memberCount == mapOp.getMembers().size()) {
7369 mapData.Types[index] |=
7370 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
7371 mapData.DevicePointers[index] = devInfoTy;
7379 auto addDevInfos = [&](
const llvm::ArrayRef<Value> &useDevOperands,
7380 llvm::OpenMPIRBuilder::DeviceInfoTy devInfoTy) {
7381 for (Value mapValue : useDevOperands) {
7382 auto mapOp = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
7384 mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtr() : mapOp.getVarPtr();
7385 llvm::Value *origValue = moduleTranslation.
lookupValue(offloadPtr);
7388 if (!findMapInfo(origValue, devInfoTy, mapOp.getMembers().size())) {
7389 mapData.OriginalValue.push_back(origValue);
7390 mapData.Pointers.push_back(mapData.OriginalValue.back());
7391 mapData.IsDeclareTarget.push_back(
false);
7392 mapData.BasePointers.push_back(mapData.OriginalValue.back());
7393 mlir::Type baseTy = mapOp.getVarPtrPtr()
7394 ? mapOp.getVarPtrPtrType().value()
7395 : mapOp.getVarPtrType();
7396 mapData.BaseType.push_back(moduleTranslation.
convertType(baseTy));
7397 mapData.Sizes.push_back(builder.getInt64(0));
7398 mapData.MapClause.push_back(mapOp.getOperation());
7399 mapData.Types.push_back(
7400 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM);
7402 mapData.HasAttachPtr.push_back(
false);
7403 mapData.Names.push_back(LLVM::createMappingInformation(
7405 mapData.DevicePointers.push_back(devInfoTy);
7406 mapData.Mappers.push_back(
nullptr);
7407 mapData.IsAMapping.push_back(
false);
7408 mapData.IsAMember.push_back(checkIsAMember(useDevOperands, mapOp));
7413 addDevInfos(useDevAddrOperands, llvm::OpenMPIRBuilder::DeviceInfoTy::Address);
7414 addDevInfos(useDevPtrOperands, llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer);
7416 for (Value mapValue : hasDevAddrOperands) {
7417 auto mapOp = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
7419 mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtr() : mapOp.getVarPtr();
7420 llvm::Value *origValue = moduleTranslation.
lookupValue(offloadPtr);
7422 auto mapTypeAlways = llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
7424 (mapOp.getMapType() & omp::ClauseMapFlags::is_device_ptr) !=
7425 omp::ClauseMapFlags::none;
7427 mapData.OriginalValue.push_back(origValue);
7428 mapData.BasePointers.push_back(origValue);
7429 mapData.Pointers.push_back(origValue);
7430 mapData.IsDeclareTarget.push_back(
false);
7432 mlir::Type baseTy = mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtrType().value()
7433 : mapOp.getVarPtrType();
7434 mapData.BaseType.push_back(moduleTranslation.
convertType(baseTy));
7435 mapData.Sizes.push_back(builder.getInt64(dl.
getTypeSize(baseTy)));
7437 mapData.MapClause.push_back(mapOp.getOperation());
7438 if (llvm::to_underlying(mapType & mapTypeAlways)) {
7442 mapData.Types.push_back(mapType);
7444 mapData.HasAttachPtr.push_back(
false);
7448 if (mapOp.getMapperId()) {
7449 mapData.Mappers.push_back(
7451 mapOp, mapOp.getMapperIdAttr()));
7453 mapData.Mappers.push_back(
nullptr);
7458 mapData.Types.push_back(
7459 isDevicePtr ? mapType
7460 : llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
7462 mapData.HasAttachPtr.push_back(
false);
7463 mapData.Mappers.push_back(
nullptr);
7465 mapData.Names.push_back(LLVM::createMappingInformation(
7467 mapData.DevicePointers.push_back(
7468 isDevicePtr ? llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer
7469 : llvm::OpenMPIRBuilder::DeviceInfoTy::Address);
7470 mapData.IsAMapping.push_back(
false);
7471 mapData.IsAMember.push_back(checkIsAMember(hasDevAddrOperands, mapOp));
7476 auto *res = llvm::find(mapData.MapClause, memberOp);
7477 assert(res != mapData.MapClause.end() &&
7478 "MapInfoOp for member not found in MapData, cannot return index");
7479 return std::distance(mapData.MapClause.begin(), res);
7483 omp::MapInfoOp mapInfo,
bool first =
true) {
7484 ArrayAttr indexAttr = mapInfo.getMembersIndexAttr();
7494 auto memberIndicesA = cast<ArrayAttr>(indexAttr[a]);
7495 auto memberIndicesB = cast<ArrayAttr>(indexAttr[b]);
7497 for (auto it : llvm::zip(memberIndicesA, memberIndicesB)) {
7498 int64_t aIndex = mlir::cast<IntegerAttr>(std::get<0>(it)).getInt();
7499 int64_t bIndex = mlir::cast<IntegerAttr>(std::get<1>(it)).getInt();
7501 if (aIndex == bIndex)
7504 if (aIndex < bIndex)
7507 if (aIndex > bIndex)
7514 bool memberAParent = memberIndicesA.size() < memberIndicesB.size();
7516 occludedChildren.push_back(
b);
7518 occludedChildren.push_back(a);
7519 return memberAParent;
7522 for (
auto v : occludedChildren)
7529 ArrayAttr indexAttr = mapInfo.getMembersIndexAttr();
7531 if (indexAttr.size() == 1)
7532 return cast<omp::MapInfoOp>(mapInfo.getMembers()[0].getDefiningOp());
7536 return llvm::cast<omp::MapInfoOp>(
7537 mapInfo.getMembers()[
indices.front()].getDefiningOp());
7560static std::vector<llvm::Value *>
7562 llvm::IRBuilderBase &builder,
bool isArrayTy,
7564 std::vector<llvm::Value *> idx;
7575 idx.push_back(builder.getInt64(0));
7576 for (
int i = bounds.size() - 1; i >= 0; --i) {
7577 if (
auto boundOp = dyn_cast_if_present<omp::MapBoundsOp>(
7578 bounds[i].getDefiningOp())) {
7579 idx.push_back(moduleTranslation.
lookupValue(boundOp.getLowerBound()));
7597 for (
int i = bounds.size() - 1; i >= 0; --i) {
7598 if (
auto boundOp = dyn_cast_if_present<omp::MapBoundsOp>(
7599 bounds[i].getDefiningOp())) {
7600 if (i == ((
int)bounds.size() - 1))
7602 moduleTranslation.
lookupValue(boundOp.getLowerBound()));
7604 idx.back() = builder.CreateAdd(
7605 builder.CreateMul(idx.back(), moduleTranslation.
lookupValue(
7606 boundOp.getExtent())),
7607 moduleTranslation.
lookupValue(boundOp.getLowerBound()));
7616 llvm::transform(values, std::back_inserter(ints), [](
Attribute value) {
7617 return cast<IntegerAttr>(value).getInt();
7625 omp::MapInfoOp parentOp) {
7627 if (parentOp.getMembers().empty())
7631 if (parentOp.getMembers().size() == 1) {
7632 overlapMapDataIdxs.push_back(0);
7636 ArrayAttr indexAttr = parentOp.getMembersIndexAttr();
7637 size_t numMembers = indexAttr.size();
7641 for (
auto [i, indicesAttr] : llvm::enumerate(indexAttr))
7642 getAsIntegers(cast<ArrayAttr>(indicesAttr), memberIndices[i]);
7648 llvm::SmallDenseSet<size_t> skipIndices;
7649 for (
size_t i = 0; i < numMembers; ++i) {
7650 const auto &iIndices = memberIndices[i];
7651 for (
size_t j = 0;
j < numMembers; ++
j) {
7654 const auto &jIndices = memberIndices[
j];
7656 if (jIndices.size() < iIndices.size() &&
7657 std::equal(jIndices.begin(), jIndices.end(), iIndices.begin())) {
7658 skipIndices.insert(i);
7665 for (
size_t i = 0; i < numMembers; ++i)
7666 if (!skipIndices.contains(i))
7667 overlapMapDataIdxs.push_back(i);
7681 llvm::OpenMPIRBuilder &ompBuilder, MapInfoData &mapData,
7682 size_t mapDataIdx, MapInfosTy &combinedInfo,
7683 TargetDirectiveEnumTy targetDirective,
7684 llvm::omp::OpenMPOffloadMappingFlags memberOfFlag =
7685 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE,
7686 bool isTargetParam =
true,
int mapDataParentIdx = -1) {
7687 auto mapFlag = mapData.Types[mapDataIdx];
7688 auto mapInfoOp = llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIdx]);
7692 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH) ==
7693 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
7699 if (isTargetParam &&
7700 (targetDirective == TargetDirectiveEnumTy::Target &&
7701 !mapData.IsDeclareTarget[mapDataIdx]) &&
7703 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7705 if (mapInfoOp.getMapCaptureType() == omp::VariableCaptureKind::ByCopy &&
7707 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL;
7716 if (memberOfFlag != llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE) {
7717 if (!isPtrTy && !isAttachMap)
7718 ompBuilder.setCorrectMemberOfFlag(mapFlag, memberOfFlag);
7725 mapFlag &=
~llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
7735 if (isPtrTy && !isAttachMap && mapData.IsDeclareTarget[mapDataIdx])
7736 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
7745 !bitEnumContainsAll(mapInfoOp.getMapType(),
7746 omp::ClauseMapFlags::ref_ptr) &&
7747 bitEnumContainsAll(mapInfoOp.getMapType(), omp::ClauseMapFlags::ref_ptee);
7748 bool isRefPtrPtee = bitEnumContainsAll(mapInfoOp.getMapType(),
7749 omp::ClauseMapFlags::ref_ptr |
7750 omp::ClauseMapFlags::ref_ptee);
7752 if (!mapInfoOp->getParentOfType<omp::DeclareMapperOp>() &&
7753 mapDataParentIdx >= 0 && !(isRefPtee || (isRefPtrPtee && isPtrTy))) {
7754 combinedInfo.BasePointers.emplace_back(
7755 mapData.BasePointers[mapDataParentIdx]);
7757 combinedInfo.BasePointers.emplace_back(mapData.BasePointers[mapDataIdx]);
7760 combinedInfo.Pointers.emplace_back(mapData.Pointers[mapDataIdx]);
7761 combinedInfo.DevicePointers.emplace_back(
7762 memberOfFlag != llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE
7763 ? llvm::OpenMPIRBuilder::DeviceInfoTy::None
7764 : mapData.DevicePointers[mapDataIdx]);
7765 combinedInfo.Mappers.emplace_back(mapData.Mappers[mapDataIdx]);
7766 combinedInfo.Names.emplace_back(mapData.Names[mapDataIdx]);
7767 combinedInfo.Types.emplace_back(mapFlag);
7769 combinedInfo.HasAttachPtr.emplace_back(
false);
7770 combinedInfo.Sizes.emplace_back(
7771 isPtrTy ? builder.CreateSelect(
7772 builder.CreateIsNull(mapData.Pointers[mapDataIdx]),
7773 builder.getInt64(0), mapData.Sizes[mapDataIdx])
7774 : mapData.Sizes[mapDataIdx]);
7794 llvm::OpenMPIRBuilder &ompBuilder,
DataLayout &dl, MapInfosTy &combinedInfo,
7795 MapInfoData &mapData, uint64_t mapDataIndex,
7796 llvm::omp::OpenMPOffloadMappingFlags memberOfFlag,
7797 TargetDirectiveEnumTy targetDirective) {
7798 using MapFlags = llvm::omp::OpenMPOffloadMappingFlags;
7799 assert(!ompBuilder.Config.isTargetDevice() &&
7800 "function only supported for host device codegen");
7802 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
7803 auto *parentMapper = mapData.Mappers[mapDataIndex];
7809 MapFlags baseFlag = (targetDirective == TargetDirectiveEnumTy::Target &&
7810 !mapData.IsDeclareTarget[mapDataIndex])
7811 ? MapFlags::OMP_MAP_TARGET_PARAM
7812 : MapFlags::OMP_MAP_NONE;
7818 MapFlags parentFlags = mapData.Types[mapDataIndex];
7819 MapFlags preserve = MapFlags::OMP_MAP_TO | MapFlags::OMP_MAP_FROM |
7820 MapFlags::OMP_MAP_ALWAYS | MapFlags::OMP_MAP_CLOSE |
7821 MapFlags::OMP_MAP_PRESENT |
7822 MapFlags::OMP_MAP_OMPX_HOLD |
7823 MapFlags::OMP_MAP_IMPLICIT;
7824 baseFlag |= (parentFlags & preserve);
7826 MapFlags parentFlags = mapData.Types[mapDataIndex];
7828 MapFlags::OMP_MAP_PRESENT | MapFlags::OMP_MAP_RETURN_PARAM;
7829 baseFlag |= (parentFlags & preserve);
7832 combinedInfo.Types.emplace_back(baseFlag);
7834 combinedInfo.HasAttachPtr.emplace_back(
false);
7835 combinedInfo.DevicePointers.emplace_back(
7836 mapData.DevicePointers[mapDataIndex]);
7840 combinedInfo.Mappers.emplace_back(
7841 parentMapper && !parentClause.getPartialMap() ? parentMapper :
nullptr);
7843 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder));
7844 combinedInfo.BasePointers.emplace_back(mapData.BasePointers[mapDataIndex]);
7853 llvm::Value *lowAddr, *highAddr;
7854 if (!parentClause.getPartialMap()) {
7855 lowAddr = builder.CreatePointerCast(mapData.Pointers[mapDataIndex],
7856 builder.getPtrTy());
7857 highAddr = builder.CreatePointerCast(
7858 builder.CreateConstGEP1_32(mapData.BaseType[mapDataIndex],
7859 mapData.Pointers[mapDataIndex], 1),
7860 builder.getPtrTy());
7861 combinedInfo.Pointers.emplace_back(mapData.Pointers[mapDataIndex]);
7863 auto mapOp = dyn_cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
7866 lowAddr = builder.CreatePointerCast(mapData.BasePointers[firstMemberIdx],
7867 builder.getPtrTy());
7871 auto lastMemberMapInfo =
7872 cast<omp::MapInfoOp>(mapData.MapClause[lastMemberIdx]);
7881 bool isRefPteeMap = bitEnumContainsAll(lastMemberMapInfo.getMapType(),
7882 omp::ClauseMapFlags::ref_ptee) &&
7883 !bitEnumContainsAll(lastMemberMapInfo.getMapType(),
7884 omp::ClauseMapFlags::ref_ptr);
7885 llvm::Type *castType = mapData.BaseType[lastMemberIdx];
7888 moduleTranslation.
convertType(lastMemberMapInfo.getVarPtrType());
7889 highAddr = builder.CreatePointerCast(
7890 builder.CreateGEP(castType, mapData.BasePointers[lastMemberIdx],
7891 builder.getInt64(1)),
7892 builder.getPtrTy());
7893 combinedInfo.Pointers.emplace_back(mapData.BasePointers[firstMemberIdx]);
7896 llvm::Value *size = builder.CreateIntCast(
7897 builder.CreatePtrDiff(builder.getInt8Ty(), highAddr, lowAddr),
7898 builder.getInt64Ty(),
7900 combinedInfo.Sizes.push_back(size);
7908 if (!parentClause.getPartialMap()) {
7913 MapFlags mapFlag = mapData.Types[mapDataIndex];
7914 bool hasMapClose = (MapFlags(mapFlag) & MapFlags::OMP_MAP_CLOSE) ==
7915 MapFlags::OMP_MAP_CLOSE;
7916 ompBuilder.setCorrectMemberOfFlag(mapFlag, memberOfFlag);
7932 if (targetDirective == TargetDirectiveEnumTy::TargetUpdate || hasMapClose ||
7933 overlapIdxs.size() == 1) {
7934 combinedInfo.Types.emplace_back(mapFlag);
7936 combinedInfo.HasAttachPtr.emplace_back(
false);
7937 combinedInfo.DevicePointers.emplace_back(
7938 mapData.DevicePointers[mapDataIndex]);
7940 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder));
7941 combinedInfo.BasePointers.emplace_back(
7942 mapData.BasePointers[mapDataIndex]);
7943 combinedInfo.Pointers.emplace_back(mapData.Pointers[mapDataIndex]);
7944 combinedInfo.Sizes.emplace_back(mapData.Sizes[mapDataIndex]);
7945 combinedInfo.Mappers.emplace_back(
nullptr);
7951 lowAddr = builder.CreatePointerCast(mapData.Pointers[mapDataIndex],
7952 builder.getPtrTy());
7953 highAddr = builder.CreatePointerCast(
7954 builder.CreateConstGEP1_32(mapData.BaseType[mapDataIndex],
7955 mapData.Pointers[mapDataIndex], 1),
7956 builder.getPtrTy());
7963 mapFlag &=
~llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
7970 for (
auto v : overlapIdxs) {
7973 cast<omp::MapInfoOp>(parentClause.getMembers()[v].getDefiningOp()));
7975 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataOverlapIdx]));
7976 combinedInfo.Types.emplace_back(mapFlag);
7978 combinedInfo.HasAttachPtr.emplace_back(
false);
7979 combinedInfo.DevicePointers.emplace_back(
7980 llvm::OpenMPIRBuilder::DeviceInfoTy::None);
7982 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder));
7983 combinedInfo.BasePointers.emplace_back(
7984 mapData.BasePointers[mapDataIndex]);
7985 combinedInfo.Mappers.emplace_back(
nullptr);
7986 combinedInfo.Pointers.emplace_back(lowAddr);
7987 auto sizeCalc = builder.CreateIntCast(
7988 builder.CreatePtrDiff(builder.getInt8Ty(),
7989 mapData.OriginalValue[mapDataOverlapIdx],
7991 builder.getInt64Ty(),
true);
7996 auto sizeSel = builder.CreateSelect(
7997 builder.CreateICmpNE(builder.getInt64(0), sizeCalc), sizeCalc,
7998 isPtrMap ? llvm::ConstantExpr::getSizeOf(builder.getPtrTy())
7999 : mapData.Sizes[mapDataOverlapIdx]);
8000 combinedInfo.Sizes.emplace_back(sizeSel);
8001 lowAddr = builder.CreateConstGEP1_32(
8002 isPtrMap ? builder.getPtrTy() : mapData.BaseType[mapDataOverlapIdx],
8003 mapData.BasePointers[mapDataOverlapIdx], 1);
8006 combinedInfo.Types.emplace_back(mapFlag);
8008 combinedInfo.HasAttachPtr.emplace_back(
false);
8009 combinedInfo.DevicePointers.emplace_back(
8010 llvm::OpenMPIRBuilder::DeviceInfoTy::None);
8012 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder));
8013 combinedInfo.BasePointers.emplace_back(
8014 mapData.BasePointers[mapDataIndex]);
8015 combinedInfo.Mappers.emplace_back(
nullptr);
8016 combinedInfo.Pointers.emplace_back(lowAddr);
8017 combinedInfo.Sizes.emplace_back(builder.CreateIntCast(
8018 builder.CreatePtrDiff(builder.getInt8Ty(), highAddr, lowAddr),
8019 builder.getInt64Ty(),
true));
8025 llvm::IRBuilderBase &builder,
8026 llvm::OpenMPIRBuilder &ompBuilder,
8028 MapInfoData &mapData, uint64_t mapDataIndex,
8029 TargetDirectiveEnumTy targetDirective) {
8030 assert(!ompBuilder.Config.isTargetDevice() &&
8031 "function only supported for host device codegen");
8034 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
8039 if (parentClause.getMembers().size() == 1 && parentClause.getPartialMap()) {
8040 auto memberClause = llvm::cast<omp::MapInfoOp>(
8041 parentClause.getMembers()[0].getDefiningOp());
8054 builder, ompBuilder, mapData, memberDataIdx, combinedInfo,
8056 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE,
8057 true, mapDataIndex);
8061 auto collectMapInfoIdxs =
8064 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
8066 for (
auto member : parentClause.getMembers())
8068 mapData, llvm::cast<omp::MapInfoOp>(member.getDefiningOp())));
8072 collectMapInfoIdxs(mapInfoIdx);
8074 llvm::omp::OpenMPOffloadMappingFlags memberOfFlag =
8075 ompBuilder.getMemberOfFlag(combinedInfo.Types.size());
8076 for (
size_t i = 0; i < mapInfoIdx.size(); i++) {
8081 combinedInfo, mapData, mapInfoIdx[i], memberOfFlag,
8085 combinedInfo, targetDirective, memberOfFlag,
8086 false, mapDataIndex);
8098 llvm::IRBuilderBase &builder) {
8100 "function only supported for host device codegen");
8101 for (
size_t i = 0; i < mapData.MapClause.size(); ++i) {
8102 auto mapOp = cast<omp::MapInfoOp>(mapData.MapClause[i]);
8105 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH) ==
8106 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
8111 if (!mapData.IsDeclareTarget[i] ||
8112 (mapData.IsDeclareTarget[i] && isAttachMap)) {
8113 omp::VariableCaptureKind captureKind = mapOp.getMapCaptureType();
8123 switch (captureKind) {
8124 case omp::VariableCaptureKind::ByRef: {
8125 llvm::Value *newV = mapData.Pointers[i];
8127 moduleTranslation, builder, mapData.BaseType[i]->isArrayTy(),
8130 newV = builder.CreateLoad(builder.getPtrTy(), newV);
8132 if (!offsetIdx.empty())
8133 newV = builder.CreateInBoundsGEP(mapData.BaseType[i], newV, offsetIdx,
8135 mapData.Pointers[i] = newV;
8137 case omp::VariableCaptureKind::ByCopy: {
8138 llvm::Type *type = mapData.BaseType[i];
8140 if (mapData.Pointers[i]->getType()->isPointerTy())
8141 newV = builder.CreateLoad(type, mapData.Pointers[i]);
8143 newV = mapData.Pointers[i];
8146 auto curInsert = builder.saveIP();
8147 llvm::DebugLoc DbgLoc = builder.getCurrentDebugLocation();
8149 auto *memTempAlloc =
8150 builder.CreateAlloca(builder.getPtrTy(),
nullptr,
".casted");
8151 builder.SetCurrentDebugLocation(DbgLoc);
8152 builder.restoreIP(curInsert);
8154 builder.CreateStore(newV, memTempAlloc);
8155 newV = builder.CreateLoad(builder.getPtrTy(), memTempAlloc);
8158 mapData.Pointers[i] = newV;
8159 mapData.BasePointers[i] = newV;
8161 case omp::VariableCaptureKind::This:
8162 case omp::VariableCaptureKind::VLAType:
8163 mapData.MapClause[i]->emitOpError(
"Unhandled capture kind");
8174 MapInfoData &mapData,
8175 TargetDirectiveEnumTy targetDirective) {
8177 "function only supported for host device codegen");
8198 for (
size_t i = 0; i < mapData.MapClause.size(); ++i) {
8199 if (mapData.IsAMember[i])
8202 auto mapInfoOp = dyn_cast<omp::MapInfoOp>(mapData.MapClause[i]);
8203 if (!mapInfoOp.getMembers().empty()) {
8205 combinedInfo, mapData, i, targetDirective);
8214static llvm::Expected<llvm::Function *>
8216 LLVM::ModuleTranslation &moduleTranslation,
8217 llvm::StringRef mapperFuncName,
8218 TargetDirectiveEnumTy targetDirective);
8220static llvm::Expected<llvm::Function *>
8223 TargetDirectiveEnumTy targetDirective) {
8225 "function only supported for host device codegen");
8226 auto declMapperOp = cast<omp::DeclareMapperOp>(op);
8227 std::string mapperFuncName =
8229 {
"omp_mapper", declMapperOp.getSymName()});
8231 if (
auto *lookupFunc = moduleTranslation.
lookupFunction(mapperFuncName))
8239 if (llvm::Function *existingFunc =
8240 moduleTranslation.
getLLVMModule()->getFunction(mapperFuncName)) {
8241 moduleTranslation.
mapFunction(mapperFuncName, existingFunc);
8242 return existingFunc;
8246 mapperFuncName, targetDirective);
8249static llvm::Expected<llvm::Function *>
8252 llvm::StringRef mapperFuncName,
8253 TargetDirectiveEnumTy targetDirective) {
8255 "function only supported for host device codegen");
8256 auto declMapperOp = cast<omp::DeclareMapperOp>(op);
8257 auto declMapperInfoOp = declMapperOp.getDeclareMapperInfo();
8259 return llvm::make_error<PreviouslyReportedError>();
8263 llvm::Type *varType = moduleTranslation.
convertType(declMapperOp.getType());
8266 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
8269 MapInfosTy combinedInfo;
8271 [&](InsertPointTy codeGenIP, llvm::Value *ptrPHI,
8272 llvm::Value *unused2) -> llvm::OpenMPIRBuilder::MapInfosOrErrorTy {
8273 builder.restoreIP(codeGenIP);
8274 moduleTranslation.
mapValue(declMapperOp.getSymVal(), ptrPHI);
8275 moduleTranslation.
mapBlock(&declMapperOp.getRegion().front(),
8276 builder.GetInsertBlock());
8277 if (failed(moduleTranslation.
convertBlock(declMapperOp.getRegion().front(),
8280 return llvm::make_error<PreviouslyReportedError>();
8281 MapInfoData mapData;
8284 genMapInfos(builder, moduleTranslation, dl, combinedInfo, mapData,
8290 return combinedInfo;
8294 if (!combinedInfo.Mappers[i])
8297 moduleTranslation, targetDirective);
8301 genMapInfoCB, varType, mapperFuncName, customMapperCB,
8304 return newFn.takeError();
8305 if ([[maybe_unused]] llvm::Function *mappedFunc =
8307 assert(mappedFunc == *newFn &&
8308 "mapper function mapping disagrees with emitted function");
8310 moduleTranslation.
mapFunction(mapperFuncName, *newFn);
8318 llvm::Value *ifCond =
nullptr;
8319 llvm::Value *deviceID = builder.getInt64(llvm::omp::OMP_DEVICEID_UNDEF);
8323 llvm::omp::RuntimeFunction RTLFn;
8325 TargetDirectiveEnumTy targetDirective = getTargetDirectiveEnumTyFromOp(op);
8328 llvm::OpenMPIRBuilder::TargetDataInfo info(
8331 assert(!ompBuilder->Config.isTargetDevice() &&
8332 "target data/enter/exit/update are host ops");
8333 bool isOffloadEntry = !ompBuilder->Config.TargetTriples.empty();
8335 auto getDeviceID = [&](
mlir::Value dev) -> llvm::Value * {
8336 llvm::Value *v = moduleTranslation.
lookupValue(dev);
8337 return builder.CreateIntCast(v, builder.getInt64Ty(),
true);
8342 .Case([&](omp::TargetDataOp dataOp) {
8346 if (
auto ifVar = dataOp.getIfExpr())
8350 deviceID = getDeviceID(devId);
8352 mapVars = dataOp.getMapVars();
8353 useDevicePtrVars = dataOp.getUseDevicePtrVars();
8354 useDeviceAddrVars = dataOp.getUseDeviceAddrVars();
8357 .Case([&](omp::TargetEnterDataOp enterDataOp) -> LogicalResult {
8361 if (
auto ifVar = enterDataOp.getIfExpr())
8365 deviceID = getDeviceID(devId);
8368 enterDataOp.getNowait()
8369 ? llvm::omp::OMPRTL___tgt_target_data_begin_nowait_mapper
8370 : llvm::omp::OMPRTL___tgt_target_data_begin_mapper;
8371 mapVars = enterDataOp.getMapVars();
8372 info.HasNoWait = enterDataOp.getNowait();
8375 .Case([&](omp::TargetExitDataOp exitDataOp) -> LogicalResult {
8379 if (
auto ifVar = exitDataOp.getIfExpr())
8383 deviceID = getDeviceID(devId);
8385 RTLFn = exitDataOp.getNowait()
8386 ? llvm::omp::OMPRTL___tgt_target_data_end_nowait_mapper
8387 : llvm::omp::OMPRTL___tgt_target_data_end_mapper;
8388 mapVars = exitDataOp.getMapVars();
8389 info.HasNoWait = exitDataOp.getNowait();
8392 .Case([&](omp::TargetUpdateOp updateDataOp) -> LogicalResult {
8396 if (
auto ifVar = updateDataOp.getIfExpr())
8400 deviceID = getDeviceID(devId);
8403 updateDataOp.getNowait()
8404 ? llvm::omp::OMPRTL___tgt_target_data_update_nowait_mapper
8405 : llvm::omp::OMPRTL___tgt_target_data_update_mapper;
8406 mapVars = updateDataOp.getMapVars();
8407 info.HasNoWait = updateDataOp.getNowait();
8410 .DefaultUnreachable(
"unexpected operation");
8415 if (!isOffloadEntry)
8416 ifCond = builder.getFalse();
8418 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
8419 MapInfoData mapData;
8421 builder, useDevicePtrVars, useDeviceAddrVars);
8424 MapInfosTy combinedInfo;
8425 auto genMapInfoCB = [&](InsertPointTy codeGenIP) -> MapInfosTy & {
8426 builder.restoreIP(codeGenIP);
8427 genMapInfos(builder, moduleTranslation, DL, combinedInfo, mapData,
8429 return combinedInfo;
8435 [&moduleTranslation](
8436 llvm::OpenMPIRBuilder::DeviceInfoTy type,
8440 for (
auto [arg, useDevVar] :
8441 llvm::zip_equal(blockArgs, useDeviceVars)) {
8443 auto getMapBasePtr = [](omp::MapInfoOp mapInfoOp) {
8444 return mapInfoOp.getVarPtrPtr() ? mapInfoOp.getVarPtrPtr()
8445 : mapInfoOp.getVarPtr();
8448 auto useDevMap = cast<omp::MapInfoOp>(useDevVar.getDefiningOp());
8449 for (
auto [mapClause, devicePointer, basePointer] : llvm::zip_equal(
8450 mapInfoData.MapClause, mapInfoData.DevicePointers,
8451 mapInfoData.BasePointers)) {
8452 auto mapOp = cast<omp::MapInfoOp>(mapClause);
8453 if (getMapBasePtr(mapOp) != getMapBasePtr(useDevMap) ||
8454 devicePointer != type)
8457 if (llvm::Value *devPtrInfoMap =
8458 mapper ? mapper(basePointer) : basePointer) {
8459 moduleTranslation.
mapValue(arg, devPtrInfoMap);
8466 using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy;
8467 auto bodyGenCB = [&](InsertPointTy codeGenIP, BodyGenTy bodyGenType)
8468 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
8471 builder.restoreIP(codeGenIP);
8472 assert(isa<omp::TargetDataOp>(op) &&
8473 "BodyGen requested for non TargetDataOp");
8474 auto blockArgIface = cast<omp::BlockArgOpenMPOpInterface>(op);
8475 Region ®ion = cast<omp::TargetDataOp>(op).getRegion();
8476 switch (bodyGenType) {
8477 case BodyGenTy::Priv:
8479 if (!info.DevicePtrInfoMap.empty()) {
8480 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Address,
8481 blockArgIface.getUseDeviceAddrBlockArgs(),
8482 useDeviceAddrVars, mapData,
8483 [&](llvm::Value *basePointer) -> llvm::Value * {
8484 if (!info.DevicePtrInfoMap[basePointer].second)
8486 return builder.CreateLoad(
8488 info.DevicePtrInfoMap[basePointer].second);
8490 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer,
8491 blockArgIface.getUseDevicePtrBlockArgs(), useDevicePtrVars,
8492 mapData, [&](llvm::Value *basePointer) {
8493 return info.DevicePtrInfoMap[basePointer].second;
8497 moduleTranslation)))
8498 return llvm::make_error<PreviouslyReportedError>();
8501 case BodyGenTy::DupNoPriv:
8502 if (info.DevicePtrInfoMap.empty()) {
8505 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Address,
8506 blockArgIface.getUseDeviceAddrBlockArgs(),
8507 useDeviceAddrVars, mapData);
8508 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer,
8509 blockArgIface.getUseDevicePtrBlockArgs(), useDevicePtrVars,
8513 case BodyGenTy::NoPriv:
8515 if (info.DevicePtrInfoMap.empty()) {
8517 moduleTranslation)))
8518 return llvm::make_error<PreviouslyReportedError>();
8522 return builder.saveIP();
8525 auto customMapperCB =
8527 if (!combinedInfo.Mappers[i])
8529 info.HasMapper =
true;
8531 moduleTranslation, targetDirective);
8534 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
8536 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
8538 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP = [&]() {
8539 if (isa<omp::TargetDataOp>(op))
8540 return ompBuilder->createTargetData(ompLoc, allocaIP, builder.saveIP(),
8541 deallocBlocks, deviceID, ifCond, info,
8542 genMapInfoCB, customMapperCB,
8545 return ompBuilder->createTargetData(ompLoc, allocaIP, builder.saveIP(),
8546 deallocBlocks, deviceID, ifCond, info,
8547 genMapInfoCB, customMapperCB, &RTLFn);
8553 builder.restoreIP(*afterIP);
8561 auto distributeOp = cast<omp::DistributeOp>(opInst);
8568 bool doDistributeReduction =
8572 unsigned numReductionVars = teamsOp ? teamsOp.getNumReductionVars() : 0;
8577 if (doDistributeReduction) {
8578 isByRef =
getIsByRef(teamsOp.getReductionByref());
8579 assert(isByRef.size() == teamsOp.getNumReductionVars());
8582 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
8586 llvm::cast<omp::BlockArgOpenMPOpInterface>(*teamsOp)
8587 .getReductionBlockArgs();
8590 teamsOp, reductionArgs, builder, moduleTranslation, allocaIP,
8591 reductionDecls, privateReductionVariables, reductionVariableMap,
8596 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
8598 [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
8603 moduleTranslation, allocaIP, deallocBlocks);
8606 builder.restoreIP(codeGenIP);
8610 distributeOp, builder, moduleTranslation, privVarsInfo, allocaIP);
8612 return llvm::make_error<PreviouslyReportedError>();
8617 return llvm::make_error<PreviouslyReportedError>();
8620 distributeOp, builder, moduleTranslation, privVarsInfo.
mlirVars,
8622 distributeOp.getPrivateNeedsBarrier())))
8623 return llvm::make_error<PreviouslyReportedError>();
8626 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
8629 builder, moduleTranslation);
8631 return regionBlock.takeError();
8632 builder.SetInsertPoint(*regionBlock, (*regionBlock)->begin());
8637 if (!isa_and_present<omp::WsloopOp>(distributeOp.getNestedWrapper())) {
8640 bool hasDistSchedule = distributeOp.getDistScheduleStatic();
8641 auto schedule = hasDistSchedule ? omp::ClauseScheduleKind::Distribute
8642 : omp::ClauseScheduleKind::Static;
8644 bool isOrdered = hasDistSchedule;
8645 std::optional<omp::ScheduleModifier> scheduleMod;
8646 bool isSimd =
false;
8647 llvm::omp::WorksharingLoopType workshareLoopType =
8648 llvm::omp::WorksharingLoopType::DistributeStaticLoop;
8649 bool loopNeedsBarrier =
false;
8650 llvm::Value *chunk = moduleTranslation.
lookupValue(
8651 distributeOp.getDistScheduleChunkSize());
8652 llvm::CanonicalLoopInfo *loopInfo =
8654 llvm::OpenMPIRBuilder::InsertPointOrErrorTy wsloopIP =
8655 ompBuilder->applyWorkshareLoop(
8656 ompLoc.DL, loopInfo, allocaIP, loopNeedsBarrier,
8657 convertToScheduleKind(schedule), chunk, isSimd,
8658 scheduleMod == omp::ScheduleModifier::monotonic,
8659 scheduleMod == omp::ScheduleModifier::nonmonotonic, isOrdered,
8660 workshareLoopType,
false, hasDistSchedule, chunk);
8663 return wsloopIP.takeError();
8666 distributeOp.getLoc(), privVarsInfo)))
8667 return llvm::make_error<PreviouslyReportedError>();
8669 return llvm::Error::success();
8673 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
8675 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
8676 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
8677 ompBuilder->createDistribute(ompLoc, allocaIP, deallocBlocks, bodyGenCB);
8682 builder.restoreIP(*afterIP);
8684 if (doDistributeReduction) {
8687 teamsOp, builder, moduleTranslation, allocaIP, reductionDecls,
8688 privateReductionVariables, isByRef,
8700 auto offloadMod = dyn_cast<omp::OffloadModuleInterface>(op);
8702 return op->
emitOpError() <<
"omp flags attached to non offload module op";
8706 if (offloadMod.getIsTargetDevice())
8707 ompBuilder->M.addModuleFlag(llvm::Module::Max,
"openmp-device",
8708 attribute.getOpenmpDeviceVersion());
8711 if (!offloadMod.getIsGPU())
8714 if (attribute.getNoGpuLib())
8717 ompBuilder->createGlobalFlag(attribute.getDebugKind(),
8718 "__omp_rtl_debug_kind");
8719 ompBuilder->createGlobalFlag(attribute.getAssumeTeamsOversubscription(),
8720 "__omp_rtl_assume_teams_oversubscription");
8721 ompBuilder->createGlobalFlag(attribute.getAssumeThreadsOversubscription(),
8722 "__omp_rtl_assume_threads_oversubscription");
8723 ompBuilder->createGlobalFlag(attribute.getAssumeNoThreadState(),
8724 "__omp_rtl_assume_no_thread_state");
8725 ompBuilder->createGlobalFlag(attribute.getAssumeNoNestedParallelism(),
8726 "__omp_rtl_assume_no_nested_parallelism");
8731 omp::TargetOp targetOp,
8732 llvm::OpenMPIRBuilder &ompBuilder,
8733 llvm::vfs::FileSystem &vfs,
8734 llvm::StringRef parentName =
"") {
8735 auto fileLoc = targetOp.getLoc()->findInstanceOf<
FileLineColLoc>();
8736 assert(fileLoc &&
"No file found from location");
8738 auto fileInfoCallBack = [&fileLoc]() {
8739 return std::pair<std::string, uint64_t>(
8740 llvm::StringRef(fileLoc.getFilename()), fileLoc.getLine());
8744 ompBuilder.getTargetEntryUniqueInfo(fileInfoCallBack, vfs, parentName);
8787 omp::TargetOp targetOp, MapInfoData &mapData, llvm::Argument &arg,
8788 llvm::Value *input, llvm::Value *&retVal, llvm::IRBuilderBase &builder,
8789 llvm::OpenMPIRBuilder &ompBuilder,
8791 llvm::IRBuilderBase::InsertPoint allocaIP,
8792 llvm::IRBuilderBase::InsertPoint codeGenIP,
8794 assert(ompBuilder.Config.isTargetDevice() &&
8795 "function only supported for target device codegen");
8796 builder.restoreIP(allocaIP);
8798 omp::VariableCaptureKind capture = omp::VariableCaptureKind::ByRef;
8800 ompBuilder.M.getContext());
8801 unsigned alignmentValue = 0;
8804 cast<omp::BlockArgOpenMPOpInterface>(*targetOp).getBlockArgsPairs(
8807 for (
size_t i = 0; i < mapData.MapClause.size(); ++i) {
8808 if (mapData.OriginalValue[i] == input) {
8809 auto mapOp = cast<omp::MapInfoOp>(mapData.MapClause[i]);
8810 capture = mapOp.getMapCaptureType();
8813 mapOp.getVarPtrType(), ompBuilder.M.getDataLayout());
8817 for (
auto &[val, arg] : blockArgsPairs) {
8818 if (mapOp.getResult() == val) {
8823 assert(mlirArg &&
"expected to find entry block argument for map clause");
8828 unsigned int allocaAS = ompBuilder.M.getDataLayout().getAllocaAddrSpace();
8829 unsigned int defaultAS =
8830 ompBuilder.M.getDataLayout().getProgramAddressSpace();
8833 llvm::Value *v =
nullptr;
8841 builder.SetInsertPoint(codeGenIP.getBlock()->getFirstInsertionPt());
8842 v = ompBuilder.createOMPAllocShared(builder, arg.getType());
8846 llvm::IRBuilderBase::InsertPointGuard guard(builder);
8847 for (
auto deallocIP : deallocIPs) {
8848 builder.SetInsertPoint(deallocIP.getBlock(), deallocIP.getPoint());
8849 ompBuilder.createOMPFreeShared(builder, v, arg.getType());
8853 v = builder.CreateAlloca(arg.getType(), allocaAS);
8855 if (allocaAS != defaultAS && arg.getType()->isPointerTy())
8856 v = builder.CreateAddrSpaceCast(v, builder.getPtrTy(defaultAS));
8859 builder.CreateStore(&arg, v);
8861 builder.restoreIP(codeGenIP);
8864 case omp::VariableCaptureKind::ByCopy: {
8868 case omp::VariableCaptureKind::ByRef: {
8869 llvm::LoadInst *loadInst = builder.CreateAlignedLoad(
8871 ompBuilder.M.getDataLayout().getPrefTypeAlign(v->getType()));
8886 if (v->getType()->isPointerTy() && alignmentValue) {
8887 llvm::MDBuilder MDB(builder.getContext());
8888 loadInst->setMetadata(
8889 llvm::LLVMContext::MD_align,
8890 llvm::MDNode::get(builder.getContext(),
8891 MDB.createConstant(llvm::ConstantInt::get(
8892 llvm::Type::getInt64Ty(builder.getContext()),
8899 case omp::VariableCaptureKind::This:
8900 case omp::VariableCaptureKind::VLAType:
8903 assert(
false &&
"Currently unsupported capture kind");
8907 return builder.saveIP();
8924 auto blockArgIface = llvm::cast<omp::BlockArgOpenMPOpInterface>(*targetOp);
8925 for (
auto item : llvm::zip_equal(targetOp.getHostEvalVars(),
8926 blockArgIface.getHostEvalBlockArgs())) {
8927 Value hostEvalVar = std::get<0>(item), blockArg = std::get<1>(item);
8931 .Case([&](omp::TeamsOp teamsOp) {
8932 if (teamsOp.getNumTeamsLower() == blockArg)
8933 numTeamsLower = hostEvalVar;
8934 else if (llvm::is_contained(teamsOp.getNumTeamsUpperVars(),
8936 numTeamsUpper = hostEvalVar;
8937 else if (!teamsOp.getThreadLimitVars().empty() &&
8938 teamsOp.getThreadLimit(0) == blockArg)
8939 threadLimit = hostEvalVar;
8941 llvm_unreachable(
"unsupported host_eval use");
8943 .Case([&](omp::ParallelOp parallelOp) {
8944 if (!parallelOp.getNumThreadsVars().empty() &&
8945 parallelOp.getNumThreads(0) == blockArg)
8946 numThreads = hostEvalVar;
8948 llvm_unreachable(
"unsupported host_eval use");
8950 .Case([&](omp::LoopNestOp loopOp) {
8951 auto processBounds =
8955 for (
auto [i, lb] : llvm::enumerate(opBounds)) {
8956 if (lb == blockArg) {
8959 (*outBounds)[i] = hostEvalVar;
8965 processBounds(loopOp.getLoopLowerBounds(), lowerBounds);
8966 found = processBounds(loopOp.getLoopUpperBounds(), upperBounds) ||
8968 found = processBounds(loopOp.getLoopSteps(), steps) || found;
8970 assert(found &&
"unsupported host_eval use");
8972 .DefaultUnreachable(
"unsupported host_eval use");
8984template <
typename OpTy>
8989 if (OpTy casted = dyn_cast<OpTy>(op))
8992 if (immediateParent)
8993 return dyn_cast_if_present<OpTy>(op->
getParentOp());
9002 return std::nullopt;
9005 if (
auto constAttr = dyn_cast<IntegerAttr>(constOp.getValue()))
9006 return constAttr.getInt();
9008 return std::nullopt;
9013 uint64_t sizeInBytes = sizeInBits / 8;
9017template <
typename OpTy>
9019 if (op.getNumReductionVars() > 0) {
9024 members.reserve(reductions.size());
9025 for (omp::DeclareReductionOp &red : reductions) {
9029 if (red.getByrefElementType())
9030 members.push_back(*red.getByrefElementType());
9032 members.push_back(red.getType());
9035 auto structType = mlir::LLVM::LLVMStructType::getLiteral(
9051 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &attrs,
9052 bool isTargetDevice,
bool isGPU) {
9055 Value numThreads, numTeamsLower, numTeamsUpper, threadLimit;
9056 if (!isTargetDevice) {
9064 numTeamsLower = teamsOp.getNumTeamsLower();
9066 if (!teamsOp.getNumTeamsUpperVars().empty())
9067 numTeamsUpper = teamsOp.getNumTeams(0);
9068 if (!teamsOp.getThreadLimitVars().empty())
9069 threadLimit = teamsOp.getThreadLimit(0);
9073 if (!parallelOp.getNumThreadsVars().empty())
9074 numThreads = parallelOp.getNumThreads(0);
9080 int32_t minTeamsVal = 1, maxTeamsVal = -1;
9084 if (numTeamsUpper) {
9086 minTeamsVal = maxTeamsVal = *val;
9088 minTeamsVal = maxTeamsVal = 0;
9094 minTeamsVal = maxTeamsVal = 1;
9096 minTeamsVal = maxTeamsVal = -1;
9101 auto setMaxValueFromClause = [](
Value clauseValue, int32_t &
result) {
9115 int32_t targetThreadLimitVal = -1, teamsThreadLimitVal = -1;
9116 if (!targetOp.getThreadLimitVars().empty())
9117 setMaxValueFromClause(targetOp.getThreadLimit(0), targetThreadLimitVal);
9118 setMaxValueFromClause(threadLimit, teamsThreadLimitVal);
9121 int32_t maxThreadsVal = -1;
9123 setMaxValueFromClause(numThreads, maxThreadsVal);
9131 int32_t combinedMaxThreadsVal = targetThreadLimitVal;
9132 if (combinedMaxThreadsVal < 0 ||
9133 (teamsThreadLimitVal >= 0 && teamsThreadLimitVal < combinedMaxThreadsVal))
9134 combinedMaxThreadsVal = teamsThreadLimitVal;
9136 if (combinedMaxThreadsVal < 0 ||
9137 (maxThreadsVal >= 0 && maxThreadsVal < combinedMaxThreadsVal))
9138 combinedMaxThreadsVal = maxThreadsVal;
9140 int32_t reductionDataSize = 0;
9141 if (isGPU && capturedOp) {
9148 omp::TargetExecMode execMode = targetOp.getKernelType();
9150 case omp::TargetExecMode::bare:
9151 attrs.ExecFlags = llvm::omp::OMP_TGT_EXEC_MODE_BARE;
9153 case omp::TargetExecMode::generic:
9154 attrs.ExecFlags = llvm::omp::OMP_TGT_EXEC_MODE_GENERIC;
9156 case omp::TargetExecMode::spmd:
9157 attrs.ExecFlags = llvm::omp::OMP_TGT_EXEC_MODE_SPMD;
9159 case omp::TargetExecMode::spmd_no_loop:
9160 attrs.ExecFlags = llvm::omp::OMP_TGT_EXEC_MODE_SPMD_NO_LOOP;
9163 attrs.MinTeams.front() = minTeamsVal;
9164 attrs.MaxTeams.front() = maxTeamsVal;
9165 attrs.MinThreads.front() = 1;
9166 attrs.MaxThreads.front() = combinedMaxThreadsVal;
9167 attrs.ReductionDataSize = reductionDataSize;
9179 omp::TargetOp targetOp,
Operation *capturedOp,
9180 llvm::OpenMPIRBuilder::TargetKernelRuntimeAttrs &attrs) {
9182 unsigned numLoops = loopOp ? loopOp.getNumLoops() : 0;
9184 Value numThreads, numTeamsLower, numTeamsUpper, teamsThreadLimit;
9188 teamsThreadLimit, &lowerBounds, &upperBounds, &steps);
9191 if (!targetOp.getThreadLimitVars().empty()) {
9192 Value targetThreadLimit = targetOp.getThreadLimit(0);
9193 attrs.TargetThreadLimit.front() =
9201 attrs.MinTeams.front() = builder.CreateSExtOrTrunc(
9202 moduleTranslation.
lookupValue(numTeamsLower), builder.getInt32Ty());
9205 attrs.MaxTeams.front() = builder.CreateSExtOrTrunc(
9206 moduleTranslation.
lookupValue(numTeamsUpper), builder.getInt32Ty());
9208 if (teamsThreadLimit)
9209 attrs.TeamsThreadLimit.front() = builder.CreateSExtOrTrunc(
9210 moduleTranslation.
lookupValue(teamsThreadLimit), builder.getInt32Ty());
9213 attrs.MaxThreads.front() = moduleTranslation.
lookupValue(numThreads);
9215 if (targetOp.hasHostEvalTripCount()) {
9217 attrs.LoopTripCount =
nullptr;
9222 for (
auto [loopLower, loopUpper, loopStep] :
9223 llvm::zip_equal(lowerBounds, upperBounds, steps)) {
9224 llvm::Value *lowerBound = moduleTranslation.
lookupValue(loopLower);
9225 llvm::Value *upperBound = moduleTranslation.
lookupValue(loopUpper);
9226 llvm::Value *step = moduleTranslation.
lookupValue(loopStep);
9228 if (!lowerBound || !upperBound || !step) {
9229 attrs.LoopTripCount =
nullptr;
9233 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
9234 llvm::Value *tripCount = ompBuilder->calculateCanonicalLoopTripCount(
9235 loc, lowerBound, upperBound, step,
true,
9236 loopOp.getLoopInclusive());
9238 if (!attrs.LoopTripCount) {
9239 attrs.LoopTripCount = tripCount;
9244 attrs.LoopTripCount = builder.CreateMul(attrs.LoopTripCount, tripCount,
9249 attrs.DeviceID = builder.getInt64(llvm::omp::OMP_DEVICEID_UNDEF);
9251 attrs.DeviceID = moduleTranslation.
lookupValue(devId);
9253 builder.CreateSExtOrTrunc(attrs.DeviceID, builder.getInt64Ty());
9257static llvm::omp::OMPDynGroupprivateFallbackType
9259 omp::FallbackModifier fb = fallbackAttr ? fallbackAttr.getValue()
9260 : omp::FallbackModifier::default_mem;
9262 case omp::FallbackModifier::abort:
9263 return llvm::omp::OMPDynGroupprivateFallbackType::Abort;
9264 case omp::FallbackModifier::null:
9265 return llvm::omp::OMPDynGroupprivateFallbackType::Null;
9266 case omp::FallbackModifier::default_mem:
9267 return llvm::omp::OMPDynGroupprivateFallbackType::DefaultMem;
9270 llvm_unreachable(
"unexpected dyn_groupprivate fallback type");
9276 auto targetOp = cast<omp::TargetOp>(opInst);
9281 llvm::DebugLoc outlinedFnLoc = builder.getCurrentDebugLocation();
9290 llvm::BasicBlock *parentBB = builder.GetInsertBlock();
9291 assert(parentBB &&
"No insert block is set for the builder");
9292 llvm::Function *parentLLVMFn = parentBB->getParent();
9293 assert(parentLLVMFn &&
"Parent Function must be valid");
9294 if (llvm::DISubprogram *SP = parentLLVMFn->getSubprogram())
9295 builder.SetCurrentDebugLocation(llvm::DILocation::get(
9296 parentLLVMFn->getContext(), outlinedFnLoc.getLine(),
9297 outlinedFnLoc.getCol(), SP, outlinedFnLoc.getInlinedAt()));
9300 bool isTargetDevice = ompBuilder->Config.isTargetDevice();
9301 bool isGPU = ompBuilder->Config.isGPU();
9304 auto argIface = cast<omp::BlockArgOpenMPOpInterface>(opInst);
9305 auto &targetRegion = targetOp.getRegion();
9322 llvm::Function *llvmOutlinedFn =
nullptr;
9323 TargetDirectiveEnumTy targetDirective =
9324 getTargetDirectiveEnumTyFromOp(&opInst);
9328 bool isOffloadEntry =
9329 isTargetDevice || !ompBuilder->Config.TargetTriples.empty();
9349 if (!targetOp.getInReductionVars().empty() && !isTargetDevice) {
9350 inRedOrigPtrs.reserve(targetOp.getInReductionVars().size());
9351 inRedMapArgIdx.reserve(targetOp.getInReductionVars().size());
9352 for (
Value v : targetOp.getInReductionVars()) {
9357 std::optional<unsigned> matchIdx;
9358 for (
auto [idx, mapV] : llvm::enumerate(targetOp.getMapVars())) {
9359 auto mapInfo = mapV.getDefiningOp<omp::MapInfoOp>();
9360 if (v != mapInfo.getVarPtr())
9363 return targetOp.emitError()
9364 <<
"in_reduction variable on omp.target has multiple matching "
9365 "map_entries entries; the redirect target is ambiguous";
9371 "TargetOp verifier guarantees a matching map_entries entry for "
9372 "each in_reduction variable");
9373 inRedMapArgIdx.push_back(*matchIdx);
9376 inRedOrigPtrs.push_back(moduleTranslation.
lookupValue(v));
9385 if (!targetOp.getPrivateVars().empty() && !targetOp.getMapVars().empty()) {
9387 std::optional<ArrayAttr> privateSyms = targetOp.getPrivateSyms();
9388 std::optional<DenseI64ArrayAttr> privateMapIndices =
9389 targetOp.getPrivateMapsAttr();
9391 for (
auto [privVarIdx, privVarSymPair] :
9392 llvm::enumerate(llvm::zip_equal(privateVars, *privateSyms))) {
9393 auto privVar = std::get<0>(privVarSymPair);
9394 auto privSym = std::get<1>(privVarSymPair);
9396 SymbolRefAttr privatizerName = llvm::cast<SymbolRefAttr>(privSym);
9397 omp::PrivateClauseOp privatizer =
9400 if (!privatizer.needsMap())
9404 targetOp.getMappedValueForPrivateVar(privVarIdx);
9405 assert(mappedValue &&
"Expected to find mapped value for a privatized "
9406 "variable that needs mapping");
9411 auto mapInfoOp = mappedValue.
getDefiningOp<omp::MapInfoOp>();
9412 [[maybe_unused]]
Type varType = mapInfoOp.getVarPtrType();
9416 if (!isa<LLVM::LLVMPointerType>(privVar.getType()))
9418 varType == privVar.getType() &&
9419 "Type of private var doesn't match the type of the mapped value");
9423 mappedPrivateVars.insert(
9425 targetRegion.getArgument(argIface.getMapBlockArgsStart() +
9426 (*privateMapIndices)[privVarIdx])});
9430 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
9431 auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
9433 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
9434 llvm::IRBuilderBase::InsertPointGuard guard(builder);
9435 builder.SetCurrentDebugLocation(llvm::DebugLoc());
9438 llvm::Function *llvmParentFn =
9440 llvmOutlinedFn = codeGenIP.getBlock()->getParent();
9441 assert(llvmParentFn && llvmOutlinedFn &&
9442 "Both parent and outlined functions must exist at this point");
9444 if (outlinedFnLoc && llvmParentFn->getSubprogram())
9445 llvmOutlinedFn->setSubprogram(outlinedFnLoc->getScope()->getSubprogram());
9447 if (
auto attr = llvmParentFn->getFnAttribute(
"target-cpu");
9448 attr.isStringAttribute())
9449 llvmOutlinedFn->addFnAttr(attr);
9451 if (
auto attr = llvmParentFn->getFnAttribute(
"target-features");
9452 attr.isStringAttribute())
9453 llvmOutlinedFn->addFnAttr(attr);
9455 for (
auto [idx, arg] : llvm::enumerate(mapBlockArgs)) {
9461 if (llvm::is_contained(inRedMapArgIdx, idx))
9463 auto mapInfoOp = cast<omp::MapInfoOp>(mapVars[idx].getDefiningOp());
9464 llvm::Value *mapOpValue =
9465 moduleTranslation.
lookupValue(mapInfoOp.getVarPtr());
9466 moduleTranslation.
mapValue(arg, mapOpValue);
9468 for (
auto [arg, mapOp] : llvm::zip_equal(hdaBlockArgs, hdaVars)) {
9469 auto mapInfoOp = cast<omp::MapInfoOp>(mapOp.getDefiningOp());
9470 llvm::Value *mapOpValue =
9471 moduleTranslation.
lookupValue(mapInfoOp.getVarPtr());
9472 moduleTranslation.
mapValue(arg, mapOpValue);
9481 privateVarsInfo, allocaIP, &mappedPrivateVars);
9484 return llvm::make_error<PreviouslyReportedError>();
9486 builder.restoreIP(codeGenIP);
9488 &mappedPrivateVars),
9491 return llvm::make_error<PreviouslyReportedError>();
9494 targetOp, builder, moduleTranslation, privateVarsInfo.
mlirVars,
9496 targetOp.getPrivateNeedsBarrier(), &mappedPrivateVars)))
9497 return llvm::make_error<PreviouslyReportedError>();
9508 if (!inRedOrigPtrs.empty()) {
9514 inRedResultPtrTys.reserve(inRedMapArgIdx.size());
9515 for (
unsigned mapArgIdx : inRedMapArgIdx)
9516 inRedResultPtrTys.push_back(
9517 moduleTranslation.
convertType(mapBlockArgs[mapArgIdx].getType()));
9519 llvm::OpenMPIRBuilder::LocationDescription bodyLoc(builder);
9520 llvm::OpenMPIRBuilder::InsertPointTy redIP =
9521 ompBuilder->createTargetInReduction(
9522 bodyLoc, inRedOrigPtrs, inRedResultPtrTys,
9523 [&](
unsigned idx, llvm::Value *priv) {
9524 moduleTranslation.
mapValue(mapBlockArgs[inRedMapArgIdx[idx]],
9527 builder.restoreIP(redIP);
9531 moduleTranslation, allocaIP, deallocBlocks);
9533 targetRegion,
"omp.target", builder, moduleTranslation);
9536 return llvm::make_error<PreviouslyReportedError>();
9538 builder.SetInsertPoint(exitBlock.get()->getTerminator());
9541 targetOp.getLoc(), privateVarsInfo)))
9542 return llvm::make_error<PreviouslyReportedError>();
9544 return builder.saveIP();
9547 StringRef parentName = parentFn.getName();
9549 llvm::TargetRegionEntryInfo entryInfo;
9555 MapInfoData mapData;
9560 MapInfosTy combinedInfos;
9562 [&](llvm::OpenMPIRBuilder::InsertPointTy codeGenIP) -> MapInfosTy & {
9563 builder.restoreIP(codeGenIP);
9564 genMapInfos(builder, moduleTranslation, dl, combinedInfos, mapData,
9569 auto *nullPtr = llvm::Constant::getNullValue(builder.getPtrTy());
9570 combinedInfos.BasePointers.push_back(nullPtr);
9571 combinedInfos.Pointers.push_back(nullPtr);
9572 combinedInfos.DevicePointers.push_back(
9573 llvm::OpenMPIRBuilder::DeviceInfoTy::None);
9574 combinedInfos.Sizes.push_back(builder.getInt64(0));
9575 combinedInfos.Types.push_back(
9576 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
9577 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
9579 combinedInfos.HasAttachPtr.push_back(
false);
9580 if (!combinedInfos.Names.empty())
9581 combinedInfos.Names.push_back(nullPtr);
9582 combinedInfos.Mappers.push_back(
nullptr);
9584 return combinedInfos;
9587 auto argAccessorCB = [&](llvm::Argument &arg, llvm::Value *input,
9588 llvm::Value *&retVal, InsertPointTy allocaIP,
9589 InsertPointTy codeGenIP,
9591 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
9592 llvm::IRBuilderBase::InsertPointGuard guard(builder);
9593 builder.SetCurrentDebugLocation(llvm::DebugLoc());
9599 if (!isTargetDevice) {
9600 retVal = cast<llvm::Value>(&arg);
9605 builder, *ompBuilder, moduleTranslation,
9606 allocaIP, codeGenIP, deallocIPs);
9609 llvm::OpenMPIRBuilder::TargetKernelRuntimeAttrs runtimeAttrs;
9610 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs defaultAttrs;
9612 cast<omp::ComposableOpInterface>(*targetOp).findCapturedOp();
9614 isTargetDevice, isGPU);
9618 if (!isTargetDevice)
9620 targetCapturedOp, runtimeAttrs);
9628 for (
auto [arg, var] : llvm::zip_equal(hostEvalBlockArgs, hostEvalVars)) {
9629 llvm::Value *value = moduleTranslation.
lookupValue(var);
9630 moduleTranslation.
mapValue(arg, value);
9632 if (!llvm::isa<llvm::Constant>(value))
9633 kernelInput.push_back(value);
9636 for (
size_t i = 0, e = mapData.OriginalValue.size(); i != e; ++i) {
9645 bool isAttachMap = (mapData.Types[i] &
9646 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH) ==
9647 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH;
9648 if (!mapData.IsDeclareTarget[i] && !mapData.IsAMember[i] && !isAttachMap)
9649 kernelInput.push_back(mapData.OriginalValue[i]);
9653 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
9656 llvm::OpenMPIRBuilder::DependenciesInfo dds;
9658 targetOp.getDependVars(), targetOp.getDependKinds(),
9659 targetOp.getDependIterated(), targetOp.getDependIteratedKinds(),
9660 builder, moduleTranslation, dds)))
9663 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
9665 llvm::OpenMPIRBuilder::TargetDataInfo info(
9669 auto customMapperCB =
9671 if (!combinedInfos.Mappers[i])
9673 info.HasMapper =
true;
9675 moduleTranslation, targetDirective);
9678 llvm::Value *ifCond =
nullptr;
9679 if (
Value targetIfCond = targetOp.getIfExpr())
9680 ifCond = moduleTranslation.
lookupValue(targetIfCond);
9682 Value dynGroupPrivateSize = targetOp.getDynGroupprivateSize();
9683 llvm::Value *dynSizeVal =
nullptr;
9684 if (dynGroupPrivateSize) {
9685 dynSizeVal = moduleTranslation.
lookupValue(dynGroupPrivateSize);
9686 dynSizeVal = builder.CreateIntCast(dynSizeVal, builder.getInt32Ty(),
9690 llvm::omp::OMPDynGroupprivateFallbackType fallbackType =
9693 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
9695 ompLoc, isOffloadEntry, allocaIP, builder.saveIP(), deallocBlocks,
9696 info, entryInfo, defaultAttrs, runtimeAttrs, ifCond, kernelInput,
9697 genMapInfoCB, bodyCB, argAccessorCB, customMapperCB, dds,
9698 targetOp.getNowait(), dynSizeVal, fallbackType);
9703 builder.restoreIP(*afterIP);
9706 builder.CreateFree(dds.DepArray);
9713 llvm::OpenMPIRBuilder *ompBuilder,
9722 if (FunctionOpInterface funcOp = dyn_cast<FunctionOpInterface>(op)) {
9723 if (
auto offloadMod = dyn_cast<omp::OffloadModuleInterface>(
9725 if (!offloadMod.getIsTargetDevice())
9728 omp::DeclareTargetDeviceType declareType =
9729 attribute.getDeviceType().getValue();
9731 if (declareType == omp::DeclareTargetDeviceType::host) {
9732 llvm::Function *llvmFunc =
9734 llvmFunc->dropAllReferences();
9735 llvmFunc->eraseFromParent();
9739 ompBuilder->Builder.ClearInsertionPoint();
9740 ompBuilder->Builder.SetCurrentDebugLocation(llvm::DebugLoc());
9741 }
else if (llvm::Function *llvmFunc =
9753 if (!llvmFunc->isDeclaration() && llvmFunc->hasExternalLinkage() &&
9754 llvmFunc->getVisibility() == llvm::GlobalValue::DefaultVisibility)
9755 llvmFunc->setVisibility(llvm::GlobalValue::HiddenVisibility);
9761 if (LLVM::GlobalOp gOp = dyn_cast<LLVM::GlobalOp>(op)) {
9762 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
9763 if (
auto *gVal = llvmModule->getNamedValue(gOp.getSymName())) {
9764 auto *gVar = cast<llvm::GlobalVariable>(gVal);
9766 bool isDeclaration = gOp.isDeclaration();
9767 bool isExternallyVisible =
9770 llvm::StringRef mangledName = gOp.getSymName();
9771 mlir::omp::DeclareTargetCaptureClause captureClause =
9772 attribute.getCaptureClause().getValue();
9776 llvm::StringRef entryMangledName = mangledName;
9777 llvm::Constant *entryAddr = llvm::cast<llvm::Constant>(gVal);
9778 std::function<llvm::GlobalValue::LinkageTypes()> variableLinkage;
9780 bool requiresUSM = ompBuilder->Config.hasRequiresUnifiedSharedMemory();
9782 captureClause == omp::DeclareTargetCaptureClause::to ||
9783 captureClause == omp::DeclareTargetCaptureClause::enter;
9784 bool isHostOnly = attribute.getDeviceType().getValue() ==
9785 omp::DeclareTargetDeviceType::host;
9790 if (isToOrEnter && !isHostOnly && !requiresUSM &&
9791 gVar->hasLocalLinkage()) {
9792 gVar->setLinkage(llvm::GlobalValue::ExternalLinkage);
9793 isExternallyVisible =
true;
9797 if (ompBuilder->Config.isTargetDevice())
9798 gVar->setDSOLocal(
false);
9803 llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny &&
9804 !requiresUSM && !isDeclaration &&
9805 (gVal->hasLocalLinkage() || gVal->hasHiddenVisibility())) {
9809 entryNameStorage = (mangledName + llvm::Twine(
"_decl_tgt_entry")).str();
9810 entryMangledName = entryNameStorage;
9811 if (llvm::GlobalValue *existing =
9812 llvmModule->getNamedValue(entryMangledName)) {
9813 entryAddr = llvm::cast<llvm::Constant>(existing);
9815 entryAddr = llvm::GlobalAlias::create(
9816 gVal->getValueType(), gVal->getAddressSpace(),
9817 llvm::GlobalValue::WeakAnyLinkage, entryMangledName, entryAddr,
9819 llvm::cast<llvm::GlobalAlias>(entryAddr)->setVisibility(
9820 llvm::GlobalValue::DefaultVisibility);
9822 variableLinkage = [] {
return llvm::GlobalValue::WeakAnyLinkage; };
9826 std::vector<llvm::GlobalVariable *> generatedRefs;
9828 std::vector<llvm::Triple> targetTriple;
9829 auto targetTripleAttr = dyn_cast_or_null<mlir::StringAttr>(
9831 LLVM::LLVMDialect::getTargetTripleAttrName()));
9832 if (targetTripleAttr)
9833 targetTriple.emplace_back(targetTripleAttr.data());
9835 auto fileInfoCallBack = [&loc]() {
9836 std::string filename =
"";
9837 std::uint64_t lineNo = 0;
9840 filename = loc.getFilename().str();
9841 lineNo = loc.getLine();
9844 return std::pair<std::string, std::uint64_t>(llvm::StringRef(filename),
9848 llvm::vfs::FileSystem &vfs = moduleTranslation.
getFileSystem();
9849 ompBuilder->registerTargetGlobalVariable(
9850 captureClauseKind, deviceClause, isDeclaration, isExternallyVisible,
9851 ompBuilder->getTargetEntryUniqueInfo(fileInfoCallBack, vfs),
9852 entryMangledName, generatedRefs,
false, targetTriple,
9853 nullptr, variableLinkage, gVal->getType(),
9856 if (ompBuilder->Config.isTargetDevice() &&
9857 (captureClause == omp::DeclareTargetCaptureClause::link ||
9862 llvm::Type *ptrTy = llvm::PointerType::get(llvmModule->getContext(), 0);
9863 llvm::Constant *refPtr = ompBuilder->getAddrOfDeclareTargetVar(
9864 captureClauseKind, deviceClause, isDeclaration, isExternallyVisible,
9865 ompBuilder->getTargetEntryUniqueInfo(fileInfoCallBack, vfs),
9866 mangledName, generatedRefs,
false, targetTriple,
9875 gVar->setLinkage(llvm::GlobalValue::InternalLinkage);
9881 dyn_cast<llvm::GlobalValue>(refPtr->stripPointerCasts()))
9882 ompBuilder->registerDeclareTargetGlobalReplacement(gVal, newGV);
9889 if (ompBuilder->Config.isTargetDevice() && isHostOnly && isToOrEnter) {
9890 gVar->setLinkage(llvm::GlobalValue::ExternalLinkage);
9891 gVar->setInitializer(
nullptr);
9903class OpenMPDialectLLVMIRTranslationInterface
9904 :
public LLVMTranslationDialectInterface {
9906 using LLVMTranslationDialectInterface::LLVMTranslationDialectInterface;
9911 convertOperation(Operation *op, llvm::IRBuilderBase &builder,
9912 LLVM::ModuleTranslation &moduleTranslation)
const final;
9917 amendOperation(Operation *op, ArrayRef<llvm::Instruction *> instructions,
9918 NamedAttribute attribute,
9919 LLVM::ModuleTranslation &moduleTranslation)
const final;
9924 void registerAllocatedPtr(Value var, llvm::Value *ptr)
const {
9925 ompAllocatedPtrs[var] = ptr;
9930 llvm::Value *lookupAllocatedPtr(Value var)
const {
9931 auto it = ompAllocatedPtrs.find(var);
9932 return it != ompAllocatedPtrs.end() ? it->second :
nullptr;
9944LogicalResult OpenMPDialectLLVMIRTranslationInterface::amendOperation(
9945 Operation *op, ArrayRef<llvm::Instruction *> instructions,
9946 NamedAttribute attribute,
9947 LLVM::ModuleTranslation &moduleTranslation)
const {
9948 return llvm::StringSwitch<llvm::function_ref<LogicalResult(Attribute)>>(
9950 .Case(
"omp.is_target_device",
9951 [&](Attribute attr) {
9952 if (
auto deviceAttr = dyn_cast<BoolAttr>(attr)) {
9953 llvm::OpenMPIRBuilderConfig &config =
9955 config.setIsTargetDevice(deviceAttr.getValue());
9961 [&](Attribute attr) {
9962 if (
auto gpuAttr = dyn_cast<BoolAttr>(attr)) {
9963 llvm::OpenMPIRBuilderConfig &config =
9965 config.setIsGPU(gpuAttr.getValue());
9970 .Case(
"omp.host_ir_filepath",
9971 [&](Attribute attr) {
9972 if (
auto filepathAttr = dyn_cast<StringAttr>(attr)) {
9973 llvm::OpenMPIRBuilder *ompBuilder =
9975 ompBuilder->loadOffloadInfoMetadata(
9976 moduleTranslation.
getFileSystem(), filepathAttr.getValue());
9982 [&](Attribute attr) {
9983 if (
auto rtlAttr = dyn_cast<omp::FlagsAttr>(attr))
9987 .Case(
"omp.version",
9988 [&](Attribute attr) {
9989 if (
auto versionAttr = dyn_cast<omp::VersionAttr>(attr)) {
9990 llvm::OpenMPIRBuilder *ompBuilder =
9992 ompBuilder->M.addModuleFlag(llvm::Module::Max,
"openmp",
9993 versionAttr.getVersion());
9998 .Case(
"omp.declare_target",
9999 [&](Attribute attr) {
10000 if (
auto declareTargetAttr =
10001 dyn_cast<omp::DeclareTargetAttr>(attr)) {
10002 llvm::OpenMPIRBuilder *ompBuilder =
10005 ompBuilder, moduleTranslation);
10009 .Case(
"omp.requires",
10010 [&](Attribute attr) {
10011 if (
auto requiresAttr = dyn_cast<omp::ClauseRequiresAttr>(attr)) {
10012 using Requires = omp::ClauseRequires;
10013 Requires flags = requiresAttr.getValue();
10014 llvm::OpenMPIRBuilderConfig &config =
10016 config.setHasRequiresReverseOffload(
10017 bitEnumContainsAll(flags, Requires::reverse_offload));
10018 config.setHasRequiresUnifiedAddress(
10019 bitEnumContainsAll(flags, Requires::unified_address));
10020 config.setHasRequiresUnifiedSharedMemory(
10021 bitEnumContainsAll(flags, Requires::unified_shared_memory));
10022 config.setHasRequiresDynamicAllocators(
10023 bitEnumContainsAll(flags, Requires::dynamic_allocators));
10028 .Case(
"omp.target_triples",
10029 [&](Attribute attr) {
10030 if (
auto triplesAttr = dyn_cast<ArrayAttr>(attr)) {
10031 llvm::OpenMPIRBuilderConfig &config =
10033 config.TargetTriples.clear();
10034 config.TargetTriples.reserve(triplesAttr.size());
10035 for (Attribute tripleAttr : triplesAttr) {
10036 if (
auto tripleStrAttr = dyn_cast<StringAttr>(tripleAttr))
10037 config.TargetTriples.emplace_back(tripleStrAttr.getValue());
10045 .Case(
"omp.integer_wrap_around",
10046 [&](Attribute attr) {
10047 if (
auto wrapAttr = dyn_cast<omp::IntegerWrapAroundAttr>(attr)) {
10048 llvm::OpenMPIRBuilderConfig &config =
10050 config.setNoSignedWrap(!wrapAttr.getIntegerWrapAround());
10055 .Default([](Attribute) {
10071 if (
auto declareTargetIface =
10072 llvm::dyn_cast<mlir::omp::DeclareTargetInterface>(
10073 parentFn.getOperation()))
10074 if (declareTargetIface.isDeclareTarget() &&
10075 declareTargetIface.getDeclareTargetDeviceType() !=
10076 mlir::omp::DeclareTargetDeviceType::host)
10086 llvm::Module *llvmModule) {
10087 llvm::Type *i64Ty = builder.getInt64Ty();
10088 llvm::Type *i32Ty = builder.getInt32Ty();
10089 llvm::Type *returnType = builder.getPtrTy(0);
10090 llvm::FunctionType *fnType =
10091 llvm::FunctionType::get(returnType, {i64Ty, i32Ty},
false);
10092 llvm::Function *
func = cast<llvm::Function>(
10093 llvmModule->getOrInsertFunction(
"omp_target_alloc", fnType).getCallee());
10097template <
typename T>
10098static llvm::Value *
10101 llvm::DataLayout dataLayout =
10103 llvm::Type *llvmHeapTy =
10104 moduleTranslation.
convertType(op.getMemElemTypeAttr().getValue());
10106 auto alignment = op.getMemAlignment();
10107 llvm::TypeSize typeSize = llvm::alignTo(
10108 dataLayout.getTypeStoreSize(llvmHeapTy),
10109 alignment ? *alignment : dataLayout.getABITypeAlign(llvmHeapTy).value());
10111 llvm::Value *allocSize = builder.getInt64(typeSize.getFixedValue());
10112 return builder.CreateMul(
10114 builder.CreateIntCast(moduleTranslation.
lookupValue(op.getMemArraySize()),
10115 builder.getInt64Ty(),
10122 omp::TargetAllocMemOp op) {
10123 llvm::DataLayout dataLayout =
10125 llvm::Type *llvmHeapTy = moduleTranslation.
convertType(op.getAllocatedType());
10126 llvm::TypeSize typeSize = dataLayout.getTypeAllocSize(llvmHeapTy);
10127 llvm::Value *allocSize = builder.getInt64(typeSize.getFixedValue());
10128 for (
auto typeParam : op.getTypeparams()) {
10129 allocSize = builder.CreateMul(
10131 builder.CreateIntCast(moduleTranslation.
lookupValue(typeParam),
10132 builder.getInt64Ty(),
10138static LogicalResult
10141 auto allocMemOp = cast<omp::TargetAllocMemOp>(opInst);
10146 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
10150 llvm::Value *llvmDeviceNum = moduleTranslation.
lookupValue(deviceNum);
10152 llvm::Value *allocSize =
10155 llvm::CallInst *call =
10156 builder.CreateCall(ompTargetAllocFunc, {allocSize, llvmDeviceNum});
10157 llvm::Value *resultI64 = builder.CreatePtrToInt(call, builder.getInt64Ty());
10160 moduleTranslation.
mapValue(allocMemOp.getResult(), resultI64);
10164static LogicalResult
10166 llvm::IRBuilderBase &builder,
10170 moduleTranslation.
mapValue(allocMemOp.getResult(),
10171 ompBuilder->createOMPAllocShared(builder, size));
10175static LogicalResult
10178 const OpenMPDialectLLVMIRTranslationInterface &ompIface) {
10179 auto allocateDirOp = cast<omp::AllocateDirOp>(opInst);
10182 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
10183 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
10184 llvm::DataLayout dataLayout = llvmModule->getDataLayout();
10186 std::optional<int64_t> alignAttr = allocateDirOp.getAlign();
10188 llvm::Value *allocator;
10189 if (
auto allocatorVar = allocateDirOp.getAllocator()) {
10190 allocator = moduleTranslation.
lookupValue(allocatorVar);
10191 if (allocator->getType()->isIntegerTy())
10192 allocator = builder.CreateIntToPtr(allocator, builder.getPtrTy());
10193 else if (allocator->getType()->isPointerTy())
10194 allocator = builder.CreatePointerBitCastOrAddrSpaceCast(
10195 allocator, builder.getPtrTy());
10197 allocator = llvm::ConstantPointerNull::get(builder.getPtrTy());
10200 for (
Value var : vars) {
10201 llvm::Type *llvmVarTy = moduleTranslation.
convertType(var.getType());
10205 llvm::Type *typeToInspect = llvmVarTy;
10206 if (llvmVarTy->isPointerTy()) {
10209 if (
auto gop = dyn_cast<LLVM::GlobalOp>(globalOp))
10210 typeToInspect = moduleTranslation.
convertType(gop.getGlobalType());
10215 if (
auto arrTy = llvm::dyn_cast<llvm::ArrayType>(typeToInspect)) {
10216 llvm::Value *elementCount = builder.getInt64(1);
10217 llvm::Type *currentType = arrTy;
10218 while (
auto nestedArrTy = llvm::dyn_cast<llvm::ArrayType>(currentType)) {
10219 elementCount = builder.CreateMul(
10220 elementCount, builder.getInt64(nestedArrTy->getNumElements()));
10221 currentType = nestedArrTy->getElementType();
10223 uint64_t elemSizeInBits = dataLayout.getTypeSizeInBits(currentType);
10225 builder.CreateMul(elementCount, builder.getInt64(elemSizeInBits / 8));
10227 size = builder.getInt64(
10228 dataLayout.getTypeStoreSize(typeToInspect).getFixedValue());
10231 uint64_t alignValue =
10232 alignAttr ? alignAttr.value()
10233 : dataLayout.getABITypeAlign(typeToInspect).value();
10234 llvm::Value *alignConst = builder.getInt64(alignValue);
10236 size = builder.CreateAdd(size, builder.getInt64(alignValue - 1),
"",
true);
10237 size = builder.CreateUDiv(size, alignConst);
10238 size = builder.CreateMul(size, alignConst,
"",
true);
10240 std::string allocName =
10241 ompBuilder->createPlatformSpecificName({
".void.addr"});
10242 llvm::CallInst *allocCall;
10243 if (alignAttr.has_value()) {
10244 allocCall = ompBuilder->createOMPAlignedAlloc(
10245 ompLoc, builder.getInt64(alignAttr.value()), size, allocator,
10249 ompBuilder->createOMPAlloc(ompLoc, size, allocator, allocName);
10252 ompIface.registerAllocatedPtr(var, allocCall);
10258static LogicalResult
10261 const OpenMPDialectLLVMIRTranslationInterface &ompIface) {
10262 auto freeOp = cast<omp::AllocateFreeOp>(opInst);
10264 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
10266 llvm::Value *allocator;
10267 if (
auto allocatorVar = freeOp.getAllocator()) {
10268 allocator = moduleTranslation.
lookupValue(allocatorVar);
10269 if (allocator->getType()->isIntegerTy())
10270 allocator = builder.CreateIntToPtr(allocator, builder.getPtrTy());
10271 else if (allocator->getType()->isPointerTy())
10272 allocator = builder.CreatePointerBitCastOrAddrSpaceCast(
10273 allocator, builder.getPtrTy());
10275 allocator = llvm::ConstantPointerNull::get(builder.getPtrTy());
10280 for (
Value var : llvm::reverse(vars)) {
10281 llvm::Value *allocPtr = ompIface.lookupAllocatedPtr(var);
10283 return opInst.
emitError(
"omp.allocate_free: no allocation recorded");
10284 ompBuilder->createOMPFree(ompLoc, allocPtr, allocator,
"");
10291 llvm::Module *llvmModule) {
10292 llvm::Type *ptrTy = builder.getPtrTy(0);
10293 llvm::Type *i32Ty = builder.getInt32Ty();
10294 llvm::Type *voidTy = builder.getVoidTy();
10295 llvm::FunctionType *fnType =
10296 llvm::FunctionType::get(voidTy, {ptrTy, i32Ty},
false);
10297 llvm::Function *
func = dyn_cast<llvm::Function>(
10298 llvmModule->getOrInsertFunction(
"omp_target_free", fnType).getCallee());
10302static LogicalResult
10305 auto freeMemOp = cast<omp::TargetFreeMemOp>(opInst);
10310 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
10311 llvm::Function *ompTragetFreeFunc =
getOmpTargetFree(builder, llvmModule);
10314 llvm::Value *llvmDeviceNum = moduleTranslation.
lookupValue(deviceNum);
10317 llvm::Value *llvmHeapref = moduleTranslation.
lookupValue(heapref);
10319 llvm::Value *intToPtr =
10320 builder.CreateIntToPtr(llvmHeapref, builder.getPtrTy(0));
10321 builder.CreateCall(ompTragetFreeFunc, {intToPtr, llvmDeviceNum});
10325static LogicalResult
10327 llvm::IRBuilderBase &builder,
10331 ompBuilder->createOMPFreeShared(
10332 builder, moduleTranslation.
lookupValue(freeMemOp.getHeapref()), size);
10337static LogicalResult
10341 auto groupprivateOp = cast<omp::GroupprivateOp>(opInst);
10346 bool isTargetDevice = ompBuilder->Config.isTargetDevice();
10350 bool shouldAllocate =
true;
10351 switch (groupprivateOp.getDeviceType().value_or(
10352 mlir::omp::DeclareTargetDeviceType::any)) {
10353 case mlir::omp::DeclareTargetDeviceType::host:
10354 shouldAllocate = !isTargetDevice;
10356 case mlir::omp::DeclareTargetDeviceType::nohost:
10357 shouldAllocate = isTargetDevice;
10359 case mlir::omp::DeclareTargetDeviceType::any:
10360 shouldAllocate =
true;
10366 &opInst, groupprivateOp.getSymNameAttr());
10369 <<
"expected symbol '" << groupprivateOp.getSymName()
10370 <<
"' to reference an LLVM global variable";
10372 llvm::GlobalValue *globalValue = moduleTranslation.
lookupGlobal(global);
10373 llvm::Type *varType = moduleTranslation.
convertType(global.getType());
10374 std::string varName = globalValue->getName().str();
10376 llvm::Value *resultPtr;
10377 if (shouldAllocate && isTargetDevice) {
10378 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
10379 llvm::Triple targetTriple(llvmModule->getTargetTriple());
10380 unsigned sharedAddressSpace;
10381 if (targetTriple.isAMDGCN())
10382 sharedAddressSpace = llvm::AMDGPUAS::LOCAL_ADDRESS;
10383 else if (targetTriple.isNVPTX())
10384 sharedAddressSpace = llvm::NVPTXAS::ADDRESS_SPACE_SHARED;
10386 return opInst.
emitError() <<
"groupprivate is not supported for target: "
10387 << targetTriple.str();
10388 llvm::GlobalVariable *sharedVar =
new llvm::GlobalVariable(
10389 *llvmModule, varType,
false,
10390 llvm::GlobalValue::InternalLinkage, llvm::PoisonValue::get(varType),
10391 varName,
nullptr, llvm::GlobalValue::NotThreadLocal,
10392 sharedAddressSpace,
10394 resultPtr = sharedVar;
10396 if (shouldAllocate && !isTargetDevice)
10397 opInst.
emitWarning(
"groupprivate directive is currently ignored on the "
10398 "host, using original global");
10399 resultPtr = globalValue;
10408LogicalResult OpenMPDialectLLVMIRTranslationInterface::convertOperation(
10409 Operation *op, llvm::IRBuilderBase &builder,
10410 LLVM::ModuleTranslation &moduleTranslation)
const {
10413 if (ompBuilder->Config.isTargetDevice() &&
10414 !isa<omp::TargetOp, omp::MapInfoOp, omp::TerminatorOp, omp::YieldOp>(
10417 return op->
emitOpError() <<
"unsupported host op found in device";
10425 bool isOutermostLoopWrapper =
10426 isa_and_present<omp::LoopWrapperInterface>(op) &&
10427 !dyn_cast_if_present<omp::LoopWrapperInterface>(op->
getParentOp());
10436 if (isa<omp::TaskloopContextOp>(op))
10437 isOutermostLoopWrapper =
true;
10438 else if (isa<omp::TaskloopWrapperOp>(op))
10439 isOutermostLoopWrapper =
false;
10441 if (isOutermostLoopWrapper)
10442 moduleTranslation.
stackPush<OpenMPLoopInfoStackFrame>();
10445 llvm::TypeSwitch<Operation *, LogicalResult>(op)
10446 .Case([&](omp::BarrierOp op) -> LogicalResult {
10450 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
10451 ompBuilder->createBarrier(builder, llvm::omp::OMPD_barrier);
10453 if (res.succeeded()) {
10456 builder.restoreIP(*afterIP);
10460 .Case([&](omp::TaskyieldOp op) {
10464 ompBuilder->createTaskyield(builder);
10467 .Case([&](omp::FlushOp op) {
10479 ompBuilder->createFlush(builder);
10482 .Case([&](omp::ErrorOp op) {
10486 llvm::Value *message =
nullptr;
10487 if (mlir::Value messageExpr = op.getMessageExpr())
10488 message = moduleTranslation.
lookupValue(messageExpr);
10489 else if (std::optional<StringRef> msg = op.getMessage();
10490 msg && !msg->empty())
10491 message = builder.CreateGlobalString(*msg);
10492 ompBuilder->createError(
10493 llvm::OpenMPIRBuilder::LocationDescription(builder),
10494 op.getSeverity() == omp::ClauseSeverity::fatal, message);
10497 .Case([&](omp::ParallelOp op) {
10500 .Case([&](omp::MaskedOp) {
10503 .Case([&](omp::MasterOp) {
10506 .Case([&](omp::CriticalOp) {
10509 .Case([&](omp::OrderedRegionOp) {
10512 .Case([&](omp::OrderedOp) {
10515 .Case([&](omp::WsloopOp) {
10518 .Case([&](omp::SimdOp) {
10521 .Case([&](omp::AtomicReadOp) {
10524 .Case([&](omp::AtomicWriteOp) {
10527 .Case([&](omp::AtomicUpdateOp op) {
10530 .Case([&](omp::AtomicCaptureOp op) {
10533 .Case([&](omp::AtomicCompareOp op) {
10536 .Case([&](omp::CancelOp op) {
10539 .Case([&](omp::CancellationPointOp op) {
10542 .Case([&](omp::SectionsOp) {
10545 .Case([&](omp::ScopeOp op) {
10548 .Case([&](omp::SingleOp op) {
10551 .Case([&](omp::TeamsOp op) {
10554 .Case([&](omp::TaskOp op) {
10557 .Case([&](omp::TaskloopWrapperOp op) {
10560 .Case([&](omp::TaskloopContextOp op) {
10563 .Case([&](omp::TaskgroupOp op) {
10566 .Case([&](omp::TaskwaitOp op) {
10569 .Case([&](omp::InteropInitOp op) {
10572 .Case([&](omp::InteropDestroyOp op) {
10575 .Case([&](omp::InteropUseOp op) {
10578 .Case<omp::YieldOp, omp::TerminatorOp, omp::DeclareMapperOp,
10579 omp::DeclareMapperInfoOp, omp::DeclareReductionOp,
10580 omp::CriticalDeclareOp>([](
auto op) {
10593 .Case([&](omp::ThreadprivateOp) {
10596 .Case<omp::TargetDataOp, omp::TargetEnterDataOp,
10597 omp::TargetExitDataOp, omp::TargetUpdateOp>([&](
auto op) {
10600 .Case([&](omp::TargetOp) {
10603 .Case([&](omp::DistributeOp) {
10606 .Case([&](omp::LoopNestOp) {
10609 .Case<omp::MapInfoOp, omp::MapBoundsOp, omp::PrivateClauseOp,
10610 omp::AffinityEntryOp, omp::IteratorOp>([&](
auto op) {
10616 .Case([&](omp::NewCliOp op) {
10621 .Case([&](omp::CanonicalLoopOp op) {
10624 .Case([&](omp::UnrollHeuristicOp op) {
10633 .Case([&](omp::UnrollFullOp op) {
10636 .Case([&](omp::UnrollPartialOp op) {
10639 .Case([&](omp::TileOp op) {
10640 return applyTile(op, builder, moduleTranslation);
10642 .Case([&](omp::FuseOp op) {
10643 return applyFuse(op, builder, moduleTranslation);
10645 .Case([&](omp::TargetAllocMemOp) {
10648 .Case([&](omp::TargetFreeMemOp) {
10651 .Case([&](omp::AllocateDirOp) {
10654 .Case([&](omp::AllocateFreeOp) {
10658 .Case([&](omp::AllocSharedMemOp op) {
10661 .Case([&](omp::FreeSharedMemOp op) {
10664 .Case([&](omp::GroupprivateOp) {
10667 .Default([&](Operation *inst) {
10669 <<
"not yet implemented: " << inst->
getName();
10672 if (isOutermostLoopWrapper)
10679 registry.
insert<omp::OpenMPDialect>();
10681 dialect->addInterfaces<OpenMPDialectLLVMIRTranslationInterface>();
static mlir::LogicalResult buildDependData(OperandRange dependVars, std::optional< ArrayAttr > dependKinds, OperandRange dependIterated, std::optional< ArrayAttr > dependIteratedKinds, llvm::IRBuilderBase &builder, mlir::LLVM::ModuleTranslation &moduleTranslation, llvm::OpenMPIRBuilder::DependenciesInfo &taskDeps)
static 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 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 LogicalResult applyTile(omp::TileOp op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Apply a #pragma omp tile / !$omp tile transformation using the OpenMPIRBuilder.
static LogicalResult convertAllocateFreeOp(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, const OpenMPDialectLLVMIRTranslationInterface &ompIface)
static llvm::Function * getOmpTargetFree(llvm::IRBuilderBase &builder, llvm::Module *llvmModule)
static LogicalResult convertOmpTaskgroupOp(omp::TaskgroupOp tgOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP taskgroup construct into LLVM IR using OpenMPIRBuilder.
static void collectMapDataFromMapOperands(MapInfoData &mapData, SmallVectorImpl< Value > &mapVars, LLVM::ModuleTranslation &moduleTranslation, DataLayout &dl, llvm::IRBuilderBase &builder, ArrayRef< Value > useDevPtrOperands={}, ArrayRef< Value > useDevAddrOperands={}, ArrayRef< Value > hasDevAddrOperands={})
static void extractAtomicControlFlags(omp::AtomicUpdateOp atomicUpdateOp, bool &isIgnoreDenormalMode, bool &isFineGrainedMemory, bool &isRemoteMemory)
static Operation * genLoop(CodegenEnv &env, OpBuilder &builder, LoopId curr, unsigned numCases, bool needsUniv, ArrayRef< TensorLevel > tidLvls)
Generates a for-loop or a while-loop, depending on whether it implements singleton iteration or co-it...
#define MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(CLASS_NAME)
Attributes are known-constant values of operations.
This class represents an argument of a Block.
Block represents an ordered list of Operations.
BlockArgument getArgument(unsigned i)
unsigned getNumArguments()
OpListType & getOperations()
Operation * getTerminator()
Get the terminator operation of this block.
iterator_range< iterator > without_terminator()
Return an iterator range over the operation within this block excluding the terminator operation at t...
The main mechanism for performing data layout queries.
llvm::TypeSize getTypeSize(Type t) const
Returns the size of the given type in the current scope.
llvm::TypeSize getTypeSizeInBits(Type t) const
Returns the size in bits of the given type in the current scope.
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
bool addExtension(TypeID extensionID, std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
An instance of this location represents a tuple of file, line number, and column number.
Implementation class for module translation.
llvm::BasicBlock * lookupBlock(Block *block) const
Finds an LLVM IR basic block that corresponds to the given MLIR block.
WalkResult stackWalk(llvm::function_ref< WalkResult(T &)> callback)
Calls callback for every ModuleTranslation stack frame of type T starting from the top of the stack.
void stackPush(Args &&...args)
Creates a stack frame of type T on ModuleTranslation stack.
LogicalResult convertBlock(Block &bb, bool ignoreArguments, llvm::IRBuilderBase &builder)
Translates the contents of the given block to LLVM IR using this translator.
SmallVector< llvm::Value * > lookupValues(ValueRange values)
Looks up remapped a list of remapped values.
void mapFunction(StringRef name, llvm::Function *func)
Stores the mapping between a function name and its LLVM IR representation.
llvm::Value * lookupValue(Value value) const
Finds an LLVM IR value corresponding to the given MLIR value.
void invalidateOmpLoop(omp::NewCliOp mlir)
Mark an OpenMP loop as having been consumed.
SymbolTableCollection & symbolTable()
llvm::Type * convertType(Type type)
Converts the type from MLIR LLVM dialect to LLVM.
llvm::OpenMPIRBuilder * getOpenMPBuilder()
Returns the OpenMP IR builder associated with the LLVM IR module being constructed.
llvm::vfs::FileSystem & getFileSystem()
Returns the virtual filesystem to use for file operations.
void mapOmpLoop(omp::NewCliOp mlir, llvm::CanonicalLoopInfo *llvm)
Map an MLIR OpenMP dialect CanonicalLoopInfo to its lowered LLVM-IR OpenMPIRBuilder CanonicalLoopInfo...
llvm::GlobalValue * lookupGlobal(Operation *op)
Finds an LLVM IR global value that corresponds to the given MLIR operation defining a global value.
SaveStateStack< T, ModuleTranslation > SaveStack
RAII object calling stackPush/stackPop on construction/destruction.
LogicalResult convertOperation(Operation &op, llvm::IRBuilderBase &builder)
Converts the given MLIR operation into LLVM IR using this translator.
llvm::Function * lookupFunction(StringRef name) const
Finds an LLVM IR function by its name.
void mapBlock(Block *mlir, llvm::BasicBlock *llvm)
Stores the mapping between an MLIR block and LLVM IR basic block.
llvm::Module * getLLVMModule()
Returns the LLVM module in which the IR is being constructed.
void stackPop()
Pops the last element from the ModuleTranslation stack.
void forgetMapping(Region ®ion)
Removes the mapping for blocks contained in the region and values defined in these blocks.
void mapValue(Value mlir, llvm::Value *llvm)
Stores the mapping between an MLIR value and its LLVM IR counterpart.
llvm::CanonicalLoopInfo * lookupOMPLoop(omp::NewCliOp mlir) const
Find the LLVM-IR loop that represents an MLIR loop.
llvm::LLVMContext & getLLVMContext() const
Returns the LLVM context in which the IR is being constructed.
Utility class to translate MLIR LLVM dialect types to LLVM IR.
unsigned getPreferredAlignment(Type type, const llvm::DataLayout &layout)
Returns the preferred alignment for the type given the data layout.
T findInstanceOf()
Return an instance of the given location type if one is nested under the current location.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
void appendDialectRegistry(const DialectRegistry ®istry)
Append the contents of the given dialect registry to the registry associated with this context.
StringAttr getName() const
Return the name of the attribute.
Attribute getValue() const
Return the value of the attribute.
This class implements the operand iterators for the Operation class.
StringAttr getIdentifier() const
Return the name of this operation as a StringAttr.
Operation is the basic unit of execution within MLIR.
Region & getRegion(unsigned index)
Returns the region held by this operation at position 'index'.
Value getOperand(unsigned idx)
InFlightDiagnostic emitWarning(const Twine &message={})
Emit a warning about this operation, reporting up to any diagnostic handlers that may be listening.
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
unsigned getNumRegions()
Returns the number of regions held by this operation.
Location getLoc()
The source location the operation was defined or derived from.
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
unsigned getNumOperands()
OperandRange operand_range
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
OperationName getName()
The name of an operation is the key identifier for it.
operand_range getOperands()
Returns an iterator on the underlying Value's.
std::enable_if_t< llvm::function_traits< std::decay_t< FnT > >::num_args==1, RetT > walk(FnT &&callback)
Walk the operation by calling the callback for each nested operation (including this one),...
user_range getUsers()
Returns a range of all users.
result_range getResults()
MLIRContext * getContext()
Return the context this operation is associated with.
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
unsigned getNumResults()
Return the number of results held by this operation.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
BlockArgListType getArguments()
unsigned getNumArguments()
Operation * getParentOp()
Return the parent operation this region is attached to.
BlockListType & getBlocks()
bool hasOneBlock()
Return true if this region has exactly one block.
Concrete CRTP base class for StateStack frames.
@ Private
The symbol is private and may only be referenced by SymbolRefAttrs local to the operations within the...
static Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class 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.