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"
57 omp::PrivateClauseOp privatizer, llvm::Value *var);
60static llvm::omp::ScheduleKind
61convertToScheduleKind(std::optional<omp::ClauseScheduleKind> schedKind) {
62 if (!schedKind.has_value())
63 return llvm::omp::OMP_SCHEDULE_Default;
64 switch (schedKind.value()) {
65 case omp::ClauseScheduleKind::Static:
66 return llvm::omp::OMP_SCHEDULE_Static;
67 case omp::ClauseScheduleKind::Dynamic:
68 return llvm::omp::OMP_SCHEDULE_Dynamic;
69 case omp::ClauseScheduleKind::Guided:
70 return llvm::omp::OMP_SCHEDULE_Guided;
71 case omp::ClauseScheduleKind::Auto:
72 return llvm::omp::OMP_SCHEDULE_Auto;
73 case omp::ClauseScheduleKind::Runtime:
74 return llvm::omp::OMP_SCHEDULE_Runtime;
75 case omp::ClauseScheduleKind::Distribute:
76 return llvm::omp::OMP_SCHEDULE_Distribute;
78 llvm_unreachable(
"unhandled schedule clause argument");
83class OpenMPAllocStackFrame
88 explicit OpenMPAllocStackFrame(
89 llvm::BasicBlock *allocBlock,
90 llvm::ArrayRef<llvm::BasicBlock *> deallocBlocks)
91 : allocBlock(allocBlock), deallocBlocks(deallocBlocks) {}
92 llvm::BasicBlock *allocBlock;
93 llvm::SmallVector<llvm::BasicBlock *> deallocBlocks;
99class OpenMPLoopInfoStackFrame
103 llvm::CanonicalLoopInfo *loopInfo =
nullptr;
122class PreviouslyReportedError
123 :
public llvm::ErrorInfo<PreviouslyReportedError> {
125 void log(raw_ostream &)
const override {
129 std::error_code convertToErrorCode()
const override {
131 "PreviouslyReportedError doesn't support ECError conversion");
138char PreviouslyReportedError::ID = 0;
149class LinearClauseProcessor {
152 SmallVector<llvm::Type *> linearVarTypes;
153 SmallVector<llvm::Value *> linearSteps;
155 SmallVector<omp::PrivateClauseOp> linearPrivatizers;
156 SmallVector<llvm::Value *> linearOrigVars;
157 SmallVector<llvm::Value *> linearPrivateVars;
159 SmallVector<llvm::Value *> linearStartVals;
160 llvm::BasicBlock *linearFinalizationBB;
161 llvm::BasicBlock *linearExitBB;
162 llvm::BasicBlock *linearLastIterExitBB;
163 std::optional<size_t> linearLoopIVIndex;
166 llvm::Expected<llvm::Value *>
167 getAddress(llvm::IRBuilderBase &builder,
168 LLVM::ModuleTranslation &moduleTranslation,
size_t index,
171 linearPrivatizers[index], var);
175 llvm::Error storeLinearVars(llvm::IRBuilderBase &builder,
176 LLVM::ModuleTranslation &moduleTranslation) {
177 for (
size_t index = 0; index < linearOrigVars.size(); index++) {
178 llvm::Expected<llvm::Value *> from = getAddress(
179 builder, moduleTranslation, index, linearPrivateVars[index]);
181 return from.takeError();
182 llvm::LoadInst *linearVarTemp =
183 builder.CreateLoad(linearVarTypes[index], *from);
184 llvm::Expected<llvm::Value *> to =
185 getAddress(builder, moduleTranslation, index, linearOrigVars[index]);
187 return to.takeError();
188 builder.CreateStore(linearVarTemp, *to);
190 return llvm::Error::success();
195 void registerType(LLVM::ModuleTranslation &moduleTranslation,
196 mlir::Attribute &ty) {
197 linearVarTypes.push_back(moduleTranslation.
convertType(
198 mlir::cast<mlir::TypeAttr>(ty).getValue()));
202 void createLinearVar(llvm::IRBuilderBase &builder,
203 const llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
204 omp::PrivateClauseOp privatizer, llvm::Value *origVar,
205 llvm::Value *privateVar,
int idx) {
206 llvm::IRBuilderBase::InsertPointGuard guard(builder);
207 builder.SetInsertPoint(allocaIP.getNodeParent()->getTerminator());
208 linearStartVals.push_back(
209 builder.CreateAlloca(linearVarTypes[idx],
nullptr,
".linear_var"));
210 linearPrivatizers.push_back(privatizer);
211 linearOrigVars.push_back(origVar);
212 linearPrivateVars.push_back(privateVar);
216 inline void initLinearStep(LLVM::ModuleTranslation &moduleTranslation,
217 mlir::Value &linearStep) {
218 linearSteps.push_back(moduleTranslation.
lookupValue(linearStep));
222 llvm::Error initLinearVar(llvm::IRBuilderBase &builder,
223 LLVM::ModuleTranslation &moduleTranslation,
224 llvm::BasicBlock *loopPreHeader) {
225 builder.SetInsertPoint(loopPreHeader->getTerminator());
226 for (
size_t index = 0; index < linearOrigVars.size(); index++) {
227 llvm::Expected<llvm::Value *> orig =
228 getAddress(builder, moduleTranslation, index, linearOrigVars[index]);
230 return orig.takeError();
231 llvm::LoadInst *linearVarLoad =
232 builder.CreateLoad(linearVarTypes[index], *orig);
233 builder.CreateStore(linearVarLoad, linearStartVals[index]);
235 return llvm::Error::success();
239 LogicalResult initLinearIV(omp::SimdOp simdOp) {
240 auto loopOp = cast<omp::LoopNestOp>(simdOp.getWrappedLoop());
242 if (loopOp.getIVs().size() != 1)
250 MutableArrayRef<BlockArgument> linearArgs =
251 cast<omp::BlockArgOpenMPOpInterface>(*simdOp).getLinearBlockArgs();
252 SmallVector<Value> ivValues{loopOp.getIVs().front()};
253 for (Operation *user : loopOp.getIVs().front().getUsers())
254 if (isa<LLVM::SExtOp, LLVM::ZExtOp, LLVM::TruncOp>(user))
255 ivValues.push_back(user->getResult(0));
257 for (Value ivValue : ivValues) {
258 for (Operation *user : ivValue.getUsers()) {
259 auto storeOp = dyn_cast<LLVM::StoreOp>(user);
260 if (!storeOp || storeOp.getValue() != ivValue)
264 Value addr = storeOp.getAddr();
267 if (
auto load = dyn_cast_if_present<LLVM::LoadOp>(def)) {
268 addr =
load.getAddr();
269 }
else if (
auto gep = dyn_cast_if_present<LLVM::GEPOp>(def)) {
270 addr = gep.getBase();
272 auto copy = llvm::find_if(addr.
getUsers(), [&](Operation *user) {
273 auto memcpy = dyn_cast<LLVM::MemcpyOp>(user);
274 return memcpy && memcpy.getDst() == addr &&
275 llvm::is_contained(linearArgs, memcpy.getSrc());
279 addr = cast<LLVM::MemcpyOp>(*copy).getSrc();
282 auto *it = llvm::find(linearArgs, addr);
283 if (it == linearArgs.end())
285 size_t index = std::distance(linearArgs.begin(), it);
286 if (linearLoopIVIndex && *linearLoopIVIndex != index)
287 return simdOp.emitError(
288 "Could not determine the linear variable associated with the "
289 "loop nest induction variable");
290 linearLoopIVIndex = index;
297 llvm::Error updateLinearVar(llvm::IRBuilderBase &builder,
298 LLVM::ModuleTranslation &moduleTranslation,
299 llvm::BasicBlock *loopBody,
300 llvm::Value *loopInductionVar) {
301 builder.SetInsertPoint(loopBody->getTerminator());
302 for (
size_t index = 0; index < linearStartVals.size(); index++) {
303 llvm::Type *linearVarType = linearVarTypes[index];
304 llvm::Value *iv = loopInductionVar;
305 llvm::Value *step = linearSteps[index];
306 llvm::Expected<llvm::Value *>
result = getAddress(
307 builder, moduleTranslation, index, linearPrivateVars[index]);
309 return result.takeError();
311 if (!iv->getType()->isIntegerTy())
312 llvm_unreachable(
"OpenMP loop induction variable must be an integer "
315 if (linearVarType->isIntegerTy()) {
317 iv = builder.CreateSExtOrTrunc(iv, linearVarType);
318 step = builder.CreateSExtOrTrunc(step, linearVarType);
320 llvm::LoadInst *linearVarStart =
321 builder.CreateLoad(linearVarType, linearStartVals[index]);
322 llvm::Value *mulInst = builder.CreateMul(iv, step);
323 llvm::Value *addInst = builder.CreateAdd(linearVarStart, mulInst);
324 builder.CreateStore(addInst, *
result);
325 }
else if (linearVarType->isFloatingPointTy()) {
327 step = builder.CreateSExtOrTrunc(step, iv->getType());
328 llvm::Value *mulInst = builder.CreateMul(iv, step);
330 llvm::LoadInst *linearVarStart =
331 builder.CreateLoad(linearVarType, linearStartVals[index]);
332 llvm::Value *mulFp = builder.CreateSIToFP(mulInst, linearVarType);
333 llvm::Value *addInst = builder.CreateFAdd(linearVarStart, mulFp);
334 builder.CreateStore(addInst, *
result);
337 "Linear variable must be of integer or floating-point type");
340 return llvm::Error::success();
344 llvm::Error updateLinearIV(llvm::IRBuilderBase &builder,
345 LLVM::ModuleTranslation &moduleTranslation) {
346 if (!linearLoopIVIndex)
347 return llvm::Error::success();
348 size_t index = *linearLoopIVIndex;
351 llvm::Type *varType = linearVarTypes[index];
352 if (!varType->isIntegerTy())
353 llvm_unreachable(
"Linear iteration variable must be of integer type");
354 llvm::Expected<llvm::Value *> var =
355 getAddress(builder, moduleTranslation, index, linearPrivateVars[index]);
357 return var.takeError();
358 llvm::Value *step = builder.CreateSExtOrTrunc(linearSteps[index], varType);
359 llvm::Value *val = builder.CreateLoad(varType, *var);
360 llvm::Value *addInst = builder.CreateAdd(val, step);
361 builder.CreateStore(addInst, *var);
362 return llvm::Error::success();
367 void splitLinearFiniBB(llvm::IRBuilderBase &builder,
368 llvm::BasicBlock *loopExit) {
369 linearFinalizationBB = loopExit->splitBasicBlock(
370 loopExit->getTerminator(),
"omp_loop.linear_finalization");
371 linearExitBB = linearFinalizationBB->splitBasicBlock(
372 linearFinalizationBB->getTerminator(),
"omp_loop.linear_exit");
373 linearLastIterExitBB = linearFinalizationBB->splitBasicBlock(
374 linearFinalizationBB->getTerminator(),
"omp_loop.linear_lastiter_exit");
378 llvm::OpenMPIRBuilder::InsertPointOrErrorTy
379 finalizeLinearVar(llvm::IRBuilderBase &builder,
380 LLVM::ModuleTranslation &moduleTranslation,
381 llvm::Value *lastIter) {
383 builder.SetInsertPoint(linearFinalizationBB->getTerminator());
384 llvm::Value *loopLastIterLoad = builder.CreateLoad(
385 llvm::Type::getInt32Ty(builder.getContext()), lastIter);
386 llvm::Value *isLast =
387 builder.CreateCmp(llvm::CmpInst::ICMP_NE, loopLastIterLoad,
388 llvm::ConstantInt::get(
389 llvm::Type::getInt32Ty(builder.getContext()), 0));
391 builder.SetInsertPoint(linearLastIterExitBB->getTerminator());
392 if (llvm::Error err = storeLinearVars(builder, moduleTranslation))
393 return std::move(err);
398 builder.SetInsertPoint(linearFinalizationBB->getTerminator());
399 builder.CreateCondBr(isLast, linearLastIterExitBB, linearExitBB);
400 linearFinalizationBB->getTerminator()->eraseFromParent();
402 builder.SetInsertPoint(linearExitBB->getTerminator());
404 builder, llvm::omp::OMPD_barrier);
410 emitStoresForLinearVar(llvm::IRBuilderBase &builder,
411 LLVM::ModuleTranslation &moduleTranslation) {
412 return storeLinearVars(builder, moduleTranslation);
421 SymbolRefAttr symbolName) {
422 omp::PrivateClauseOp privatizer =
425 assert(privatizer &&
"privatizer not found in the symbol table");
436 auto todo = [&op](StringRef clauseName) {
437 return op.
emitError() <<
"not yet implemented: Unhandled clause "
438 << clauseName <<
" in " << op.
getName()
442 auto checkAllocate = [&todo](
auto op, LogicalResult &
result) {
443 if (!op.getAllocateVars().empty() || !op.getAllocatorVars().empty())
444 result = todo(
"allocate");
446 auto checkBare = [&todo](
auto op, LogicalResult &
result) {
447 if (op.getKernelType() == omp::TargetExecMode::bare)
448 result = todo(
"ompx_bare");
450 auto checkDepend = [&todo](
auto op, LogicalResult &
result) {
451 if (!op.getDependVars().empty() || op.getDependKinds() ||
452 !op.getDependIterated().empty() || op.getDependIteratedKinds())
455 auto checkHint = [](
auto op, LogicalResult &) {
459 auto checkInReduction = [&todo](
auto op, LogicalResult &
result) {
460 if (isa<omp::TargetOp, omp::TaskOp, omp::TaskloopContextOp>(
461 op.getOperation())) {
462 if (
auto byrefAttr = op.getInReductionByref()) {
463 for (
bool isByRef : *byrefAttr) {
465 result = todo(
"in_reduction with byref modifier");
470 if (isa<omp::TargetOp>(op.getOperation())) {
471 if (
auto inReductionSyms = op.getInReductionSyms()) {
473 (*inReductionSyms).template getAsRange<SymbolRefAttr>()) {
478 "symbol resolution should be guaranteed by the op verifier");
479 if (decl.getInitializerRegion().front().getNumArguments() != 1) {
480 result = todo(
"in_reduction with two-argument initializer");
483 if (!decl.getCleanupRegion().empty()) {
484 result = todo(
"in_reduction with cleanup region");
490 }
else if (!op.getInReductionVars().empty() || op.getInReductionByref() ||
491 op.getInReductionSyms()) {
492 result = todo(
"in_reduction");
495 auto checkNowait = [&todo](
auto op, LogicalResult &
result) {
499 auto checkOrder = [&todo](
auto op, LogicalResult &
result) {
500 if (op.getOrder() || op.getOrderMod())
503 auto checkPrivate = [&todo](
auto op, LogicalResult &
result) {
504 if (!op.getPrivateVars().empty() || op.getPrivateSyms())
505 result = todo(
"privatization");
507 auto checkReduction = [&todo](
auto op, LogicalResult &
result) {
508 if (isa<omp::TeamsOp>(op))
509 if (!op.getReductionVars().empty() || op.getReductionByref() ||
510 op.getReductionSyms())
511 result = todo(
"reduction");
512 if (op.getReductionMod() &&
513 op.getReductionMod().value() != omp::ReductionModifier::defaultmod) {
514 omp::ReductionModifier mod = op.getReductionMod().value();
518 bool taskModifierSupported =
519 mod == omp::ReductionModifier::task &&
520 isa<omp::ParallelOp, omp::WsloopOp, omp::SectionsOp>(op);
521 if (!taskModifierSupported) {
522 result = todo(
"reduction with modifier");
523 }
else if (
auto byref = op.getReductionByref()) {
526 for (
bool isByRef : *byref)
528 result = todo(
"task reduction modifier with by-ref reduction");
534 auto checkTaskReductionByref = [&todo](
auto op, LogicalResult &
result) {
535 if (
auto byrefAttr = op.getTaskReductionByref())
536 for (
bool isByRef : *byrefAttr)
538 result = todo(
"task_reduction with byref modifier");
542 auto checkReductionByref = [&todo](
auto op, LogicalResult &
result) {
543 if (
auto byrefAttr = op.getReductionByref())
544 for (
bool isByRef : *byrefAttr)
546 result = todo(
"reduction with byref modifier");
550 auto checkNumTeams = [&todo](
auto op, LogicalResult &
result) {
551 if (op.hasNumTeamsMultiDim())
552 result = todo(
"num_teams with multi-dimensional values");
554 auto checkNumThreads = [&todo](
auto op, LogicalResult &
result) {
555 if (op.hasNumThreadsMultiDim())
556 result = todo(
"num_threads with multi-dimensional values");
559 auto checkThreadLimit = [&todo](
auto op, LogicalResult &
result) {
560 if (op.hasThreadLimitMultiDim())
561 result = todo(
"thread_limit with multi-dimensional values");
563 auto checkMap = [&todo](
auto op, LogicalResult &
result) {
564 if (!op.getMapIterated().empty())
565 result = todo(
"map/motion clause with iterator modifier");
568 auto checkDynGroupprivate = [&todo](
auto op, LogicalResult &
result) {
569 if (op.getDynGroupprivateSize())
570 result = todo(
"dyn_groupprivate");
575 .Case([&](omp::DistributeOp op) {
576 checkAllocate(op,
result);
579 .Case([&](omp::SectionsOp op) {
580 checkAllocate(op,
result);
582 checkReduction(op,
result);
584 .Case([&](omp::ScopeOp op) { checkReduction(op,
result); })
585 .Case([&](omp::SingleOp op) {
586 checkAllocate(op,
result);
589 .Case([&](omp::TeamsOp op) {
590 checkAllocate(op,
result);
592 checkNumTeams(op,
result);
593 checkThreadLimit(op,
result);
594 checkDynGroupprivate(op,
result);
596 .Case([&](omp::TaskOp op) {
597 checkAllocate(op,
result);
598 checkInReduction(op,
result);
600 .Case([&](omp::TaskgroupOp op) {
601 checkAllocate(op,
result);
602 checkTaskReductionByref(op,
result);
604 .Case([&](omp::DispatchOp op) {
613 .Case([&](omp::TaskloopContextOp op) {
614 checkAllocate(op,
result);
615 checkInReduction(op,
result);
616 checkReduction(op,
result);
617 checkReductionByref(op,
result);
619 .Case([&](omp::WsloopOp op) {
620 checkAllocate(op,
result);
622 checkReduction(op,
result);
624 .Case([&](omp::ParallelOp op) {
625 checkReduction(op,
result);
626 checkNumThreads(op,
result);
628 .Case([&](omp::SimdOp op) { checkReduction(op,
result); })
629 .Case<omp::AtomicReadOp, omp::AtomicWriteOp, omp::AtomicUpdateOp,
630 omp::AtomicCaptureOp>([&](
auto op) { checkHint(op,
result); })
631 .Case([&](omp::AtomicCompareOp op) {
637 auto structTy = dyn_cast<LLVM::LLVMStructType>(argType);
643 result = todo(
"compare for complex types wider than 128 bits");
645 .Case<omp::TargetEnterDataOp, omp::TargetExitDataOp>([&](
auto op) {
649 .Case([&](omp::TargetUpdateOp op) {
653 .Case([&](omp::TargetOp op) {
654 checkAllocate(op,
result);
656 checkInReduction(op,
result);
658 checkThreadLimit(op,
result);
660 .Case([&](omp::TargetDataOp op) { checkMap(op,
result); })
661 .Case([&](omp::DeclareMapperInfoOp op) { checkMap(op,
result); })
672 llvm::handleAllErrors(
674 [&](
const PreviouslyReportedError &) {
result = failure(); },
675 [&](
const llvm::ErrorInfoBase &err) {
698 llvm::OpenMPIRBuilder::InsertPointTy allocInsertPoint;
701 [&](OpenMPAllocStackFrame &frame) {
702 allocInsertPoint = frame.allocBlock->getFirstInsertionPt();
703 deallocInsertPoints = frame.deallocBlocks;
711 allocInsertPoint.getNodeParent()->getParent() ==
712 builder.GetInsertBlock()->getParent()) {
714 deallocBlocks->insert(deallocBlocks->end(), deallocInsertPoints.begin(),
715 deallocInsertPoints.end());
716 return allocInsertPoint;
726 if (builder.GetInsertBlock() ==
727 &builder.GetInsertBlock()->getParent()->getEntryBlock()) {
728 assert(builder.GetInsertPoint() == builder.GetInsertBlock()->end() &&
729 "Assuming end of basic block");
730 llvm::BasicBlock *entryBB = llvm::BasicBlock::Create(
731 builder.getContext(),
"entry", builder.GetInsertBlock()->getParent(),
732 builder.GetInsertBlock()->getNextNode());
733 builder.CreateBr(entryBB);
734 builder.SetInsertPoint(entryBB);
740 for (llvm::BasicBlock &block : *builder.GetInsertBlock()->getParent()) {
744 llvm::Instruction *terminator = block.getTerminatorOrNull();
745 if (isa_and_present<llvm::ReturnInst>(terminator))
746 deallocBlocks->emplace_back(&block);
750 llvm::BasicBlock &funcEntryBlock =
751 builder.GetInsertBlock()->getParent()->getEntryBlock();
752 return funcEntryBlock.getFirstInsertionPt();
758static llvm::CanonicalLoopInfo *
760 llvm::CanonicalLoopInfo *loopInfo =
nullptr;
761 moduleTranslation.
stackWalk<OpenMPLoopInfoStackFrame>(
762 [&](OpenMPLoopInfoStackFrame &frame) {
763 loopInfo = frame.loopInfo;
775 Region ®ion, StringRef blockName, llvm::IRBuilderBase &builder,
778 bool isLoopWrapper = isa<omp::LoopWrapperInterface>(region.
getParentOp());
780 llvm::BasicBlock *continuationBlock =
781 splitBB(builder,
true,
"omp.region.cont");
782 llvm::BasicBlock *sourceBlock = builder.GetInsertBlock();
784 llvm::LLVMContext &llvmContext = builder.getContext();
785 for (
Block &bb : region) {
786 llvm::BasicBlock *llvmBB = llvm::BasicBlock::Create(
787 llvmContext, blockName, builder.GetInsertBlock()->getParent(),
788 builder.GetInsertBlock()->getNextNode());
789 moduleTranslation.
mapBlock(&bb, llvmBB);
792 llvm::Instruction *sourceTerminator = sourceBlock->getTerminator();
799 unsigned numYields = 0;
801 if (!isLoopWrapper) {
802 bool operandsProcessed =
false;
804 if (omp::YieldOp yield = dyn_cast<omp::YieldOp>(bb.getTerminator())) {
805 if (!operandsProcessed) {
806 for (
unsigned i = 0, e = yield->getNumOperands(); i < e; ++i) {
807 continuationBlockPHITypes.push_back(
808 moduleTranslation.
convertType(yield->getOperand(i).getType()));
810 operandsProcessed =
true;
812 assert(continuationBlockPHITypes.size() == yield->getNumOperands() &&
813 "mismatching number of values yielded from the region");
814 for (
unsigned i = 0, e = yield->getNumOperands(); i < e; ++i) {
815 llvm::Type *operandType =
816 moduleTranslation.
convertType(yield->getOperand(i).getType());
818 assert(continuationBlockPHITypes[i] == operandType &&
819 "values of mismatching types yielded from the region");
829 if (!continuationBlockPHITypes.empty())
831 continuationBlockPHIs &&
832 "expected continuation block PHIs if converted regions yield values");
833 if (continuationBlockPHIs) {
834 llvm::IRBuilderBase::InsertPointGuard guard(builder);
835 continuationBlockPHIs->reserve(continuationBlockPHITypes.size());
836 builder.SetInsertPoint(continuationBlock->begin());
837 for (llvm::Type *ty : continuationBlockPHITypes)
838 continuationBlockPHIs->push_back(builder.CreatePHI(ty, numYields));
844 for (
Block *bb : blocks) {
845 llvm::BasicBlock *llvmBB = moduleTranslation.
lookupBlock(bb);
848 if (bb->isEntryBlock()) {
849 assert(sourceTerminator->getNumSuccessors() == 1 &&
850 "provided entry block has multiple successors");
851 assert(sourceTerminator->getSuccessor(0) == continuationBlock &&
852 "ContinuationBlock is not the successor of the entry block");
853 sourceTerminator->setSuccessor(0, llvmBB);
856 llvm::IRBuilderBase::InsertPointGuard guard(builder);
858 moduleTranslation.
convertBlock(*bb, bb->isEntryBlock(), builder)))
859 return llvm::make_error<PreviouslyReportedError>();
864 builder.CreateBr(continuationBlock);
875 Operation *terminator = bb->getTerminator();
876 if (isa<omp::TerminatorOp, omp::YieldOp>(terminator)) {
877 builder.CreateBr(continuationBlock);
879 for (
unsigned i = 0, e = terminator->
getNumOperands(); i < e; ++i)
880 (*continuationBlockPHIs)[i]->addIncoming(
894 return continuationBlock;
900 case omp::ClauseProcBindKind::Close:
901 return llvm::omp::ProcBindKind::OMP_PROC_BIND_close;
902 case omp::ClauseProcBindKind::Master:
903 return llvm::omp::ProcBindKind::OMP_PROC_BIND_master;
904 case omp::ClauseProcBindKind::Primary:
905 return llvm::omp::ProcBindKind::OMP_PROC_BIND_primary;
906 case omp::ClauseProcBindKind::Spread:
907 return llvm::omp::ProcBindKind::OMP_PROC_BIND_spread;
909 llvm_unreachable(
"Unknown ClauseProcBindKind kind");
916 auto dispatchOp = cast<omp::DispatchOp>(opInst);
921 auto ®ion = dispatchOp.getRegion();
926 builder.SetInsertPoint(*
result);
934 auto maskedOp = cast<omp::MaskedOp>(opInst);
935 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
940 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
943 auto ®ion = maskedOp.getRegion();
944 builder.restoreIP(codeGenIP);
952 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
954 llvm::Value *filterVal =
nullptr;
955 if (
auto filterVar = maskedOp.getFilteredThreadId()) {
956 filterVal = moduleTranslation.
lookupValue(filterVar);
958 llvm::LLVMContext &llvmContext = builder.getContext();
960 llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvmContext), 0);
962 assert(filterVal !=
nullptr);
963 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
964 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
971 builder.restoreIP(*afterIP);
979 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
980 auto masterOp = cast<omp::MasterOp>(opInst);
985 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
988 auto ®ion = masterOp.getRegion();
989 builder.restoreIP(codeGenIP);
997 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
999 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
1000 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
1007 builder.restoreIP(*afterIP);
1015 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1016 auto criticalOp = cast<omp::CriticalOp>(opInst);
1021 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
1024 auto ®ion = cast<omp::CriticalOp>(opInst).getRegion();
1025 builder.restoreIP(codeGenIP);
1033 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
1035 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
1036 llvm::LLVMContext &llvmContext = moduleTranslation.
getLLVMContext();
1037 llvm::Constant *hint =
nullptr;
1040 if (criticalOp.getNameAttr()) {
1043 auto symbolRef = cast<SymbolRefAttr>(criticalOp.getNameAttr());
1044 auto criticalDeclareOp =
1048 llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvmContext),
1049 static_cast<int>(criticalDeclareOp.getHint()));
1051 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
1053 ompLoc, bodyGenCB, finiCB, criticalOp.getName().value_or(
""), hint);
1058 builder.restoreIP(*afterIP);
1070 template <
typename OP>
1073 cast<
omp::BlockArgOpenMPOpInterface>(*op).getPrivateBlockArgs())) {
1076 collectPrivatizationDecls<OP>(op);
1084 template <
typename OP>
1089 cast<omp::BlockArgOpenMPOpInterface>(*op).getLinearBlockArgs());
1090 llvm::append_range(
mlirVars, op.getLinearVars());
1091 if (std::optional<ArrayAttr> attr = op.getLinearSyms())
1092 for (
auto symbolRef : attr->getAsRange<SymbolRefAttr>())
1109 void collectPrivatizationDecls(OP op) {
1110 std::optional<ArrayAttr> attr = op.getPrivateSyms();
1115 for (
auto symbolRef : attr->getAsRange<SymbolRefAttr>()) {
1122template <
typename T>
1126 std::optional<ArrayAttr> attr = op.getReductionSyms();
1130 reductions.reserve(reductions.size() + op.getNumReductionVars());
1131 for (
auto symbolRef : attr->getAsRange<SymbolRefAttr>()) {
1132 reductions.push_back(
1147 Operation *contextOp, std::optional<ArrayAttr> syms, StringRef opName,
1151 out.reserve(out.size() + syms->size());
1152 for (
auto sym : syms->getAsRange<SymbolRefAttr>()) {
1157 <<
"failed to resolve " << clauseName
1158 <<
" declare_reduction symbol " << sym.getRootReference() <<
" in "
1160 if (decl.getInitializerRegion().front().getNumArguments() != 1)
1162 <<
"not yet implemented: " << clauseName
1163 <<
" with two-argument initializer in " << opName;
1164 if (!decl.getCleanupRegion().empty())
1165 return contextOp->
emitError() <<
"not yet implemented: " << clauseName
1166 <<
" with cleanup region in " << opName;
1167 if (decl.getReductionRegion().empty())
1169 << clauseName <<
" declare_reduction is missing a combiner region";
1170 out.push_back(decl);
1181 Region ®ion, StringRef blockName, llvm::IRBuilderBase &builder,
1190 llvm::BasicBlock *insertBlock = builder.GetInsertBlock();
1191 llvm::Instruction *potentialTerminator =
1192 insertBlock->empty() ?
nullptr : &insertBlock->back();
1194 if (potentialTerminator && potentialTerminator->isTerminator()) {
1195 assert(builder.GetInsertPoint() == potentialTerminator->getIterator() &&
1196 "Insertion point should be the terminator");
1197 potentialTerminator->removeFromParent();
1199 builder.SetInsertPoint(insertBlock);
1205 llvm::DebugLoc loc = builder.getCurrentDebugLocation();
1207 region.
front(),
true, builder)))
1209 builder.SetCurrentDebugLocation(loc);
1212 if (continuationBlockArgs)
1214 *continuationBlockArgs,
1221 if (potentialTerminator && potentialTerminator->isTerminator()) {
1222 llvm::BasicBlock *block = builder.GetInsertBlock();
1223 if (block->empty()) {
1229 potentialTerminator->insertInto(block, block->begin());
1231 potentialTerminator->insertAfter(&block->back());
1245 if (continuationBlockArgs)
1246 llvm::append_range(*continuationBlockArgs, phis);
1247 builder.SetInsertPoint((*continuationBlock)->getFirstInsertionPt());
1254using OwningReductionGen =
1255 std::function<llvm::OpenMPIRBuilder::InsertPointOrErrorTy(
1256 llvm::OpenMPIRBuilder::InsertPointTy, llvm::Value *, llvm::Value *,
1258using OwningAtomicReductionGen =
1259 std::function<llvm::OpenMPIRBuilder::InsertPointOrErrorTy(
1260 llvm::OpenMPIRBuilder::InsertPointTy, llvm::Type *, llvm::Value *,
1262using OwningDataPtrPtrReductionGen =
1263 std::function<llvm::OpenMPIRBuilder::InsertPointOrErrorTy(
1264 llvm::OpenMPIRBuilder::InsertPointTy, llvm::Value *, llvm::Value *&)>;
1270static OwningReductionGen
1276 OwningReductionGen gen =
1277 [&, decl](llvm::OpenMPIRBuilder::InsertPointTy insertPoint,
1278 llvm::Value *lhs, llvm::Value *rhs,
1279 llvm::Value *&
result)
mutable
1280 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
1281 moduleTranslation.
mapValue(decl.getReductionLhsArg(), lhs);
1282 moduleTranslation.
mapValue(decl.getReductionRhsArg(), rhs);
1283 builder.restoreIP(insertPoint);
1286 "omp.reduction.nonatomic.body", builder,
1287 moduleTranslation, &phis)))
1288 return llvm::createStringError(
1289 "failed to inline `combiner` region of `omp.declare_reduction`");
1290 result = llvm::getSingleElement(phis);
1291 return builder.saveIP();
1300static OwningAtomicReductionGen
1302 llvm::IRBuilderBase &builder,
1304 if (decl.getAtomicReductionRegion().empty())
1305 return OwningAtomicReductionGen();
1311 [&, decl](llvm::OpenMPIRBuilder::InsertPointTy insertPoint, llvm::Type *,
1312 llvm::Value *lhs, llvm::Value *rhs)
mutable
1313 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
1314 moduleTranslation.
mapValue(decl.getAtomicReductionLhsArg(), lhs);
1315 moduleTranslation.
mapValue(decl.getAtomicReductionRhsArg(), rhs);
1316 builder.restoreIP(insertPoint);
1319 "omp.reduction.atomic.body", builder,
1320 moduleTranslation, &phis)))
1321 return llvm::createStringError(
1322 "failed to inline `atomic` region of `omp.declare_reduction`");
1323 assert(phis.empty());
1324 return builder.saveIP();
1333static OwningDataPtrPtrReductionGen
1336 if (!isByRef || decl.getDataPtrPtrRegion().empty())
1337 return OwningDataPtrPtrReductionGen();
1339 OwningDataPtrPtrReductionGen refDataPtrGen =
1340 [&, decl](llvm::OpenMPIRBuilder::InsertPointTy insertPoint,
1341 llvm::Value *byRefVal, llvm::Value *&
result)
mutable
1342 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
1343 moduleTranslation.
mapValue(decl.getDataPtrPtrRegionArg(), byRefVal);
1344 builder.restoreIP(insertPoint);
1347 "omp.data_ptr_ptr.body", builder,
1348 moduleTranslation, &phis)))
1349 return llvm::createStringError(
1350 "failed to inline `data_ptr_ptr` region of `omp.declare_reduction`");
1351 result = llvm::getSingleElement(phis);
1352 return builder.saveIP();
1355 return refDataPtrGen;
1362 auto orderedOp = cast<omp::OrderedOp>(opInst);
1367 omp::ClauseDepend dependType = *orderedOp.getDoacrossDependType();
1368 bool isDependSource = dependType == omp::ClauseDepend::dependsource;
1369 unsigned numLoops = *orderedOp.getDoacrossNumLoops();
1371 moduleTranslation.
lookupValues(orderedOp.getDoacrossDependVars());
1373 size_t indexVecValues = 0;
1374 while (indexVecValues < vecValues.size()) {
1376 storeValues.reserve(numLoops);
1377 for (
unsigned i = 0; i < numLoops; i++) {
1378 storeValues.push_back(vecValues[indexVecValues]);
1381 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
1383 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
1384 builder.restoreIP(moduleTranslation.
getOpenMPBuilder()->createOrderedDepend(
1385 ompLoc, allocaIP, numLoops, storeValues,
".cnt.addr", isDependSource));
1395 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1396 auto orderedRegionOp = cast<omp::OrderedRegionOp>(opInst);
1401 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
1404 auto ®ion = cast<omp::OrderedRegionOp>(opInst).getRegion();
1405 builder.restoreIP(codeGenIP);
1413 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
1415 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
1416 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
1418 ompLoc, bodyGenCB, finiCB, !orderedRegionOp.getParLevelSimd());
1423 builder.restoreIP(*afterIP);
1429struct DeferredStore {
1430 DeferredStore(llvm::Value *value, llvm::Value *address)
1431 : value(value), address(address) {}
1434 llvm::Value *address;
1441template <
typename T>
1444 llvm::IRBuilderBase &builder,
1446 const llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
1452 llvm::IRBuilderBase::InsertPointGuard guard(builder);
1453 builder.SetInsertPoint(allocaIP.getNodeParent()->getTerminator());
1459 deferredStores.reserve(op.getNumReductionVars());
1461 for (std::size_t i = 0; i < op.getNumReductionVars(); ++i) {
1462 Region &allocRegion = reductionDecls[i].getAllocRegion();
1464 if (allocRegion.
empty())
1469 builder, moduleTranslation, &phis)))
1470 return op.emitError(
1471 "failed to inline `alloc` region of `omp.declare_reduction`");
1473 assert(phis.size() == 1 &&
"expected one allocation to be yielded");
1474 builder.SetInsertPoint(allocaIP.getNodeParent()->getTerminator());
1478 llvm::Type *ptrTy = builder.getPtrTy();
1482 if (useDeviceSharedMem) {
1483 var = ompBuilder->createOMPAllocShared(builder, varTy);
1485 var = builder.CreateAlloca(varTy);
1486 var = builder.CreatePointerBitCastOrAddrSpaceCast(var, ptrTy);
1489 llvm::Value *castPhi =
1490 builder.CreatePointerBitCastOrAddrSpaceCast(phis[0], ptrTy);
1492 deferredStores.emplace_back(castPhi, var);
1494 privateReductionVariables[i] = var;
1495 moduleTranslation.
mapValue(reductionArgs[i], castPhi);
1496 reductionVariableMap.try_emplace(op.getReductionVars()[i], castPhi);
1498 assert(allocRegion.
empty() &&
1499 "allocaction is implicit for by-val reduction");
1501 llvm::Type *ptrTy = builder.getPtrTy();
1505 if (useDeviceSharedMem) {
1506 var = ompBuilder->createOMPAllocShared(builder, varTy);
1508 var = builder.CreateAlloca(varTy);
1509 var = builder.CreatePointerBitCastOrAddrSpaceCast(var, ptrTy);
1512 moduleTranslation.
mapValue(reductionArgs[i], var);
1513 privateReductionVariables[i] = var;
1514 reductionVariableMap.try_emplace(op.getReductionVars()[i], var);
1522template <
typename T>
1525 llvm::IRBuilderBase &builder,
1530 mlir::omp::DeclareReductionOp &reduction = reductionDecls[i];
1531 Region &initializerRegion = reduction.getInitializerRegion();
1534 mlir::Value mlirSource = loop.getReductionVars()[i];
1535 llvm::Value *llvmSource = moduleTranslation.
lookupValue(mlirSource);
1536 llvm::Value *origVal = llvmSource;
1538 if (!isa<LLVM::LLVMPointerType>(
1539 reduction.getInitializerMoldArg().getType()) &&
1540 isa<LLVM::LLVMPointerType>(mlirSource.
getType())) {
1543 reduction.getInitializerMoldArg().getType()),
1544 llvmSource,
"omp_orig");
1546 moduleTranslation.
mapValue(reduction.getInitializerMoldArg(), origVal);
1549 llvm::Value *allocation =
1550 reductionVariableMap.lookup(loop.getReductionVars()[i]);
1551 moduleTranslation.
mapValue(reduction.getInitializerAllocArg(), allocation);
1557 llvm::BasicBlock *block =
nullptr) {
1558 if (block ==
nullptr)
1559 block = builder.GetInsertBlock();
1561 if (!block->hasTerminator())
1562 builder.SetInsertPoint(block);
1564 builder.SetInsertPoint(block->getTerminator());
1572template <
typename OP>
1575 llvm::IRBuilderBase &builder,
1577 llvm::BasicBlock *latestAllocaBlock,
1583 if (op.getNumReductionVars() == 0)
1589 llvm::BasicBlock *initBlock = splitBB(builder,
true,
"omp.reduction.init");
1592 llvm::IRBuilderBase::InsertPointGuard guard(builder);
1593 auto allocaIP = latestAllocaBlock->getTerminator()->getIterator();
1594 builder.restoreIP(allocaIP);
1596 for (
unsigned i = 0; i < op.getNumReductionVars(); ++i) {
1598 if (!reductionDecls[i].getAllocRegion().empty())
1606 if (useDeviceSharedMem)
1607 byRefVars[i] = ompBuilder->createOMPAllocShared(builder, varTy);
1609 byRefVars[i] = builder.CreateAlloca(varTy);
1618 for (
auto [data, addr] : deferredStores)
1619 builder.CreateStore(data, addr);
1624 for (
unsigned i = 0; i < op.getNumReductionVars(); ++i) {
1629 reductionVariableMap, i);
1637 "omp.reduction.neutral", builder,
1638 moduleTranslation, &phis)))
1641 assert(phis.size() == 1 &&
"expected one value to be yielded from the "
1642 "reduction neutral element declaration region");
1647 if (!reductionDecls[i].getAllocRegion().empty())
1656 builder.CreateStore(phis[0], byRefVars[i]);
1658 privateReductionVariables[i] = byRefVars[i];
1659 moduleTranslation.
mapValue(reductionArgs[i], phis[0]);
1660 reductionVariableMap.try_emplace(op.getReductionVars()[i], phis[0]);
1663 builder.CreateStore(phis[0], privateReductionVariables[i]);
1670 moduleTranslation.
forgetMapping(reductionDecls[i].getInitializerRegion());
1677template <
typename T>
1678static void collectReductionInfo(
1679 T loop, llvm::IRBuilderBase &builder,
1688 unsigned numReductions = loop.getNumReductionVars();
1690 for (
unsigned i = 0; i < numReductions; ++i) {
1693 owningAtomicReductionGens.push_back(
1696 reductionDecls[i], builder, moduleTranslation, isByRef[i]));
1700 reductionInfos.reserve(numReductions);
1701 for (
unsigned i = 0; i < numReductions; ++i) {
1702 llvm::OpenMPIRBuilder::ReductionGenAtomicCBTy
atomicGen =
nullptr;
1703 if (owningAtomicReductionGens[i])
1704 atomicGen = owningAtomicReductionGens[i];
1705 llvm::Value *variable =
1706 moduleTranslation.
lookupValue(loop.getReductionVars()[i]);
1709 if (
auto alloca = mlir::dyn_cast<LLVM::AllocaOp>(op)) {
1710 allocatedType = alloca.getElemType();
1717 reductionInfos.push_back(
1719 privateReductionVariables[i],
1720 llvm::OpenMPIRBuilder::EvalKind::Scalar,
1724 allocatedType ? moduleTranslation.
convertType(allocatedType) :
nullptr,
1725 reductionDecls[i].getByrefElementType()
1727 *reductionDecls[i].getByrefElementType())
1737 llvm::IRBuilderBase &builder, StringRef regionName,
1738 bool shouldLoadCleanupRegionArg =
true) {
1739 for (
auto [i, cleanupRegion] : llvm::enumerate(cleanupRegions)) {
1740 if (cleanupRegion->empty())
1746 llvm::Instruction *potentialTerminator =
1747 builder.GetInsertBlock()->empty() ?
nullptr
1748 : &builder.GetInsertBlock()->back();
1749 if (potentialTerminator && potentialTerminator->isTerminator())
1750 builder.SetInsertPoint(potentialTerminator);
1751 llvm::Value *privateVarValue =
1752 shouldLoadCleanupRegionArg
1753 ? builder.CreateLoad(
1755 privateVariables[i])
1756 : privateVariables[i];
1761 moduleTranslation)))
1774 OP op, llvm::IRBuilderBase &builder,
1776 llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
1779 bool isNowait =
false,
bool isTeamsReduction =
false) {
1781 if (op.getNumReductionVars() == 0)
1793 collectReductionInfo(op, builder, moduleTranslation, reductionDecls,
1795 owningReductionGenRefDataPtrGens,
1796 privateReductionVariables, reductionInfos, isByRef);
1801 llvm::UnreachableInst *tempTerminator = builder.CreateUnreachable();
1802 builder.SetInsertPoint(tempTerminator);
1803 llvm::DebugLoc reductionLoc = builder.getCurrentDebugLocation();
1804 llvm::OpenMPIRBuilder::InsertPointOrErrorTy contInsertPoint =
1805 ompBuilder->createReductions(builder, allocaIP, reductionInfos, isByRef,
1806 isNowait, isTeamsReduction);
1811 if (!contInsertPoint->isValid())
1812 return op->emitOpError() <<
"failed to convert reductions";
1814 llvm::OpenMPIRBuilder::InsertPointTy afterIP = *contInsertPoint;
1815 if (!isTeamsReduction) {
1816 llvm::OpenMPIRBuilder::InsertPointOrErrorTy barrierIP =
1817 ompBuilder->createBarrier({*contInsertPoint, reductionLoc},
1818 llvm::omp::OMPD_for);
1822 afterIP = *barrierIP;
1825 tempTerminator->eraseFromParent();
1826 builder.restoreIP(afterIP);
1830 llvm::transform(reductionDecls, std::back_inserter(reductionRegions),
1831 [](omp::DeclareReductionOp reductionDecl) {
1832 return &reductionDecl.getCleanupRegion();
1835 reductionRegions, privateReductionVariables, moduleTranslation, builder,
1836 "omp.reduction.cleanup");
1839 if (useDeviceSharedMem) {
1840 for (
auto [var, reductionDecl] :
1841 llvm::zip_equal(privateReductionVariables, reductionDecls))
1842 ompBuilder->createOMPFreeShared(
1843 builder, var, moduleTranslation.
convertType(reductionDecl.getType()));
1856template <
typename OP>
1860 llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
1865 if (op.getNumReductionVars() == 0)
1871 allocaIP, reductionDecls,
1872 privateReductionVariables, reductionVariableMap,
1873 deferredStores, isByRef)))
1876 return initReductionVars(op, reductionArgs, builder, moduleTranslation,
1877 allocaIP.getNodeParent(), reductionDecls,
1878 privateReductionVariables, reductionVariableMap,
1879 isByRef, deferredStores);
1893 if (mappedPrivateVars ==
nullptr || !mappedPrivateVars->contains(privateVar))
1896 Value blockArg = (*mappedPrivateVars)[privateVar];
1899 assert(isa<LLVM::LLVMPointerType>(blockArgType) &&
1900 "A block argument corresponding to a mapped var should have "
1903 if (privVarType == blockArgType)
1910 if (!isa<LLVM::LLVMPointerType>(privVarType))
1911 return builder.CreateLoad(moduleTranslation.
convertType(privVarType),
1928 llvm::Type *regionArgType =
1930 if (regionArgType->isPointerTy() || !value->getType()->isPointerTy())
1933 return builder.CreateLoad(regionArgType, value);
1940 omp::PrivateClauseOp privatizer, llvm::Value *var) {
1941 Region ®ion = privatizer.getDataAddressRegion();
1950 builder, moduleTranslation, &address)))
1951 return llvm::make_error<PreviouslyReportedError>();
1953 return address.front();
1963 omp::PrivateClauseOp &privDecl, llvm::Value *nonPrivateVar,
1965 llvm::BasicBlock *privInitBlock,
1967 Region &initRegion = privDecl.getInitRegion();
1968 if (initRegion.
empty())
1969 return llvmPrivateVar;
1971 assert(nonPrivateVar);
1972 moduleTranslation.
mapValue(privDecl.getInitMoldArg(), nonPrivateVar);
1973 moduleTranslation.
mapValue(privDecl.getInitPrivateArg(), llvmPrivateVar);
1978 moduleTranslation, &phis)))
1979 return llvm::createStringError(
1980 "failed to inline `init` region of `omp.private`");
1982 assert(phis.size() == 1 &&
"expected one allocation to be yielded");
1999 llvm::Value *llvmPrivateVar, llvm::BasicBlock *privInitBlock,
2002 builder, moduleTranslation, privDecl,
2005 blockArg, llvmPrivateVar, privInitBlock, mappedPrivateVars);
2014 return llvm::Error::success();
2016 llvm::BasicBlock *privInitBlock = splitBB(builder,
true,
"omp.private.init");
2019 for (
auto [idx, zip] : llvm::enumerate(llvm::zip_equal(
2022 auto [privDecl, mlirPrivVar, blockArg, llvmPrivateVar] = zip;
2024 builder, moduleTranslation, privDecl, mlirPrivVar, blockArg,
2025 llvmPrivateVar, privInitBlock, mappedPrivateVars);
2028 return privVarOrErr.takeError();
2030 llvmPrivateVar = privVarOrErr.get();
2031 moduleTranslation.
mapValue(blockArg, llvmPrivateVar);
2036 return llvm::Error::success();
2041 llvm::IRBuilderBase &builder,
2044 for (
Value allocatorVar : allocatorVars) {
2048 llvm::Value *allocator = moduleTranslation.
lookupValue(allocatorVar);
2050 return op.
emitError(
"failed to translate OpenMP allocator operand");
2051 if (allocator->getType()->isIntegerTy())
2052 allocator = builder.CreateIntToPtr(allocator, builder.getPtrTy());
2053 else if (allocator->getType()->isPointerTy())
2054 allocator = builder.CreatePointerBitCastOrAddrSpaceCast(
2055 allocator, builder.getPtrTy());
2058 "OpenMP allocator operand must have integer or pointer type");
2068template <
typename T>
2070 T op, llvm::IRBuilderBase &builder,
2073 llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
2075 std::optional<llvm::OpenMPIRBuilder::InsertPointTy> allocatorIP =
2080 llvm::BasicBlock *allocaBB = allocaIP.getNodeParent();
2081 llvm::Instruction *allocaTerminator = allocaBB->getTerminator();
2082 splitBB(allocaTerminator->getIterator(),
true,
2083 allocaTerminator->getDebugLoc(),
"omp.region.after_alloca");
2085 allocaTerminator = allocaBB->getTerminator();
2087 assert(allocaTerminator->getNumSuccessors() == 1 &&
2088 "This is an unconditional branch created by splitBB");
2089 allocaIP = allocaTerminator->getIterator();
2091 llvm::Instruction *allocatorTerminator =
nullptr;
2092 llvm::BasicBlock *afterAllocatorAllocations =
nullptr;
2094 llvm::BasicBlock *allocatorBB = allocatorIP->getNodeParent();
2095 allocatorTerminator = allocatorBB->getTerminator();
2096 afterAllocatorAllocations = splitBB(
2097 allocatorTerminator->getIterator(),
true,
2098 allocatorTerminator->getDebugLoc(),
"omp.region.after_allocate");
2099 allocatorTerminator = allocatorBB->getTerminator();
2100 assert(allocatorTerminator->getNumSuccessors() == 1 &&
2101 "This is an unconditional branch created by splitBB");
2104 std::optional<llvm::IRBuilderBase::InsertPointGuard> guard;
2106 guard.emplace(builder);
2107 builder.SetInsertPoint(allocaTerminator);
2109 llvm::DataLayout dataLayout = builder.getDataLayout();
2110 llvm::BasicBlock *afterAllocas = allocaTerminator->getSuccessor(0);
2114 unsigned int allocaAS =
2115 moduleTranslation.
getLLVMModule()->getDataLayout().getAllocaAddrSpace();
2118 .getProgramAddressSpace();
2124 if constexpr (std::is_same_v<T, omp::ParallelOp> ||
2125 std::is_same_v<T, omp::ScopeOp>) {
2126 allocatorVars = op.getAllocatorVars();
2127 allocateAlignments = op.getAllocateAlignmentsAttr();
2128 if (
auto privateIndices = op.getAllocatePrivateIndicesAttr())
2129 for (
auto [allocateIndex, privateIndex] :
2130 llvm::enumerate(privateIndices.asArrayRef()))
2131 allocateItemForPrivate[privateIndex] = allocateIndex;
2134 for (
auto [privateIndex, tuple] : llvm::enumerate(llvm::zip_equal(
2137 auto [privDecl, mlirPrivVar, blockArg] = tuple;
2138 llvm::Type *llvmAllocType =
2139 moduleTranslation.
convertType(privDecl.getType());
2140 llvm::Value *llvmPrivateVar =
nullptr;
2141 int64_t allocateIndex = allocateItemForPrivate[privateIndex];
2142 builder.SetInsertPoint(allocateIndex >= 0 && allocatorTerminator
2143 ? allocatorTerminator
2144 : allocaTerminator);
2145 if (allocateIndex >= 0) {
2146 if (ompBuilder->Config.isTargetDevice() ||
2147 op->template getParentOfType<omp::TargetOp>())
2148 return llvm::createStringError(
2149 "allocate clause in an OpenMP device context is not supported");
2150 if (!llvmAllocType->isSized())
2151 return llvm::createStringError(
2152 "allocate clause private type must have a fixed size");
2153 llvm::TypeSize size = dataLayout.getTypeAllocSize(llvmAllocType);
2154 if (size.isScalable())
2155 return llvm::createStringError(
2156 "allocate clause private type must have a fixed size");
2157 llvm::IntegerType *sizeTy =
2158 moduleTranslation.
getLLVMModule()->getDataLayout().getIntPtrType(
2160 if (!llvm::isUIntN(sizeTy->getBitWidth(), size.getFixedValue()))
2161 return llvm::createStringError(
2162 "OpenMP allocation size cannot be represented by the target size "
2164 llvm::Value *sizeValue =
2165 llvm::ConstantInt::get(sizeTy, size.getFixedValue());
2167 Value allocatorVar = allocatorVars[allocateIndex];
2170 return llvm::createStringError(
2171 "failed to find converted OpenMP allocator operand");
2172 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2174 allocateAlignments ? allocateAlignments[allocateIndex] : 0;
2175 if (alignment != 0) {
2179 uint64_t alignmentValue = std::max<uint64_t>(
2180 static_cast<uint64_t
>(alignment),
2181 dataLayout.getABITypeAlign(llvmAllocType).value());
2182 if (!llvm::isUIntN(sizeTy->getBitWidth(), alignmentValue))
2183 return llvm::createStringError(
2184 "OpenMP allocation alignment cannot be represented by the "
2185 "target size type");
2186 llvmPrivateVar = ompBuilder->createOMPAlignedAlloc(
2187 ompLoc, llvm::ConstantInt::get(sizeTy, alignmentValue), sizeValue,
2188 allocator->second,
"omp.private.alloc");
2190 llvmPrivateVar = ompBuilder->createOMPAlloc(
2191 ompLoc, sizeValue, allocator->second,
"omp.private.alloc");
2193 if (!llvmPrivateVar)
2194 return llvm::createStringError(
2195 "failed to create OpenMP private allocation");
2197 {llvmPrivateVar, allocator->second});
2198 }
else if (mightUseDeviceSharedMem &&
2200 llvmPrivateVar = ompBuilder->createOMPAllocShared(builder, llvmAllocType);
2202 llvmPrivateVar = builder.CreateAlloca(
2203 llvmAllocType,
nullptr,
"omp.private.alloc");
2204 if (allocaAS != defaultAS)
2205 llvmPrivateVar = builder.CreateAddrSpaceCast(
2206 llvmPrivateVar, builder.getPtrTy(defaultAS));
2209 privateVarsInfo.
llvmVars.push_back(llvmPrivateVar);
2212 return afterAllocatorAllocations ? afterAllocatorAllocations : afterAllocas;
2223 if (mlir::isa<omp::ParallelOp>(parent))
2226 if (mlir::isa<omp::SingleOp, omp::CriticalOp, omp::MaskedOp, omp::MasterOp,
2227 omp::SectionOp>(parent))
2240 llvm::OpenMPIRBuilder::InsertPointOrErrorTy res =
2241 ompBuilder->createBarrier(builder, llvm::omp::OMPD_barrier);
2254 bool needsFirstprivate =
2255 llvm::any_of(privateDecls, [](omp::PrivateClauseOp &privOp) {
2256 return privOp.getDataSharingType() ==
2257 omp::DataSharingClauseType::FirstPrivate;
2260 if (!needsFirstprivate)
2261 return insertBarrier
2265 llvm::BasicBlock *copyBlock =
2266 splitBB(builder,
true,
"omp.private.copy");
2269 for (
auto [decl, moldVar, llvmVar] :
2270 llvm::zip_equal(privateDecls, moldVars, llvmPrivateVars)) {
2271 if (decl.getDataSharingType() != omp::DataSharingClauseType::FirstPrivate)
2275 Region ©Region = decl.getCopyRegion();
2278 builder, moduleTranslation, decl.getCopyMoldArg(), moldVar);
2280 builder, moduleTranslation, decl.getCopyPrivateArg(), llvmVar);
2282 moduleTranslation.
mapValue(decl.getCopyMoldArg(), copyMoldVar);
2285 moduleTranslation.
mapValue(decl.getCopyPrivateArg(), copyPrivateVar);
2289 moduleTranslation)))
2290 return decl.emitError(
"failed to inline `copy` region of `omp.private`");
2302 return insertBarrier
2316 llvm::transform(mlirPrivateVars, moldVars.begin(), [&](
mlir::Value mlirVar) {
2318 llvm::Value *moldVar = findAssociatedValue(
2319 mlirVar, builder, moduleTranslation, mappedPrivateVars);
2324 llvmPrivateVars, privateDecls, insertBarrier,
2328template <
typename T>
2336 std::back_inserter(privateCleanupRegions),
2337 [](omp::PrivateClauseOp privatizer) {
2338 return &privatizer.getDeallocRegion();
2342 privateVarsInfo.
llvmVars, moduleTranslation,
2343 builder,
"omp.private.dealloc",
2345 return mlir::emitError(loc,
"failed to inline `dealloc` region of an "
2346 "`omp.private` op in");
2351 for (
auto [privDecl, llvmPrivVar, blockArg] :
2355 ompBuilder->createOMPFreeShared(
2356 builder, llvmPrivVar,
2357 moduleTranslation.
convertType(privDecl.getType()));
2361 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2364 ompBuilder->createOMPFree(ompLoc, allocation.allocatedPtr,
2365 allocation.allocator);
2377 if (mlir::isa<omp::CancelOp, omp::CancellationPointOp>(child))
2394 llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder::InsertPointTy allocaIP,
2396 bool isWorksharing =
false);
2404 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2405 using StorableBodyGenCallbackTy =
2406 llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
2408 auto sectionsOp = cast<omp::SectionsOp>(opInst);
2414 assert(isByRef.size() == sectionsOp.getNumReductionVars());
2418 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
2422 sectionsOp.getNumReductionVars());
2426 cast<omp::BlockArgOpenMPOpInterface>(opInst).getReductionBlockArgs();
2429 sectionsOp, reductionArgs, builder, moduleTranslation, allocaIP,
2430 reductionDecls, privateReductionVariables, reductionVariableMap,
2434 bool isTaskReductionMod =
2435 sectionsOp.getReductionMod() == omp::ReductionModifier::task &&
2436 sectionsOp.getNumReductionVars() > 0;
2441 auto sectionOp = dyn_cast<omp::SectionOp>(op);
2445 Region ®ion = sectionOp.getRegion();
2446 auto sectionCB = [§ionsOp, ®ion, &builder, &moduleTranslation](
2447 InsertPointTy allocaIP, InsertPointTy codeGenIP,
2449 builder.restoreIP(codeGenIP);
2456 sectionsOp.getRegion().getNumArguments());
2457 for (
auto [sectionsArg, sectionArg] : llvm::zip_equal(
2458 sectionsOp.getRegion().getArguments(), region.
getArguments())) {
2459 llvm::Value *llvmVal = moduleTranslation.
lookupValue(sectionsArg);
2461 moduleTranslation.
mapValue(sectionArg, llvmVal);
2468 sectionCBs.push_back(sectionCB);
2474 if (sectionCBs.empty())
2482 if (isTaskReductionMod &&
2484 "__omp_taskred_mod_", builder, allocaIP,
2485 moduleTranslation,
true,
2487 return sectionsOp.emitError(
2488 "failed to emit task reduction modifier initialization");
2490 assert(isa<omp::SectionOp>(*sectionsOp.getRegion().op_begin()));
2495 auto privCB = [&](InsertPointTy, InsertPointTy codeGenIP, llvm::Value &,
2496 llvm::Value &vPtr, llvm::Value *&replacementValue)
2497 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
2498 replacementValue = &vPtr;
2504 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
2508 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2509 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2511 ompLoc, allocaIP, sectionCBs, privCB, finiCB, isCancellable,
2512 sectionsOp.getNowait());
2517 builder.restoreIP(*afterIP);
2520 if (isTaskReductionMod)
2526 sectionsOp, builder, moduleTranslation, allocaIP, reductionDecls,
2527 privateReductionVariables, isByRef, sectionsOp.getNowait());
2534 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2541 assert(isByRef.size() == scopeOp.getNumReductionVars());
2545 moduleTranslation, privateVarsInfo)))
2550 InsertPointTy privateAllocaIP =
2554 scopeOp.getNumReductionVars());
2558 cast<omp::BlockArgOpenMPOpInterface>(*scopeOp).getReductionBlockArgs();
2560 if (scopeOp.getAllocateVars().empty()) {
2562 scopeOp, builder, moduleTranslation, privateVarsInfo, privateAllocaIP);
2568 scopeOp, reductionArgs, builder, moduleTranslation, privateAllocaIP,
2569 reductionDecls, privateReductionVariables, reductionVariableMap,
2574 [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
2576 if (!scopeOp.getAllocateVars().empty()) {
2580 scopeOp, builder, moduleTranslation, privateVarsInfo, privateAllocaIP,
2581 nullptr, codeGenIP);
2583 return llvm::make_error<PreviouslyReportedError>();
2584 builder.SetInsertPoint(afterAllocas.get()->getTerminator());
2586 builder.restoreIP(codeGenIP);
2593 return llvm::make_error<PreviouslyReportedError>();
2596 scopeOp, builder, moduleTranslation, privateVarsInfo.
mlirVars,
2598 scopeOp.getPrivateNeedsBarrier())))
2599 return llvm::make_error<PreviouslyReportedError>();
2606 auto finiCB = [&](InsertPointTy codeGenIP) -> llvm::Error {
2607 InsertPointTy oldIP = builder.saveIP();
2608 builder.restoreIP(codeGenIP);
2610 scopeOp.getLoc(), privateVarsInfo)))
2611 return llvm::make_error<PreviouslyReportedError>();
2612 builder.restoreIP(oldIP);
2613 return llvm::Error::success();
2616 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2617 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2618 ompBuilder->createScope(ompLoc, bodyCB, finiCB, scopeOp.getNowait());
2623 builder.restoreIP(*afterIP);
2627 scopeOp, builder, moduleTranslation, privateAllocaIP, reductionDecls,
2628 privateReductionVariables, isByRef, scopeOp.getNowait(),
2636 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2637 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2642 auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
2644 builder.restoreIP(codegenIP);
2646 builder, moduleTranslation)
2649 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
2653 std::optional<ArrayAttr> cpFuncs = singleOp.getCopyprivateSyms();
2656 for (
size_t i = 0, e = cpVars.size(); i < e; ++i) {
2657 llvmCPVars.push_back(moduleTranslation.
lookupValue(cpVars[i]));
2659 singleOp, cast<SymbolRefAttr>((*cpFuncs)[i]));
2660 llvmCPFuncs.push_back(
2664 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2666 ompLoc, bodyCB, finiCB, singleOp.getNowait(), llvmCPVars,
2672 builder.restoreIP(*afterIP);
2676static omp::DistributeOp
2680 omp::DistributeOp distOp;
2681 WalkResult walk = teamsOp.getRegion().walk([&](omp::DistributeOp op) {
2687 if (walk.wasInterrupted() || !distOp)
2691 llvm::cast<mlir::omp::BlockArgOpenMPOpInterface>(teamsOp.getOperation());
2695 for (
auto ra : iface.getReductionBlockArgs())
2696 for (
auto &use : ra.getUses()) {
2697 auto *useOp = use.getOwner();
2699 if (mlir::isa<LLVM::DbgDeclareOp, LLVM::DbgValueOp>(useOp)) {
2700 debugUses.push_back(useOp);
2703 if (!distOp->isProperAncestor(useOp))
2710 for (
auto *use : debugUses)
2719 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2724 unsigned numReductionVars = op.getNumReductionVars();
2728 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
2734 if (doTeamsReduction) {
2735 isByRef =
getIsByRef(op.getReductionByref());
2737 assert(isByRef.size() == op.getNumReductionVars());
2740 llvm::cast<omp::BlockArgOpenMPOpInterface>(*op).getReductionBlockArgs();
2745 op, reductionArgs, builder, moduleTranslation, allocaIP,
2746 reductionDecls, privateReductionVariables, reductionVariableMap,
2751 auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
2754 moduleTranslation, allocaIP.getNodeParent(), deallocBlocks);
2755 builder.restoreIP(codegenIP);
2761 llvm::Value *numTeamsLower =
nullptr;
2762 if (
Value numTeamsLowerVar = op.getNumTeamsLower())
2763 numTeamsLower = moduleTranslation.
lookupValue(numTeamsLowerVar);
2765 llvm::Value *numTeamsUpper =
nullptr;
2766 if (!op.getNumTeamsUpperVars().empty())
2767 numTeamsUpper = moduleTranslation.
lookupValue(op.getNumTeams(0));
2769 llvm::Value *threadLimit =
nullptr;
2770 if (!op.getThreadLimitVars().empty())
2771 threadLimit = moduleTranslation.
lookupValue(op.getThreadLimit(0));
2773 llvm::Value *ifExpr =
nullptr;
2774 if (
Value ifVar = op.getIfExpr())
2777 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2778 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2780 ompLoc, bodyCB, numTeamsLower, numTeamsUpper, threadLimit, ifExpr);
2785 builder.restoreIP(*afterIP);
2786 if (doTeamsReduction) {
2789 op, builder, moduleTranslation, allocaIP, reductionDecls,
2790 privateReductionVariables, isByRef,
2796static llvm::omp::RTLDependenceKindTy
2799 case mlir::omp::ClauseTaskDepend::taskdependin:
2800 return llvm::omp::RTLDependenceKindTy::DepIn;
2804 case mlir::omp::ClauseTaskDepend::taskdependout:
2805 case mlir::omp::ClauseTaskDepend::taskdependinout:
2806 return llvm::omp::RTLDependenceKindTy::DepInOut;
2807 case mlir::omp::ClauseTaskDepend::taskdependmutexinoutset:
2808 return llvm::omp::RTLDependenceKindTy::DepMutexInOutSet;
2809 case mlir::omp::ClauseTaskDepend::taskdependinoutset:
2810 return llvm::omp::RTLDependenceKindTy::DepInOutSet;
2812 llvm_unreachable(
"unhandled depend kind");
2816 std::optional<ArrayAttr> dependKinds,
OperandRange dependVars,
2819 if (dependVars.empty())
2821 for (
auto dep : llvm::zip(dependVars, dependKinds->getValue())) {
2823 cast<mlir::omp::ClauseTaskDependAttr>(std::get<1>(dep)).getValue();
2825 llvm::Value *depVal = moduleTranslation.
lookupValue(std::get<0>(dep));
2826 llvm::OpenMPIRBuilder::DependData dd(type, depVal->getType(), depVal);
2827 dds.emplace_back(dd);
2839 llvm::IRBuilderBase &llvmBuilder, llvm::OpenMPIRBuilder &ompBuilder,
2841 auto finiCB = [&](llvm::OpenMPIRBuilder::InsertPointTy ip) -> llvm::Error {
2842 llvm::IRBuilderBase::InsertPointGuard guard(llvmBuilder);
2846 llvmBuilder.restoreIP(ip);
2852 cancelTerminators.push_back(llvmBuilder.CreateBr(ip.getNodeParent()));
2853 return llvm::Error::success();
2858 ompBuilder.pushFinalizationCB(
2868 llvm::OpenMPIRBuilder &ompBuilder,
2869 llvm::BasicBlock *afterBB) {
2870 ompBuilder.popFinalizationCB();
2871 llvm::BasicBlock *constructFini = afterBB->getSinglePredecessor();
2872 for (llvm::UncondBrInst *cancelBranch : cancelTerminators)
2873 cancelBranch->setSuccessor(constructFini);
2879class TaskContextStructManager {
2881 TaskContextStructManager(llvm::IRBuilderBase &builder,
2882 LLVM::ModuleTranslation &moduleTranslation,
2883 MutableArrayRef<omp::PrivateClauseOp> privateDecls)
2884 : builder{builder}, moduleTranslation{moduleTranslation},
2885 privateDecls{privateDecls} {}
2891 void generateTaskContextStruct();
2897 void createGEPsToPrivateVars();
2903 SmallVector<llvm::Value *>
2904 createGEPsToPrivateVars(llvm::Value *altStructPtr)
const;
2907 void freeStructPtr();
2909 MutableArrayRef<llvm::Value *> getLLVMPrivateVarGEPs() {
2910 return llvmPrivateVarGEPs;
2913 llvm::Value *getStructPtr() {
return structPtr; }
2916 llvm::IRBuilderBase &builder;
2917 LLVM::ModuleTranslation &moduleTranslation;
2918 MutableArrayRef<omp::PrivateClauseOp> privateDecls;
2921 SmallVector<llvm::Type *> privateVarTypes;
2925 SmallVector<llvm::Value *> llvmPrivateVarGEPs;
2928 llvm::Value *structPtr =
nullptr;
2930 llvm::Type *structTy =
nullptr;
2942 llvm::SmallVector<llvm::Value *> lowerBounds;
2943 llvm::SmallVector<llvm::Value *> upperBounds;
2944 llvm::SmallVector<llvm::Value *> steps;
2945 llvm::SmallVector<llvm::Value *> trips;
2947 llvm::Value *totalTrips;
2950 IteratorInfo(mlir::omp::IteratorOp itersOp,
2951 mlir::LLVM::ModuleTranslation &moduleTranslation,
2952 llvm::IRBuilderBase &builder) {
2953 dims = itersOp.getLoopLowerBounds().size();
2954 lowerBounds.resize(dims);
2955 upperBounds.resize(dims);
2959 for (
unsigned d = 0; d < dims; ++d) {
2961 moduleTranslation.
lookupValue(itersOp.getLoopLowerBounds()[d]);
2963 moduleTranslation.
lookupValue(itersOp.getLoopUpperBounds()[d]);
2965 moduleTranslation.
lookupValue(itersOp.getLoopSteps()[d]);
2966 assert(lb && ub && st &&
2967 "Expect lowerBounds, upperBounds, and steps in IteratorOp");
2968 assert((!llvm::isa<llvm::ConstantInt>(st) ||
2969 !llvm::cast<llvm::ConstantInt>(st)->isZero()) &&
2970 "Expect non-zero step in IteratorOp");
2972 lowerBounds[d] = lb;
2973 upperBounds[d] = ub;
2978 llvm::Type *countTy =
2979 builder.getIntNTy(lb->getType()->getIntegerBitWidth() + 1);
2980 llvm::Value *start = builder.CreateSExt(lb, countTy);
2981 llvm::Value *stop = builder.CreateSExt(ub, countTy);
2982 llvm::Value *step = builder.CreateSExt(st, countTy);
2983 llvm::Value *count =
2985 builder, start, stop, step,
true,
2987 trips[d] = builder.CreateZExtOrTrunc(count, builder.getInt64Ty());
2990 totalTrips = llvm::ConstantInt::get(builder.getInt64Ty(), 1);
2991 for (
unsigned d = 0; d < dims; ++d)
2992 totalTrips = builder.CreateMul(totalTrips, trips[d]);
2995 unsigned getDims()
const {
return dims; }
2996 llvm::ArrayRef<llvm::Value *> getLowerBounds()
const {
return lowerBounds; }
2997 llvm::ArrayRef<llvm::Value *> getUpperBounds()
const {
return upperBounds; }
2998 llvm::ArrayRef<llvm::Value *> getSteps()
const {
return steps; }
2999 llvm::ArrayRef<llvm::Value *> getTrips()
const {
return trips; }
3000 llvm::Value *getTotalTrips()
const {
return totalTrips; }
3005void TaskContextStructManager::generateTaskContextStruct() {
3006 if (privateDecls.empty())
3008 privateVarTypes.reserve(privateDecls.size());
3010 for (omp::PrivateClauseOp &privOp : privateDecls) {
3013 if (!privOp.readsFromMold())
3015 Type mlirType = privOp.getType();
3016 privateVarTypes.push_back(moduleTranslation.
convertType(mlirType));
3019 if (privateVarTypes.empty())
3022 structTy = llvm::StructType::get(moduleTranslation.
getLLVMContext(),
3025 llvm::DataLayout dataLayout = builder.getDataLayout();
3026 llvm::Type *intPtrTy = builder.getIntPtrTy(dataLayout);
3027 llvm::Value *allocSize =
3028 builder.CreateTypeSize(intPtrTy, dataLayout.getTypeAllocSize(structTy));
3031 structPtr = builder.CreateMalloc(intPtrTy, allocSize,
3033 "omp.task.context_ptr");
3036SmallVector<llvm::Value *> TaskContextStructManager::createGEPsToPrivateVars(
3037 llvm::Value *altStructPtr)
const {
3038 SmallVector<llvm::Value *> ret;
3041 ret.reserve(privateDecls.size());
3042 llvm::Value *zero = builder.getInt32(0);
3044 for (
auto privDecl : privateDecls) {
3045 if (!privDecl.readsFromMold()) {
3047 ret.push_back(
nullptr);
3050 llvm::Value *iVal = builder.getInt32(i);
3051 llvm::Value *gep = builder.CreateGEP(structTy, altStructPtr, {zero, iVal});
3058void TaskContextStructManager::createGEPsToPrivateVars() {
3060 assert(privateVarTypes.empty());
3064 llvmPrivateVarGEPs = createGEPsToPrivateVars(structPtr);
3067void TaskContextStructManager::freeStructPtr() {
3071 llvm::IRBuilderBase::InsertPointGuard guard{builder};
3073 builder.SetInsertPoint(builder.GetInsertBlock()->getTerminator());
3074 builder.CreateFree(structPtr);
3078 llvm::OpenMPIRBuilder &ompBuilder,
3079 llvm::Value *affinityList, llvm::Value *
index,
3080 llvm::Value *addr, llvm::Value *len) {
3081 llvm::StructType *kmpTaskAffinityInfoTy =
3082 ompBuilder.getKmpTaskAffinityInfoTy();
3083 llvm::Value *entry = builder.CreateInBoundsGEP(
3084 kmpTaskAffinityInfoTy, affinityList,
index,
"omp.affinity.entry");
3086 addr = builder.CreatePtrToInt(addr, kmpTaskAffinityInfoTy->getElementType(0));
3087 len = builder.CreateIntCast(len, kmpTaskAffinityInfoTy->getElementType(1),
3089 llvm::Value *flags = builder.getInt32(0);
3091 builder.CreateStore(addr,
3092 builder.CreateStructGEP(kmpTaskAffinityInfoTy, entry, 0));
3093 builder.CreateStore(len,
3094 builder.CreateStructGEP(kmpTaskAffinityInfoTy, entry, 1));
3095 builder.CreateStore(flags,
3096 builder.CreateStructGEP(kmpTaskAffinityInfoTy, entry, 2));
3100 llvm::IRBuilderBase &builder,
3102 llvm::Value *affinityList) {
3103 for (
auto [i, affinityVar] : llvm::enumerate(affinityVars)) {
3104 auto entryOp = affinityVar.getDefiningOp<mlir::omp::AffinityEntryOp>();
3105 assert(entryOp &&
"affinity item must be omp.affinity_entry");
3107 llvm::Value *addr = moduleTranslation.
lookupValue(entryOp.getAddr());
3108 llvm::Value *len = moduleTranslation.
lookupValue(entryOp.getLen());
3109 assert(addr && len &&
"expect affinity addr and len to be non-null");
3111 affinityList, builder.getInt64(i), addr, len);
3116 llvm::Value *linearIV, IteratorInfo &iterInfo,
mlir::Region &iteratorRegion,
3119 llvm::Value *tmp = linearIV;
3120 for (
int d = (
int)iterInfo.getDims() - 1; d >= 0; --d) {
3121 llvm::Value *trip = iterInfo.getTrips()[d];
3123 llvm::Value *idx = builder.CreateURem(tmp, trip);
3125 tmp = builder.CreateUDiv(tmp, trip);
3129 builder.CreateZExtOrTrunc(idx, iterInfo.getLowerBounds()[d]->getType());
3130 llvm::Value *physIV = builder.CreateAdd(
3131 iterInfo.getLowerBounds()[d],
3132 builder.CreateMul(idx, iterInfo.getSteps()[d]),
"omp.it.phys_iv");
3139 moduleTranslation.
mapBlock(&entryBlock, builder.GetInsertBlock());
3140 return moduleTranslation.
convertBlock(entryBlock,
true,
3148 llvm::BasicBlock *continuation =
3149 splitBB(builder,
true,
"omp.iterator.region.cont");
3150 llvm::Instruction *sourceBranch = builder.GetInsertBlock()->getTerminator();
3154 llvm::BasicBlock::Create(builder.getContext(),
"omp.iterator.region",
3155 continuation->getParent(), continuation));
3156 sourceBranch->setSuccessor(0, moduleTranslation.
lookupBlock(&entryBlock));
3159 llvm::IRBuilderBase::InsertPointGuard guard(builder);
3160 if (failed(moduleTranslation.
convertBlock(*block, block->isEntryBlock(),
3162 return mlir::failure();
3163 if (isa<omp::YieldOp>(block->getTerminator()))
3164 builder.CreateBr(continuation);
3168 builder.SetInsertPoint(continuation);
3169 return mlir::success();
3175static mlir::LogicalResult
3178 IteratorInfo &iterInfo, llvm::StringRef loopName,
3182 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
3184 auto bodyGen = [&](llvm::OpenMPIRBuilder::InsertPointTy bodyIP,
3185 llvm::Value *linearIV) -> llvm::Error {
3186 llvm::IRBuilderBase::InsertPointGuard guard(builder);
3187 builder.restoreIP(bodyIP);
3190 moduleTranslation))) {
3191 return llvm::make_error<llvm::StringError>(
3192 "failed to convert iterator region", llvm::inconvertibleErrorCode());
3195 mlir::omp::YieldOp yield = itersOp.getYieldOp();
3196 assert(yield && yield.getResults().size() == 1 &&
3197 "expect omp.yield in iterator region to have one result");
3199 genStoreEntry(linearIV, yield);
3205 return llvm::Error::success();
3208 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
3210 loc, iterInfo.getTotalTrips(), bodyGen, loopName);
3214 builder.restoreIP(*afterIP);
3216 return mlir::success();
3219static mlir::LogicalResult
3222 llvm::OpenMPIRBuilder::AffinityData &ad) {
3224 if (taskOp.getAffinityVars().empty() && taskOp.getIterated().empty()) {
3227 return mlir::success();
3231 llvm::StructType *kmpTaskAffinityInfoTy =
3234 auto allocateAffinityList = [&](llvm::Value *count) -> llvm::Value * {
3235 llvm::IRBuilderBase::InsertPointGuard guard(builder);
3236 if (llvm::isa<llvm::Constant>(count) || llvm::isa<llvm::Argument>(count))
3238 return builder.CreateAlloca(kmpTaskAffinityInfoTy, count,
3239 "omp.affinity_list");
3242 auto createAffinity =
3243 [&](llvm::Value *count,
3244 llvm::Value *info) -> llvm::OpenMPIRBuilder::AffinityData {
3245 llvm::OpenMPIRBuilder::AffinityData ad{};
3246 ad.Count = builder.CreateTrunc(count, builder.getInt32Ty());
3248 builder.CreatePointerBitCastOrAddrSpaceCast(info, builder.getPtrTy(0));
3252 if (!taskOp.getAffinityVars().empty()) {
3253 llvm::Value *count = llvm::ConstantInt::get(
3254 builder.getInt64Ty(), taskOp.getAffinityVars().size());
3255 llvm::Value *list = allocateAffinityList(count);
3258 ads.emplace_back(createAffinity(count, list));
3261 if (!taskOp.getIterated().empty()) {
3262 for (
auto [i, iter] : llvm::enumerate(taskOp.getIterated())) {
3263 auto itersOp = iter.getDefiningOp<omp::IteratorOp>();
3264 assert(itersOp &&
"iterated value must be defined by omp.iterator");
3265 IteratorInfo iterInfo(itersOp, moduleTranslation, builder);
3266 llvm::Value *affList = allocateAffinityList(iterInfo.getTotalTrips());
3268 itersOp, builder, moduleTranslation, iterInfo,
"iterator",
3269 [&](llvm::Value *linearIV, mlir::omp::YieldOp yield) {
3270 auto entryOp = yield.getResults()[0]
3271 .getDefiningOp<mlir::omp::AffinityEntryOp>();
3272 assert(entryOp &&
"expect yield produce an affinity entry");
3279 affList, linearIV, addr, len);
3281 return llvm::failure();
3282 ads.emplace_back(createAffinity(iterInfo.getTotalTrips(), affList));
3286 llvm::Value *totalAffinityCount = builder.getInt32(0);
3287 for (
const auto &affinity : ads)
3288 totalAffinityCount = builder.CreateAdd(
3290 builder.CreateIntCast(affinity.Count, builder.getInt32Ty(),
3293 llvm::Value *affinityInfo = ads.front().Info;
3294 if (ads.size() > 1) {
3295 llvm::StructType *kmpTaskAffinityInfoTy =
3297 llvm::Value *affinityInfoElemSize = builder.getInt64(
3298 moduleTranslation.
getLLVMModule()->getDataLayout().getTypeAllocSize(
3299 kmpTaskAffinityInfoTy));
3301 llvm::Value *packedAffinityInfo = allocateAffinityList(totalAffinityCount);
3302 llvm::Value *packedAffinityInfoOffset = builder.getInt32(0);
3303 for (
const auto &affinity : ads) {
3304 llvm::Value *affinityCount = builder.CreateIntCast(
3305 affinity.Count, builder.getInt32Ty(),
false);
3306 llvm::Value *affinityCountInt64 = builder.CreateIntCast(
3307 affinityCount, builder.getInt64Ty(),
false);
3308 llvm::Value *affinityInfoSize =
3309 builder.CreateMul(affinityCountInt64, affinityInfoElemSize);
3311 llvm::Value *packedAffinityInfoIndex = builder.CreateIntCast(
3312 packedAffinityInfoOffset, kmpTaskAffinityInfoTy->getElementType(0),
3314 packedAffinityInfoIndex = builder.CreateInBoundsGEP(
3315 kmpTaskAffinityInfoTy, packedAffinityInfo, packedAffinityInfoIndex);
3317 builder.CreateMemCpy(
3318 packedAffinityInfoIndex, llvm::Align(1),
3319 builder.CreatePointerBitCastOrAddrSpaceCast(
3320 affinity.Info, builder.getPtrTy(packedAffinityInfoIndex->getType()
3321 ->getPointerAddressSpace())),
3322 llvm::Align(1), affinityInfoSize);
3324 packedAffinityInfoOffset =
3325 builder.CreateAdd(packedAffinityInfoOffset, affinityCount);
3328 affinityInfo = packedAffinityInfo;
3331 ad.Count = totalAffinityCount;
3332 ad.Info = affinityInfo;
3334 return mlir::success();
3340static mlir::LogicalResult
3343 std::optional<ArrayAttr> dependIteratedKinds,
3344 llvm::IRBuilderBase &builder,
3346 llvm::OpenMPIRBuilder::DependenciesInfo &taskDeps) {
3347 if (dependIterated.empty()) {
3350 return mlir::success();
3354 llvm::Type *dependInfoTy = ompBuilder.DependInfo;
3355 unsigned numLocator = dependVars.size();
3358 llvm::Value *totalCount =
3359 llvm::ConstantInt::get(builder.getInt64Ty(), numLocator);
3362 for (
auto iter : dependIterated) {
3363 auto itersOp = iter.getDefiningOp<mlir::omp::IteratorOp>();
3364 assert(itersOp &&
"depend_iterated value must be defined by omp.iterator");
3365 iterInfos.emplace_back(itersOp, moduleTranslation, builder);
3367 builder.CreateAdd(totalCount, iterInfos.back().getTotalTrips());
3372 llvm::DataLayout dataLayout = builder.getDataLayout();
3373 llvm::Value *allocSize = builder.CreateTypeSize(
3374 ompBuilder.SizeTy, dataLayout.getTypeAllocSize(dependInfoTy));
3375 llvm::Value *depArray =
3376 builder.CreateMalloc(ompBuilder.SizeTy, allocSize, totalCount,
3377 nullptr,
".dep.arr.addr");
3380 if (numLocator > 0) {
3383 for (
auto [i, dd] : llvm::enumerate(dds)) {
3384 llvm::Value *idx = llvm::ConstantInt::get(builder.getInt64Ty(), i);
3385 llvm::Value *entry =
3386 builder.CreateInBoundsGEP(dependInfoTy, depArray, idx);
3387 ompBuilder.emitTaskDependency(builder, entry, dd);
3392 llvm::Value *offset =
3393 llvm::ConstantInt::get(builder.getInt64Ty(), numLocator);
3394 for (
auto [i, iterInfo] : llvm::enumerate(iterInfos)) {
3395 auto kindAttr = cast<mlir::omp::ClauseTaskDependAttr>(
3396 dependIteratedKinds->getValue()[i]);
3397 llvm::omp::RTLDependenceKindTy rtlKind =
3400 auto itersOp = dependIterated[i].getDefiningOp<mlir::omp::IteratorOp>();
3402 itersOp, builder, moduleTranslation, iterInfo,
"dep_iterator",
3403 [&](llvm::Value *linearIV, mlir::omp::YieldOp yield) {
3405 moduleTranslation.
lookupValue(yield.getResults()[0]);
3406 llvm::Value *idx = builder.CreateAdd(offset, linearIV);
3407 llvm::Value *entry =
3408 builder.CreateInBoundsGEP(dependInfoTy, depArray, idx);
3409 ompBuilder.emitTaskDependency(
3411 llvm::OpenMPIRBuilder::DependData{rtlKind, addr->getType(),
3414 return mlir::failure();
3417 offset = builder.CreateAdd(offset, iterInfo.getTotalTrips());
3420 taskDeps.DepArray = depArray;
3421 taskDeps.NumDeps = builder.CreateTrunc(totalCount, builder.getInt32Ty());
3422 return mlir::success();
3429 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
3434 TaskContextStructManager taskStructMgr{builder, moduleTranslation,
3446 InsertPointTy allocaIP =
3451 assert(builder.GetInsertPoint() == builder.GetInsertBlock()->end());
3452 llvm::BasicBlock *taskStartBlock = llvm::BasicBlock::Create(
3453 builder.getContext(),
"omp.task.start",
3454 builder.GetInsertBlock()->getParent());
3455 llvm::Instruction *branchToTaskStartBlock = builder.CreateBr(taskStartBlock);
3456 builder.SetInsertPoint(branchToTaskStartBlock);
3459 llvm::BasicBlock *copyBlock =
3460 splitBB(builder,
true,
"omp.private.copy");
3461 llvm::BasicBlock *initBlock =
3462 splitBB(builder,
true,
"omp.private.init");
3478 moduleTranslation, allocaIP.getNodeParent(), deallocBlocks);
3481 builder.SetInsertPoint(initBlock->getTerminator());
3484 taskStructMgr.generateTaskContextStruct();
3491 taskStructMgr.createGEPsToPrivateVars();
3493 for (
auto [privDecl, mlirPrivVar, blockArg, llvmPrivateVarAlloc] :
3496 taskStructMgr.getLLVMPrivateVarGEPs())) {
3498 if (!privDecl.readsFromMold())
3500 assert(llvmPrivateVarAlloc &&
3501 "reads from mold so shouldn't have been skipped");
3504 initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar,
3505 blockArg, llvmPrivateVarAlloc, initBlock);
3506 if (!privateVarOrErr)
3507 return handleError(privateVarOrErr, *taskOp.getOperation());
3516 [[maybe_unused]] llvm::Value *llvmPrivateVar = llvmPrivateVarAlloc;
3517 if ((privateVarOrErr.get() != llvmPrivateVarAlloc) &&
3518 !mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
3519 builder.CreateStore(privateVarOrErr.get(), llvmPrivateVarAlloc);
3521 llvmPrivateVar = builder.CreateLoad(privateVarOrErr.get()->getType(),
3522 llvmPrivateVarAlloc);
3524 assert(llvmPrivateVar->getType() ==
3525 moduleTranslation.
convertType(blockArg.getType()));
3535 taskOp, builder, moduleTranslation, privateVarsInfo.
mlirVars,
3536 taskStructMgr.getLLVMPrivateVarGEPs(), privateVarsInfo.
privatizers,
3537 taskOp.getPrivateNeedsBarrier())))
3538 return llvm::failure();
3540 llvm::OpenMPIRBuilder::AffinityData ad;
3542 return llvm::failure();
3552 taskOp.getOperation(), taskOp.getInReductionSyms(),
"omp.task",
3553 "in_reduction", inRedDecls)))
3556 inRedOrigPtrs.reserve(inRedDecls.size());
3557 for (
Value v : taskOp.getInReductionVars())
3558 inRedOrigPtrs.push_back(moduleTranslation.
lookupValue(v));
3561 builder.SetInsertPoint(taskStartBlock);
3564 [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
3569 moduleTranslation, allocaIP.getNodeParent(), deallocBlocks);
3572 builder.restoreIP(codegenIP);
3574 llvm::BasicBlock *privInitBlock =
nullptr;
3576 for (
auto [i, zip] : llvm::enumerate(llvm::zip_equal(
3579 auto [blockArg, privDecl, mlirPrivVar] = zip;
3581 if (privDecl.readsFromMold())
3584 llvm::IRBuilderBase::InsertPointGuard guard(builder);
3585 llvm::Type *llvmAllocType =
3586 moduleTranslation.
convertType(privDecl.getType());
3587 builder.SetInsertPoint(allocaIP.getNodeParent()->getTerminator());
3588 llvm::Value *llvmPrivateVar = builder.CreateAlloca(
3589 llvmAllocType,
nullptr,
"omp.private.alloc");
3592 initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar,
3593 blockArg, llvmPrivateVar, privInitBlock);
3594 if (!privateVarOrError)
3595 return privateVarOrError.takeError();
3596 moduleTranslation.
mapValue(blockArg, privateVarOrError.get());
3597 privateVarsInfo.
llvmVars[i] = privateVarOrError.get();
3600 taskStructMgr.createGEPsToPrivateVars();
3601 for (
auto [i, llvmPrivVar] :
3602 llvm::enumerate(taskStructMgr.getLLVMPrivateVarGEPs())) {
3604 assert(privateVarsInfo.
llvmVars[i] &&
3605 "This is added in the loop above");
3608 privateVarsInfo.
llvmVars[i] = llvmPrivVar;
3613 for (
auto [blockArg, llvmPrivateVar, privateDecl] :
3617 if (!privateDecl.readsFromMold())
3620 if (!mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
3621 llvmPrivateVar = builder.CreateLoad(
3622 moduleTranslation.
convertType(blockArg.getType()), llvmPrivateVar);
3624 assert(llvmPrivateVar->getType() ==
3625 moduleTranslation.
convertType(blockArg.getType()));
3626 moduleTranslation.
mapValue(blockArg, llvmPrivateVar);
3637 if (!inRedDecls.empty()) {
3638 auto iface = cast<omp::BlockArgOpenMPOpInterface>(taskOp.getOperation());
3641 llvm::LLVMContext &llvmCtx = m->getContext();
3642 llvm::OpenMPIRBuilder::LocationDescription bodyLoc(builder);
3643 uint32_t srcLocSize;
3644 llvm::Constant *srcLocStr =
3645 ompB.getOrCreateSrcLocStr(bodyLoc, srcLocSize);
3646 llvm::Value *bodyIdent = ompB.getOrCreateIdent(srcLocStr, srcLocSize);
3649 ompB.updateToLocation(bodyLoc);
3650 llvm::Value *bodyGtid = ompB.getOrCreateThreadID(bodyIdent);
3651 llvm::FunctionCallee getThData = ompB.getOrCreateRuntimeFunction(
3652 *m, llvm::omp::OMPRTL___kmpc_task_reduction_get_th_data);
3653 llvm::Type *ptrTy = llvm::PointerType::getUnqual(llvmCtx);
3654 llvm::Value *nullDesc = llvm::ConstantPointerNull::get(ptrTy);
3656 for (
auto [blockArg, origPtr] :
3657 llvm::zip_equal(inRedBlockArgs, inRedOrigPtrs)) {
3664 llvm::Value *lookupPtr = origPtr;
3665 if (
auto *origPtrTy =
3666 llvm::dyn_cast<llvm::PointerType>(lookupPtr->getType());
3667 origPtrTy && origPtrTy->getAddressSpace() != 0)
3668 lookupPtr = builder.CreateAddrSpaceCast(lookupPtr, ptrTy);
3669 llvm::Value *priv = builder.CreateCall(
3670 getThData, {bodyGtid, nullDesc, lookupPtr},
"omp.inred.priv");
3671 if (
auto *argPtrTy = llvm::dyn_cast<llvm::PointerType>(
3672 moduleTranslation.
convertType(blockArg.getType()));
3673 argPtrTy && argPtrTy->getAddressSpace() != 0)
3674 priv = builder.CreateAddrSpaceCast(priv, argPtrTy);
3675 moduleTranslation.
mapValue(blockArg, priv);
3680 taskOp.getRegion(),
"omp.task.region", builder, moduleTranslation);
3681 if (failed(
handleError(continuationBlockOrError, *taskOp)))
3682 return llvm::make_error<PreviouslyReportedError>();
3684 builder.SetInsertPoint(continuationBlockOrError.get()->getTerminator());
3687 taskOp.getLoc(), privateVarsInfo)))
3688 return llvm::make_error<PreviouslyReportedError>();
3691 taskStructMgr.freeStructPtr();
3693 return llvm::Error::success();
3702 llvm::omp::Directive::OMPD_taskgroup);
3704 llvm::OpenMPIRBuilder::DependenciesInfo dependencies;
3705 if (failed(
buildDependData(taskOp.getDependVars(), taskOp.getDependKinds(),
3706 taskOp.getDependIterated(),
3707 taskOp.getDependIteratedKinds(), builder,
3708 moduleTranslation, dependencies)))
3711 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
3712 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
3714 ompLoc, allocaIP, deallocBlocks, bodyCB, !taskOp.getUntied(),
3716 moduleTranslation.
lookupValue(taskOp.getIfExpr()), dependencies, ad,
3717 taskOp.getMergeable(),
3718 moduleTranslation.
lookupValue(taskOp.getEventHandle()),
3719 moduleTranslation.
lookupValue(taskOp.getPriority()),
3720 taskOp.getThreadset() == omp::ThreadsetPolicy::omp_pool);
3727 afterIP->getNodeParent());
3729 builder.restoreIP(*afterIP);
3731 if (dependencies.DepArray)
3732 builder.CreateFree(dependencies.DepArray);
3741 llvm::IRBuilderBase &builder,
3749 loopWrapperOp.getRegion(),
"omp.taskloop.wrapper.region", builder,
3752 if (failed(
handleError(continuationBlockOrError, opInst)))
3755 builder.SetInsertPoint(continuationBlockOrError.get());
3763static llvm::Expected<llvm::Value *>
3766 llvm::IRBuilderBase &builder) {
3767 if (llvm::Value *mapped = moduleTranslation.
lookupValue(value))
3772 return llvm::make_error<llvm::StringError>(
3773 "value is a block argument and is not mapped",
3774 llvm::inconvertibleErrorCode());
3776 return llvm::make_error<llvm::StringError>(
3777 "unsupported op defining taskloop loop bound",
3778 llvm::inconvertibleErrorCode());
3788 if (!operandOrError)
3789 return operandOrError.takeError();
3790 moduleTranslation.
mapValue(operand, *operandOrError);
3791 mappingsToRemove.push_back(operand);
3795 return llvm::make_error<llvm::StringError>(
3796 "failed to convert op defining taskloop loop bound",
3797 llvm::inconvertibleErrorCode());
3800 assert(
result &&
"expected conversion of loop bound op to produce a value");
3804 mappingsToRemove.push_back(resultValue);
3806 for (
Value mappedValue : mappingsToRemove)
3815 llvm::Value *&lbVal, llvm::Value *&ubVal,
3816 llvm::Value *&stepVal) {
3824 return firstLbOrErr.takeError();
3826 llvm::Type *boundType = (*firstLbOrErr)->getType();
3827 ubVal = builder.getIntN(boundType->getIntegerBitWidth(), 1);
3828 if (loopOp.getCollapseNumLoops() > 1) {
3846 for (uint64_t i = 0; i < loopOp.getCollapseNumLoops(); i++) {
3848 i == 0 ? std::move(firstLbOrErr)
3852 return lbOrErr.takeError();
3854 upperBounds[i], moduleTranslation, builder);
3856 return ubOrErr.takeError();
3860 return stepOrErr.takeError();
3862 llvm::Value *loopLb = *lbOrErr;
3863 llvm::Value *loopUb = *ubOrErr;
3864 llvm::Value *loopStep = *stepOrErr;
3870 llvm::Value *loopLbMinusOne = builder.CreateSub(
3871 loopLb, builder.getIntN(boundType->getIntegerBitWidth(), 1));
3872 llvm::Value *loopUbMinusOne = builder.CreateSub(
3873 loopUb, builder.getIntN(boundType->getIntegerBitWidth(), 1));
3874 llvm::Value *boundsCmp = builder.CreateICmpSLT(loopLb, loopUb);
3875 llvm::Value *ubMinusLb = builder.CreateSub(loopUb, loopLbMinusOne);
3876 llvm::Value *lbMinusUb = builder.CreateSub(loopLb, loopUbMinusOne);
3877 llvm::Value *loopTripCount =
3878 builder.CreateSelect(boundsCmp, ubMinusLb, lbMinusUb);
3879 loopTripCount = builder.CreateBinaryIntrinsic(
3880 llvm::Intrinsic::abs, loopTripCount, builder.getFalse());
3884 llvm::Value *loopTripCountDivStep =
3885 builder.CreateSDiv(loopTripCount, loopStep);
3886 loopTripCountDivStep = builder.CreateBinaryIntrinsic(
3887 llvm::Intrinsic::abs, loopTripCountDivStep, builder.getFalse());
3888 llvm::Value *loopTripCountRem =
3889 builder.CreateSRem(loopTripCount, loopStep);
3890 loopTripCountRem = builder.CreateBinaryIntrinsic(
3891 llvm::Intrinsic::abs, loopTripCountRem, builder.getFalse());
3892 llvm::Value *needsRoundUp = builder.CreateICmpNE(
3894 builder.getIntN(loopTripCountRem->getType()->getIntegerBitWidth(),
3897 builder.CreateAdd(loopTripCountDivStep,
3898 builder.CreateZExtOrTrunc(
3899 needsRoundUp, loopTripCountDivStep->getType()));
3900 ubVal = builder.CreateMul(ubVal, loopTripCount);
3902 lbVal = builder.getIntN(boundType->getIntegerBitWidth(), 1);
3903 stepVal = builder.getIntN(boundType->getIntegerBitWidth(), 1);
3908 return ubOrErr.takeError();
3912 return stepOrErr.takeError();
3913 lbVal = *firstLbOrErr;
3915 stepVal = *stepOrErr;
3918 assert(lbVal !=
nullptr &&
"Expected value for lbVal");
3919 assert(ubVal !=
nullptr &&
"Expected value for ubVal");
3920 assert(stepVal !=
nullptr &&
"Expected value for stepVal");
3921 return llvm::Error::success();
3927 llvm::IRBuilderBase &builder,
3929 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
3931 omp::TaskloopWrapperOp loopWrapperOp = contextOp.getLoopOp();
3939 TaskContextStructManager taskStructMgr{builder, moduleTranslation,
3943 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
3946 assert(builder.GetInsertPoint() == builder.GetInsertBlock()->end());
3947 llvm::BasicBlock *taskloopStartBlock = llvm::BasicBlock::Create(
3948 builder.getContext(),
"omp.taskloop.wrapper.start",
3949 builder.GetInsertBlock()->getParent());
3950 llvm::Instruction *branchToTaskloopStartBlock =
3951 builder.CreateBr(taskloopStartBlock);
3952 builder.SetInsertPoint(branchToTaskloopStartBlock);
3954 llvm::BasicBlock *copyBlock =
3955 splitBB(builder,
true,
"omp.private.copy");
3956 llvm::BasicBlock *initBlock =
3957 splitBB(builder,
true,
"omp.private.init");
3960 moduleTranslation, allocaIP.getNodeParent(), deallocBlocks);
3963 builder.SetInsertPoint(initBlock->getTerminator());
3966 taskStructMgr.generateTaskContextStruct();
3967 taskStructMgr.createGEPsToPrivateVars();
3969 llvmFirstPrivateVars.resize(privateVarsInfo.
blockArgs.size());
3971 for (
auto [i, zip] : llvm::enumerate(llvm::zip_equal(
3973 privateVarsInfo.
blockArgs, taskStructMgr.getLLVMPrivateVarGEPs()))) {
3974 auto [privDecl, mlirPrivVar, blockArg, llvmPrivateVarAlloc] = zip;
3976 if (!privDecl.readsFromMold())
3978 assert(llvmPrivateVarAlloc &&
3979 "reads from mold so shouldn't have been skipped");
3982 initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar,
3983 blockArg, llvmPrivateVarAlloc, initBlock);
3984 if (!privateVarOrErr)
3985 return handleError(privateVarOrErr, *contextOp.getOperation());
3987 llvmFirstPrivateVars[i] = privateVarOrErr.get();
3989 llvm::IRBuilderBase::InsertPointGuard guard(builder);
3990 builder.SetInsertPoint(builder.GetInsertBlock()->getTerminator());
3992 [[maybe_unused]] llvm::Value *llvmPrivateVar = llvmPrivateVarAlloc;
3993 if ((privateVarOrErr.get() != llvmPrivateVarAlloc) &&
3994 !mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
3995 builder.CreateStore(privateVarOrErr.get(), llvmPrivateVarAlloc);
3997 llvmPrivateVar = builder.CreateLoad(privateVarOrErr.get()->getType(),
3998 llvmPrivateVarAlloc);
4000 assert(llvmPrivateVar->getType() ==
4001 moduleTranslation.
convertType(blockArg.getType()));
4007 contextOp, builder, moduleTranslation, privateVarsInfo.
mlirVars,
4008 taskStructMgr.getLLVMPrivateVarGEPs(), privateVarsInfo.
privatizers,
4009 contextOp.getPrivateNeedsBarrier())))
4010 return llvm::failure();
4020 contextOp.getOperation(), contextOp.getReductionSyms(),
4021 "omp.taskloop.context",
"reduction", redDecls)))
4025 contextOp.getOperation(), contextOp.getInReductionSyms(),
4026 "omp.taskloop.context",
"in_reduction", inRedDecls)))
4032 redOrigPtrs.reserve(redDecls.size());
4033 for (
Value v : contextOp.getReductionVars())
4034 redOrigPtrs.push_back(moduleTranslation.
lookupValue(v));
4036 inRedOrigPtrs.reserve(inRedDecls.size());
4037 for (
Value v : contextOp.getInReductionVars())
4038 inRedOrigPtrs.push_back(moduleTranslation.
lookupValue(v));
4042 builder.SetInsertPoint(taskloopStartBlock);
4044 llvm::OpenMPIRBuilder &ompBuilderRef = *moduleTranslation.
getOpenMPBuilder();
4051 bool implicitTaskgroup = !redDecls.empty();
4052 llvm::Value *redDesc =
nullptr;
4053 if (implicitTaskgroup) {
4054 llvm::OpenMPIRBuilder::LocationDescription redLoc(builder);
4055 uint32_t srcLocSize;
4056 llvm::Constant *srcLocStr =
4057 ompBuilderRef.getOrCreateSrcLocStr(redLoc, srcLocSize);
4058 llvm::Value *ident = ompBuilderRef.getOrCreateIdent(srcLocStr, srcLocSize);
4061 ompBuilderRef.updateToLocation(redLoc);
4062 llvm::Value *outerGtid = ompBuilderRef.getOrCreateThreadID(ident);
4063 llvm::FunctionCallee taskgroupFn = ompBuilderRef.getOrCreateRuntimeFunction(
4064 *module, llvm::omp::OMPRTL___kmpc_taskgroup);
4065 builder.CreateCall(taskgroupFn, {ident, outerGtid});
4068 "__omp_taskloop_taskred_", builder,
4069 allocaIP, moduleTranslation);
4074 auto loopOp = cast<omp::LoopNestOp>(loopWrapperOp.getWrappedLoop());
4075 llvm::Value *lbVal =
nullptr;
4076 llvm::Value *ubVal =
nullptr;
4077 llvm::Value *stepVal =
nullptr;
4079 loopOp, builder, moduleTranslation, lbVal, ubVal, stepVal))
4083 [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
4088 moduleTranslation, allocaIP.getNodeParent(), deallocBlocks);
4091 builder.restoreIP(codegenIP);
4093 llvm::BasicBlock *privInitBlock =
nullptr;
4095 for (
auto [i, zip] : llvm::enumerate(llvm::zip_equal(
4098 auto [blockArg, privDecl, mlirPrivVar] = zip;
4100 if (privDecl.readsFromMold())
4103 llvm::IRBuilderBase::InsertPointGuard guard(builder);
4104 llvm::Type *llvmAllocType =
4105 moduleTranslation.
convertType(privDecl.getType());
4106 builder.SetInsertPoint(allocaIP.getNodeParent()->getTerminator());
4107 llvm::Value *llvmPrivateVar = builder.CreateAlloca(
4108 llvmAllocType,
nullptr,
"omp.private.alloc");
4111 initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar,
4112 blockArg, llvmPrivateVar, privInitBlock);
4113 if (!privateVarOrError)
4114 return privateVarOrError.takeError();
4115 moduleTranslation.
mapValue(blockArg, privateVarOrError.get());
4116 privateVarsInfo.
llvmVars[i] = privateVarOrError.get();
4119 taskStructMgr.createGEPsToPrivateVars();
4120 for (
auto [i, llvmPrivVar] :
4121 llvm::enumerate(taskStructMgr.getLLVMPrivateVarGEPs())) {
4123 assert(privateVarsInfo.
llvmVars[i] &&
4124 "This is added in the loop above");
4127 privateVarsInfo.
llvmVars[i] = llvmPrivVar;
4132 for (
auto [blockArg, llvmPrivateVar, privateDecl] :
4136 if (!privateDecl.readsFromMold())
4139 if (!mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
4140 llvmPrivateVar = builder.CreateLoad(
4141 moduleTranslation.
convertType(blockArg.getType()), llvmPrivateVar);
4143 assert(llvmPrivateVar->getType() ==
4144 moduleTranslation.
convertType(blockArg.getType()));
4145 moduleTranslation.
mapValue(blockArg, llvmPrivateVar);
4157 if (!redDecls.empty() || !inRedDecls.empty()) {
4159 cast<omp::BlockArgOpenMPOpInterface>(contextOp.getOperation());
4162 llvm::LLVMContext &llvmCtx = m->getContext();
4163 llvm::OpenMPIRBuilder::LocationDescription bodyLoc(builder);
4164 uint32_t srcLocSize;
4165 llvm::Constant *srcLocStr =
4166 ompB.getOrCreateSrcLocStr(bodyLoc, srcLocSize);
4167 llvm::Value *bodyIdent = ompB.getOrCreateIdent(srcLocStr, srcLocSize);
4170 ompB.updateToLocation(bodyLoc);
4171 llvm::Value *bodyGtid = ompB.getOrCreateThreadID(bodyIdent);
4172 llvm::FunctionCallee getThData = ompB.getOrCreateRuntimeFunction(
4173 *m, llvm::omp::OMPRTL___kmpc_task_reduction_get_th_data);
4174 llvm::Type *ptrTy = llvm::PointerType::getUnqual(llvmCtx);
4184 auto remapReductionArg = [&](
BlockArgument blockArg, llvm::Value *desc,
4185 llvm::Value *origPtr,
4186 const llvm::Twine &name) {
4187 if (
auto *origPtrTy =
4188 llvm::dyn_cast<llvm::PointerType>(origPtr->getType());
4189 origPtrTy && origPtrTy->getAddressSpace() != 0)
4190 origPtr = builder.CreateAddrSpaceCast(origPtr, ptrTy);
4192 builder.CreateCall(getThData, {bodyGtid, desc, origPtr}, name);
4193 if (
auto *argPtrTy = llvm::dyn_cast<llvm::PointerType>(
4195 argPtrTy && argPtrTy->getAddressSpace() != 0)
4196 priv = builder.CreateAddrSpaceCast(priv, argPtrTy);
4197 moduleTranslation.
mapValue(blockArg, priv);
4201 for (
auto [blockArg, origPtr] :
4202 llvm::zip_equal(redBlockArgs, redOrigPtrs))
4203 remapReductionArg(blockArg, redDesc, origPtr,
"omp.taskred.priv");
4205 llvm::Value *nullDesc = llvm::ConstantPointerNull::get(ptrTy);
4206 for (
auto [blockArg, origPtr] :
4207 llvm::zip_equal(inRedBlockArgs, inRedOrigPtrs))
4208 remapReductionArg(blockArg, nullDesc, origPtr,
"omp.inred.priv");
4214 contextOp.getRegion(),
"omp.taskloop.context.region", builder,
4217 if (failed(
handleError(continuationBlockOrError, opInst)))
4218 return llvm::make_error<PreviouslyReportedError>();
4220 builder.SetInsertPoint(continuationBlockOrError.get()->getTerminator());
4228 contextOp.getLoc(), privateVarsInfo)))
4229 return llvm::make_error<PreviouslyReportedError>();
4232 taskStructMgr.freeStructPtr();
4234 return llvm::Error::success();
4240 auto taskDupCB = [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
4241 llvm::Value *destPtr, llvm::Value *srcPtr)
4243 llvm::IRBuilderBase::InsertPointGuard guard(builder);
4244 builder.restoreIP(codegenIP);
4247 builder.getPtrTy(srcPtr->getType()->getPointerAddressSpace());
4249 builder.CreateLoad(ptrTy, srcPtr,
"omp.taskloop.context.src");
4251 TaskContextStructManager &srcStructMgr = taskStructMgr;
4252 TaskContextStructManager destStructMgr(builder, moduleTranslation,
4254 destStructMgr.generateTaskContextStruct();
4255 llvm::Value *dest = destStructMgr.getStructPtr();
4256 dest->setName(
"omp.taskloop.context.dest");
4257 builder.CreateStore(dest, destPtr);
4260 srcStructMgr.createGEPsToPrivateVars(src);
4262 destStructMgr.createGEPsToPrivateVars(dest);
4265 for (
auto [privDecl, mold, blockArg, llvmPrivateVarAlloc] :
4266 llvm::zip_equal(privateVarsInfo.
privatizers, srcGEPs,
4269 if (!privDecl.readsFromMold())
4271 assert(llvmPrivateVarAlloc &&
4272 "reads from mold so shouldn't have been skipped");
4275 builder, moduleTranslation, privDecl.getInitMoldArg(), mold);
4277 builder, moduleTranslation, privDecl, moldArg, blockArg,
4278 llvmPrivateVarAlloc, builder.GetInsertBlock());
4279 if (!privateVarOrErr)
4280 return privateVarOrErr.takeError();
4289 [[maybe_unused]] llvm::Value *llvmPrivateVar = llvmPrivateVarAlloc;
4290 if ((privateVarOrErr.get() != llvmPrivateVarAlloc) &&
4291 !mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
4292 builder.CreateStore(privateVarOrErr.get(), llvmPrivateVarAlloc);
4294 llvmPrivateVar = builder.CreateLoad(privateVarOrErr.get()->getType(),
4295 llvmPrivateVarAlloc);
4297 assert(llvmPrivateVar->getType() ==
4298 moduleTranslation.
convertType(blockArg.getType()));
4306 moduleTranslation, srcGEPs, destGEPs,
4308 contextOp.getPrivateNeedsBarrier())))
4309 return llvm::make_error<PreviouslyReportedError>();
4311 return builder.saveIP();
4319 llvm::Value *ifCond =
nullptr;
4320 llvm::Value *grainsize =
nullptr;
4322 mlir::Value grainsizeVal = contextOp.getGrainsize();
4323 mlir::Value numTasksVal = contextOp.getNumTasks();
4324 if (
Value ifVar = contextOp.getIfExpr())
4327 grainsize = moduleTranslation.
lookupValue(grainsizeVal);
4329 }
else if (numTasksVal) {
4330 grainsize = moduleTranslation.
lookupValue(numTasksVal);
4334 llvm::OpenMPIRBuilder::TaskDupCallbackTy taskDupOrNull =
nullptr;
4335 if (taskStructMgr.getStructPtr())
4336 taskDupOrNull = taskDupCB;
4346 llvm::omp::Directive::OMPD_taskgroup);
4348 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4349 bool effectiveNoGroup = contextOp.getNogroup() || implicitTaskgroup;
4350 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
4352 ompLoc, allocaIP, deallocBlocks, bodyCB, loopInfo, lbVal, ubVal,
4353 stepVal, contextOp.getUntied(), ifCond, grainsize, effectiveNoGroup,
4354 sched, moduleTranslation.
lookupValue(contextOp.getFinal()),
4355 contextOp.getMergeable(),
4356 moduleTranslation.
lookupValue(contextOp.getPriority()),
4357 loopOp.getCollapseNumLoops(), taskDupOrNull,
4358 taskStructMgr.getStructPtr(),
4359 contextOp.getThreadset() == omp::ThreadsetPolicy::omp_pool);
4365 afterIP->getNodeParent());
4367 builder.restoreIP(*afterIP);
4371 if (implicitTaskgroup) {
4372 llvm::OpenMPIRBuilder::LocationDescription endLoc(builder);
4373 uint32_t srcLocSize;
4374 llvm::Constant *srcLocStr =
4375 ompBuilder.getOrCreateSrcLocStr(endLoc, srcLocSize);
4376 llvm::Value *ident = ompBuilder.getOrCreateIdent(srcLocStr, srcLocSize);
4379 ompBuilder.updateToLocation(endLoc);
4380 llvm::Value *outerGtid = ompBuilder.getOrCreateThreadID(ident);
4381 llvm::FunctionCallee endTgFn = ompBuilder.getOrCreateRuntimeFunction(
4383 llvm::omp::OMPRTL___kmpc_end_taskgroup);
4384 builder.CreateCall(endTgFn, {ident, outerGtid});
4395static llvm::Function *
4398 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
4399 llvm::LLVMContext &ctx = llvmModule->getContext();
4400 llvm::Type *voidTy = llvm::Type::getVoidTy(ctx);
4401 llvm::Type *ptrTy = llvm::PointerType::getUnqual(ctx);
4402 llvm::FunctionType *fty =
4403 llvm::FunctionType::get(voidTy, {ptrTy, ptrTy},
false);
4404 llvm::Function *fn =
4405 llvm::Function::Create(fty, llvm::GlobalValue::InternalLinkage,
4406 baseName +
".red.init", llvmModule);
4407 fn->setDoesNotRecurse();
4408 fn->getArg(0)->setName(
"priv");
4409 fn->getArg(1)->setName(
"orig");
4411 llvm::BasicBlock *entry = llvm::BasicBlock::Create(ctx,
"entry", fn);
4412 llvm::IRBuilder<>
b(entry);
4419 Value moldArg = decl.getInitializerMoldArg();
4420 llvm::Value *origVal = fn->getArg(1);
4421 if (!isa<LLVM::LLVMPointerType>(moldArg.
getType()))
4423 fn->getArg(1),
"omp.orig");
4424 moduleTranslation.
mapValue(moldArg, origVal);
4427 "omp.taskred.init",
b, moduleTranslation,
4429 fn->eraseFromParent();
4432 assert(phis.size() == 1 &&
4433 "expected one value yielded from reduction initializer");
4434 b.CreateStore(phis[0], fn->getArg(0));
4437 moduleTranslation.
forgetMapping(decl.getInitializerRegion());
4445static llvm::Function *
4448 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
4449 llvm::LLVMContext &ctx = llvmModule->getContext();
4450 llvm::Type *voidTy = llvm::Type::getVoidTy(ctx);
4451 llvm::Type *ptrTy = llvm::PointerType::getUnqual(ctx);
4452 llvm::FunctionType *fty =
4453 llvm::FunctionType::get(voidTy, {ptrTy, ptrTy},
false);
4454 llvm::Function *fn =
4455 llvm::Function::Create(fty, llvm::GlobalValue::InternalLinkage,
4456 baseName +
".red.comb", llvmModule);
4457 fn->setDoesNotRecurse();
4458 fn->getArg(0)->setName(
"lhs");
4459 fn->getArg(1)->setName(
"rhs");
4461 llvm::BasicBlock *entry = llvm::BasicBlock::Create(ctx,
"entry", fn);
4462 llvm::IRBuilder<>
b(entry);
4464 llvm::Type *elemTy = moduleTranslation.
convertType(decl.getType());
4465 Block &combBlock = decl.getReductionRegion().
front();
4467 "expected two arguments in declare_reduction combiner");
4468 llvm::Value *lhsVal =
b.CreateLoad(elemTy, fn->getArg(0),
"omp.lhs");
4469 llvm::Value *rhsVal =
b.CreateLoad(elemTy, fn->getArg(1),
"omp.rhs");
4475 "omp.taskred.comb",
b, moduleTranslation,
4477 fn->eraseFromParent();
4480 assert(phis.size() == 1 &&
4481 "expected one value yielded from reduction combiner");
4482 b.CreateStore(phis[0], fn->getArg(0));
4508 llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder::InsertPointTy allocaIP,
4510 bool isWorksharing) {
4511 assert(redDecls.size() == origPtrs.size() &&
4512 "expected one orig pointer per reduction decl");
4514 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
4515 llvm::LLVMContext &ctx = llvmModule->getContext();
4516 const llvm::DataLayout &dl = llvmModule->getDataLayout();
4518 llvm::Type *ptrTy = llvm::PointerType::getUnqual(ctx);
4519 llvm::Type *i32Ty = llvm::Type::getInt32Ty(ctx);
4520 llvm::Type *sizeTy =
4521 llvm::Type::getIntNTy(ctx, dl.getPointerSizeInBits(0));
4525 llvm::StructType *redInputTy =
4526 llvm::StructType::getTypeByName(ctx,
"kmp_taskred_input_t");
4528 redInputTy = llvm::StructType::create(
4529 ctx, {ptrTy, ptrTy, sizeTy, ptrTy, ptrTy, ptrTy, i32Ty},
4530 "kmp_taskred_input_t");
4532 unsigned n = redDecls.size();
4533 llvm::ArrayType *arrTy = llvm::ArrayType::get(redInputTy, n);
4536 llvm::AllocaInst *arrAlloca;
4538 llvm::IRBuilderBase::InsertPointGuard guard(builder);
4539 builder.restoreIP(allocaIP);
4541 builder.CreateAlloca(arrTy,
nullptr,
".taskred.input");
4545 llvm::Value *zero = builder.getInt32(0);
4546 for (
unsigned i = 0; i < n; ++i) {
4547 omp::DeclareReductionOp decl = redDecls[i];
4548 llvm::Value *orig = origPtrs[i];
4549 if (
auto *origPtrTy = llvm::dyn_cast<llvm::PointerType>(orig->getType());
4550 origPtrTy && origPtrTy->getAddressSpace() != 0)
4551 orig = builder.CreateAddrSpaceCast(orig, ptrTy);
4552 llvm::Type *elemTy = moduleTranslation.
convertType(decl.getType());
4553 uint64_t size = dl.getTypeAllocSize(elemTy).getFixedValue();
4555 std::string baseName =
4556 (llvm::Twine(helperNamePrefix) + decl.getSymName()).str();
4557 llvm::Function *initFn =
4559 llvm::Function *combFn =
4561 if (!initFn || !combFn)
4563 llvm::Value *elemPtr = builder.CreateInBoundsGEP(
4564 arrTy, arrAlloca, {zero, builder.getInt32(i)},
".taskred.elem");
4565 auto storeField = [&](
unsigned fieldIdx, llvm::Value *val) {
4566 llvm::Value *fieldPtr =
4567 builder.CreateStructGEP(redInputTy, elemPtr, fieldIdx);
4568 builder.CreateStore(val, fieldPtr);
4570 storeField(0, orig);
4571 storeField(1, orig);
4572 storeField(2, llvm::ConstantInt::get(sizeTy, size));
4573 storeField(3, initFn);
4574 storeField(4, llvm::ConstantPointerNull::get(ptrTy));
4575 storeField(5, combFn);
4576 storeField(6, llvm::ConstantInt::get(i32Ty, 0));
4580 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4581 uint32_t srcLocSize;
4582 llvm::Constant *srcLocStr =
4583 ompBuilder->getOrCreateSrcLocStr(ompLoc, srcLocSize);
4584 llvm::Value *ident = ompBuilder->getOrCreateIdent(srcLocStr, srcLocSize);
4585 ompBuilder->updateToLocation(ompLoc);
4586 llvm::Value *gtid = ompBuilder->getOrCreateThreadID(ident);
4590 llvm::FunctionCallee modInit = ompBuilder->getOrCreateRuntimeFunction(
4591 *llvmModule, llvm::omp::OMPRTL___kmpc_taskred_modifier_init);
4592 return builder.CreateCall(modInit,
4594 builder.getInt32(isWorksharing ? 1 : 0),
4595 builder.getInt32(n), arrAlloca},
4599 llvm::FunctionCallee taskredInit = ompBuilder->getOrCreateRuntimeFunction(
4600 *llvmModule, llvm::omp::OMPRTL___kmpc_taskred_init);
4601 return builder.CreateCall(taskredInit, {gtid, builder.getInt32(n), arrAlloca},
4612 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
4613 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4614 uint32_t srcLocSize;
4615 llvm::Constant *srcLocStr =
4616 ompBuilder->getOrCreateSrcLocStr(ompLoc, srcLocSize);
4617 llvm::Value *ident = ompBuilder->getOrCreateIdent(srcLocStr, srcLocSize);
4618 ompBuilder->updateToLocation(ompLoc);
4619 llvm::Value *gtid = ompBuilder->getOrCreateThreadID(ident);
4620 llvm::FunctionCallee fini = ompBuilder->getOrCreateRuntimeFunction(
4621 *llvmModule, llvm::omp::OMPRTL___kmpc_task_reduction_modifier_fini);
4622 builder.CreateCall(fini,
4623 {ident, gtid, builder.getInt32(isWorksharing ? 1 : 0)});
4630 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4639 if (
auto syms = tgOp.getTaskReductionSyms()) {
4640 redDecls.reserve(syms->size());
4641 for (
auto sym : syms->getAsRange<SymbolRefAttr>()) {
4645 return tgOp.emitError()
4646 <<
"failed to resolve task_reduction declare_reduction symbol "
4647 << sym.getRootReference() <<
" in omp.taskgroup";
4648 if (decl.getInitializerRegion().front().getNumArguments() != 1)
4649 return tgOp.emitError(
"not yet implemented: task_reduction with "
4650 "two-argument initializer in omp.taskgroup");
4651 if (!decl.getCleanupRegion().empty())
4652 return tgOp.emitError(
"not yet implemented: task_reduction with "
4653 "cleanup region in omp.taskgroup");
4654 if (decl.getReductionRegion().empty())
4655 return tgOp.emitError(
"task_reduction declare_reduction is missing a "
4657 redDecls.push_back(decl);
4662 [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
4664 builder.restoreIP(codegenIP);
4666 if (!redDecls.empty()) {
4668 origPtrs.reserve(redDecls.size());
4669 for (
Value v : tgOp.getTaskReductionVars())
4670 origPtrs.push_back(moduleTranslation.
lookupValue(v));
4672 builder, allocaIP, moduleTranslation))
4673 return llvm::createStringError(
4674 llvm::inconvertibleErrorCode(),
4675 "failed to emit task_reduction initialization for omp.taskgroup");
4683 for (
auto [i, blockArg] :
4684 llvm::enumerate(tgOp.getRegion().getArguments())) {
4686 moduleTranslation.
lookupValue(tgOp.getTaskReductionVars()[i]);
4687 moduleTranslation.
mapValue(blockArg, orig);
4691 builder, moduleTranslation)
4696 InsertPointTy allocaIP =
4698 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4699 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
4701 ompLoc, allocaIP, deallocBlocks, bodyCB);
4706 builder.restoreIP(*afterIP);
4713 if (!initOp.getDependVars().empty() || initOp.getDependKinds() ||
4714 !initOp.getDependIterated().empty() || initOp.getDependIteratedKinds())
4715 return initOp.emitError()
4716 <<
"not yet implemented: Unhandled clause depend in "
4717 << omp::InteropInitOp::getOperationName() <<
" operation";
4720 llvm::Value *interopVar =
4721 moduleTranslation.
lookupValue(initOp.getInteropVar());
4722 llvm::Value *device = initOp.getDevice()
4723 ? moduleTranslation.
lookupValue(initOp.getDevice())
4727 llvm::Value *numDeps = llvm::ConstantInt::get(builder.getInt32Ty(), 0);
4728 llvm::Value *depArray = llvm::ConstantPointerNull::get(builder.getPtrTy());
4729 bool hasNowait = initOp.getNowait();
4736 bool hasTarget =
false, hasTargetSync =
false;
4738 switch (cast<omp::InteropTypeAttr>(typeAttr).getValue()) {
4739 case omp::InteropType::target:
4742 case omp::InteropType::targetsync:
4743 hasTargetSync =
true;
4747 llvm::omp::OMPInteropType interopType =
4748 (!hasTarget && hasTargetSync) ? llvm::omp::OMPInteropType::TargetSync
4749 : llvm::omp::OMPInteropType::Target;
4750 ompBuilder->createOMPInteropInit(builder, interopVar, interopType, device,
4751 numDeps, depArray, hasNowait);
4757 llvm::IRBuilderBase &builder,
4759 if (!destroyOp.getDependVars().empty() || destroyOp.getDependKinds() ||
4760 !destroyOp.getDependIterated().empty() ||
4761 destroyOp.getDependIteratedKinds())
4762 return destroyOp.emitError()
4763 <<
"not yet implemented: Unhandled clause depend in "
4764 << omp::InteropDestroyOp::getOperationName() <<
" operation";
4767 llvm::Value *interopVar =
4768 moduleTranslation.
lookupValue(destroyOp.getInteropVar());
4769 llvm::Value *device =
4770 destroyOp.getDevice()
4771 ? moduleTranslation.
lookupValue(destroyOp.getDevice())
4774 llvm::Value *numDeps = llvm::ConstantInt::get(builder.getInt32Ty(), 0);
4775 llvm::Value *depArray = llvm::ConstantPointerNull::get(builder.getPtrTy());
4776 bool hasNowait = destroyOp.getNowait();
4778 ompBuilder->createOMPInteropDestroy(builder, interopVar, device, numDeps,
4779 depArray, hasNowait);
4786 if (!useOp.getDependVars().empty() || useOp.getDependKinds() ||
4787 !useOp.getDependIterated().empty() || useOp.getDependIteratedKinds())
4788 return useOp.emitError()
4789 <<
"not yet implemented: Unhandled clause depend in "
4790 << omp::InteropUseOp::getOperationName() <<
" operation";
4793 llvm::Value *interopVar =
4794 moduleTranslation.
lookupValue(useOp.getInteropVar());
4795 llvm::Value *device = useOp.getDevice()
4796 ? moduleTranslation.
lookupValue(useOp.getDevice())
4799 llvm::Value *numDeps = llvm::ConstantInt::get(builder.getInt32Ty(), 0);
4800 llvm::Value *depArray = llvm::ConstantPointerNull::get(builder.getPtrTy());
4801 bool hasNowait = useOp.getNowait();
4803 ompBuilder->createOMPInteropUse(builder, interopVar, device, numDeps,
4804 depArray, hasNowait);
4814 llvm::OpenMPIRBuilder::DependenciesInfo dds;
4816 twOp.getDependVars(), twOp.getDependKinds(), twOp.getDependIterated(),
4817 twOp.getDependIteratedKinds(), builder, moduleTranslation, dds))) {
4824 builder.CreateFree(dds.DepArray);
4835 auto wsloopOp = cast<omp::WsloopOp>(opInst);
4839 auto loopOp = cast<omp::LoopNestOp>(wsloopOp.getWrappedLoop());
4841 assert(isByRef.size() == wsloopOp.getNumReductionVars());
4845 wsloopOp.getScheduleKind().value_or(omp::ClauseScheduleKind::Static);
4848 llvm::Value *step = moduleTranslation.
lookupValue(loopOp.getLoopSteps()[0]);
4849 llvm::Type *ivType = step->getType();
4850 llvm::Value *chunk =
nullptr;
4851 if (wsloopOp.getScheduleChunk()) {
4852 llvm::Value *chunkVar =
4853 moduleTranslation.
lookupValue(wsloopOp.getScheduleChunk());
4854 chunk = builder.CreateSExtOrTrunc(chunkVar, ivType);
4857 omp::DistributeOp distributeOp =
nullptr;
4858 llvm::Value *distScheduleChunk =
nullptr;
4859 bool hasDistSchedule =
false;
4860 if (llvm::isa_and_present<omp::DistributeOp>(opInst.
getParentOp())) {
4861 distributeOp = cast<omp::DistributeOp>(opInst.
getParentOp());
4862 hasDistSchedule = distributeOp.getDistScheduleStatic();
4863 if (distributeOp.getDistScheduleChunkSize()) {
4864 llvm::Value *chunkVar = moduleTranslation.
lookupValue(
4865 distributeOp.getDistScheduleChunkSize());
4866 distScheduleChunk = builder.CreateSExtOrTrunc(chunkVar, ivType);
4876 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
4879 llvm::BasicBlock *allocaBlock = allocaIP.getNodeParent();
4881 wsloopOp.getNumReductionVars());
4884 wsloopOp, builder, moduleTranslation, privateVarsInfo, allocaIP);
4891 cast<omp::BlockArgOpenMPOpInterface>(opInst).getReductionBlockArgs();
4896 moduleTranslation, allocaIP, reductionDecls,
4897 privateReductionVariables, reductionVariableMap,
4898 deferredStores, isByRef)))
4907 wsloopOp, builder, moduleTranslation, privateVarsInfo.
mlirVars,
4909 wsloopOp.getPrivateNeedsBarrier())))
4912 assert(afterAllocas.get()->getSinglePredecessor());
4913 if (failed(initReductionVars(wsloopOp, reductionArgs, builder,
4915 afterAllocas.get()->getSinglePredecessor(),
4916 reductionDecls, privateReductionVariables,
4917 reductionVariableMap, isByRef, deferredStores)))
4923 bool isTaskReductionMod =
4924 wsloopOp.getReductionMod() == omp::ReductionModifier::task &&
4925 wsloopOp.getNumReductionVars() > 0;
4926 if (isTaskReductionMod &&
4928 "__omp_taskred_mod_", builder, allocaIP,
4929 moduleTranslation,
true,
4931 return wsloopOp.emitError(
4932 "failed to emit task reduction modifier initialization");
4935 bool isOrdered = wsloopOp.getOrdered().has_value();
4936 std::optional<omp::ScheduleModifier> scheduleMod = wsloopOp.getScheduleMod();
4937 bool isSimd = wsloopOp.getScheduleSimd();
4938 bool loopNeedsBarrier = !wsloopOp.getNowait();
4943 llvm::omp::WorksharingLoopType workshareLoopType =
4944 llvm::isa_and_present<omp::DistributeOp>(opInst.
getParentOp())
4945 ? llvm::omp::WorksharingLoopType::DistributeForStaticLoop
4946 : llvm::omp::WorksharingLoopType::ForStaticLoop;
4950 llvm::omp::Directive::OMPD_for);
4952 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4955 LinearClauseProcessor linearClauseProcessor;
4957 if (!wsloopOp.getLinearVars().empty()) {
4958 auto linearVarTypes = wsloopOp.getLinearVarTypes().value();
4960 linearClauseProcessor.registerType(moduleTranslation, linearVarType);
4962 for (
auto [idx, linearVar] : llvm::enumerate(wsloopOp.getLinearVars())) {
4964 linearClauseProcessor.createLinearVar(
4965 builder, allocaIP, privateVarsInfo.
privatizers[privIdx],
4967 privateVarsInfo.
llvmVars[privIdx], idx);
4969 for (
mlir::Value linearStep : wsloopOp.getLinearStepVars())
4970 linearClauseProcessor.initLinearStep(moduleTranslation, linearStep);
4974 wsloopOp.getRegion(),
"omp.wsloop.region", builder, moduleTranslation);
4982 if (!wsloopOp.getLinearVars().empty()) {
4984 linearClauseProcessor.initLinearVar(builder, moduleTranslation,
4985 loopInfo->getPreheader()),
4988 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterBarrierIP =
4990 builder, llvm::omp::OMPD_barrier);
4993 builder.restoreIP(*afterBarrierIP);
4994 if (failed(
handleError(linearClauseProcessor.updateLinearVar(
4995 builder, moduleTranslation, loopInfo->getBody(),
4996 loopInfo->getIndVar()),
4999 linearClauseProcessor.splitLinearFiniBB(builder, loopInfo->getExit());
5002 builder.SetInsertPoint((*regionBlock)->begin());
5005 bool noLoopMode =
false;
5006 omp::TargetOp targetOp = wsloopOp->getParentOfType<mlir::omp::TargetOp>();
5008 targetOp.getKernelType() == omp::TargetExecMode::spmd_no_loop) {
5010 cast<omp::ComposableOpInterface>(*targetOp).findCapturedOp();
5014 if (loopOp == targetCapturedOp)
5019 allocaIP = allocaBlock->getFirstInsertionPt();
5020 llvm::OpenMPIRBuilder::InsertPointOrErrorTy wsloopIP =
5021 ompBuilder->applyWorkshareLoop(
5022 ompLoc.DL, loopInfo, allocaIP, loopNeedsBarrier,
5023 convertToScheduleKind(schedule), chunk, isSimd,
5024 scheduleMod == omp::ScheduleModifier::monotonic,
5025 scheduleMod == omp::ScheduleModifier::nonmonotonic, isOrdered,
5026 workshareLoopType, noLoopMode, hasDistSchedule, distScheduleChunk,
5027 !wsloopOp.getLinearVars().empty());
5034 llvm::BasicBlock *wsloopContinuationBB = wsloopIP->getNodeParent();
5037 if (!wsloopOp.getLinearVars().empty()) {
5038 llvm::OpenMPIRBuilder::InsertPointTy oldIP = builder.saveIP();
5039 assert(loopInfo->getLastIter() &&
5040 "`lastiter` in CanonicalLoopInfo is nullptr");
5041 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterBarrierIP =
5042 linearClauseProcessor.finalizeLinearVar(builder, moduleTranslation,
5043 loopInfo->getLastIter());
5047 builder.restoreIP(oldIP);
5054 if (isTaskReductionMod)
5060 wsloopOp, builder, moduleTranslation, allocaIP, reductionDecls,
5061 privateReductionVariables, isByRef, wsloopOp.getNowait(),
5066 wsloopOp.getLoc(), privateVarsInfo);
5073 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5075 assert(isByRef.size() == opInst.getNumReductionVars());
5084 moduleTranslation, privateVarsInfo)))
5091 opInst.getNumReductionVars());
5097 bool isTaskReductionMod =
5098 opInst.getReductionMod() == omp::ReductionModifier::task &&
5099 opInst.getNumReductionVars() > 0;
5102 [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
5105 opInst, builder, moduleTranslation, privateVarsInfo, allocaIP);
5107 return llvm::make_error<PreviouslyReportedError>();
5113 cast<omp::BlockArgOpenMPOpInterface>(*opInst).getReductionBlockArgs();
5115 allocaIP = allocaIP.getNodeParent()->getTerminator()->getIterator();
5118 opInst, reductionArgs, builder, moduleTranslation, allocaIP,
5119 reductionDecls, privateReductionVariables, reductionVariableMap,
5120 deferredStores, isByRef)))
5121 return llvm::make_error<PreviouslyReportedError>();
5123 assert(afterAllocas.get()->getSinglePredecessor());
5124 builder.restoreIP(codeGenIP);
5130 return llvm::make_error<PreviouslyReportedError>();
5133 opInst, builder, moduleTranslation, privateVarsInfo.
mlirVars,
5135 opInst.getPrivateNeedsBarrier())))
5136 return llvm::make_error<PreviouslyReportedError>();
5139 initReductionVars(opInst, reductionArgs, builder, moduleTranslation,
5140 afterAllocas.get()->getSinglePredecessor(),
5141 reductionDecls, privateReductionVariables,
5142 reductionVariableMap, isByRef, deferredStores)))
5143 return llvm::make_error<PreviouslyReportedError>();
5148 if (isTaskReductionMod &&
5150 "__omp_taskred_mod_", builder, allocaIP,
5151 moduleTranslation,
true,
5153 return llvm::createStringError(
5154 "failed to emit task reduction modifier initialization");
5159 moduleTranslation, allocaIP.getNodeParent(), deallocBlocks);
5163 opInst.getRegion(),
"omp.par.region", builder, moduleTranslation);
5165 return regionBlock.takeError();
5168 if (opInst.getNumReductionVars() > 0) {
5173 owningReductionGenRefDataPtrGens;
5175 collectReductionInfo(opInst, builder, moduleTranslation, reductionDecls,
5177 owningReductionGenRefDataPtrGens,
5178 privateReductionVariables, reductionInfos, isByRef);
5181 builder.SetInsertPoint((*regionBlock)->getTerminator());
5185 if (isTaskReductionMod)
5190 llvm::UnreachableInst *tempTerminator = builder.CreateUnreachable();
5191 builder.SetInsertPoint(tempTerminator);
5193 llvm::OpenMPIRBuilder::InsertPointOrErrorTy contInsertPoint =
5194 ompBuilder->createReductions(builder, allocaIP, reductionInfos,
5198 if (!contInsertPoint)
5199 return contInsertPoint.takeError();
5201 if (!contInsertPoint->isValid())
5202 return llvm::make_error<PreviouslyReportedError>();
5204 tempTerminator->eraseFromParent();
5205 builder.restoreIP(*contInsertPoint);
5208 return llvm::Error::success();
5211 auto privCB = [](InsertPointTy allocaIP, InsertPointTy codeGenIP,
5212 llvm::Value &, llvm::Value &val, llvm::Value *&replVal) {
5221 auto finiCB = [&](InsertPointTy codeGenIP) -> llvm::Error {
5222 InsertPointTy oldIP = builder.saveIP();
5223 builder.restoreIP(codeGenIP);
5228 llvm::transform(reductionDecls, std::back_inserter(reductionCleanupRegions),
5229 [](omp::DeclareReductionOp reductionDecl) {
5230 return &reductionDecl.getCleanupRegion();
5233 reductionCleanupRegions, privateReductionVariables,
5234 moduleTranslation, builder,
"omp.reduction.cleanup")))
5235 return llvm::createStringError(
5236 "failed to inline `cleanup` region of `omp.declare_reduction`");
5239 opInst.getLoc(), privateVarsInfo)))
5240 return llvm::make_error<PreviouslyReportedError>();
5244 if (isCancellable) {
5245 auto IPOrErr = ompBuilder->createBarrier(
5246 llvm::OpenMPIRBuilder::LocationDescription(builder),
5247 llvm::omp::Directive::OMPD_unknown,
5251 return IPOrErr.takeError();
5254 builder.restoreIP(oldIP);
5255 return llvm::Error::success();
5258 llvm::Value *ifCond =
nullptr;
5259 if (
auto ifVar = opInst.getIfExpr())
5261 llvm::Value *numThreads =
nullptr;
5262 if (!opInst.getNumThreadsVars().empty())
5263 numThreads = moduleTranslation.
lookupValue(opInst.getNumThreads(0));
5264 auto pbKind = llvm::omp::OMP_PROC_BIND_default;
5265 if (
auto bind = opInst.getProcBindKind())
5269 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
5271 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5273 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
5274 ompBuilder->createParallel(ompLoc, allocaIP, deallocBlocks, bodyGenCB,
5275 privCB, finiCB, ifCond, numThreads, pbKind,
5281 builder.restoreIP(*afterIP);
5286static llvm::omp::OrderKind
5289 return llvm::omp::OrderKind::OMP_ORDER_unknown;
5291 case omp::ClauseOrderKind::Concurrent:
5292 return llvm::omp::OrderKind::OMP_ORDER_concurrent;
5294 llvm_unreachable(
"Unknown ClauseOrderKind kind");
5302 auto simdOp = cast<omp::SimdOp>(opInst);
5311 cast<omp::BlockArgOpenMPOpInterface>(opInst).getReductionBlockArgs();
5314 simdOp.getNumReductionVars());
5319 assert(isByRef.size() == simdOp.getNumReductionVars());
5321 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
5325 simdOp, builder, moduleTranslation, privateVarsInfo, allocaIP);
5330 moduleTranslation, allocaIP, reductionDecls,
5331 privateReductionVariables, reductionVariableMap,
5332 deferredStores, isByRef)))
5345 LinearClauseProcessor linearClauseProcessor;
5346 if (linearClauseProcessor.initLinearIV(simdOp).failed())
5349 if (!simdOp.getLinearVars().empty()) {
5350 auto linearVarTypes = simdOp.getLinearVarTypes().value();
5352 linearClauseProcessor.registerType(moduleTranslation, linearVarType);
5353 for (
auto [idx, linearVar] : llvm::enumerate(simdOp.getLinearVars())) {
5355 linearClauseProcessor.createLinearVar(
5356 builder, allocaIP, privateVarsInfo.
privatizers[privIdx],
5358 privateVarsInfo.
llvmVars[privIdx], idx);
5360 for (
mlir::Value linearStep : simdOp.getLinearStepVars())
5361 linearClauseProcessor.initLinearStep(moduleTranslation, linearStep);
5364 assert(afterAllocas.get()->getSinglePredecessor());
5365 if (failed(initReductionVars(simdOp, reductionArgs, builder,
5367 afterAllocas.get()->getSinglePredecessor(),
5368 reductionDecls, privateReductionVariables,
5369 reductionVariableMap, isByRef, deferredStores)))
5372 llvm::ConstantInt *simdlen =
nullptr;
5373 if (std::optional<uint64_t> simdlenVar = simdOp.getSimdlen())
5374 simdlen = builder.getInt64(simdlenVar.value());
5376 llvm::ConstantInt *safelen =
nullptr;
5377 if (std::optional<uint64_t> safelenVar = simdOp.getSafelen())
5378 safelen = builder.getInt64(safelenVar.value());
5383 llvm::BasicBlock *sourceBlock = builder.GetInsertBlock();
5384 std::optional<ArrayAttr> alignmentValues = simdOp.getAlignments();
5386 for (
size_t i = 0; i < operands.size(); ++i) {
5387 llvm::Value *alignment =
nullptr;
5388 llvm::Value *llvmVal = moduleTranslation.
lookupValue(operands[i]);
5389 llvm::Type *ty = llvmVal->getType();
5391 auto intAttr = cast<IntegerAttr>((*alignmentValues)[i]);
5392 alignment = builder.getInt64(intAttr.getInt());
5393 assert(ty->isPointerTy() &&
"Invalid type for aligned variable");
5394 assert(alignment &&
"Invalid alignment value");
5398 if (!intAttr.getValue().isPowerOf2())
5401 auto curInsert = builder.saveIP();
5402 builder.SetInsertPoint(sourceBlock);
5403 llvmVal = builder.CreateLoad(ty, llvmVal);
5404 builder.restoreIP(curInsert);
5405 alignedVars[llvmVal] = alignment;
5409 simdOp.getRegion(),
"omp.simd.region", builder, moduleTranslation);
5416 if (simdOp.getLinearVars().size()) {
5418 linearClauseProcessor.initLinearVar(builder, moduleTranslation,
5419 loopInfo->getPreheader()),
5423 if (failed(
handleError(linearClauseProcessor.updateLinearVar(
5424 builder, moduleTranslation, loopInfo->getBody(),
5425 loopInfo->getIndVar()),
5429 builder.SetInsertPoint((*regionBlock)->begin());
5431 ompBuilder->applySimd(loopInfo, alignedVars,
5433 ? moduleTranslation.
lookupValue(simdOp.getIfExpr())
5435 order, simdlen, safelen);
5438 linearClauseProcessor.updateLinearIV(builder, moduleTranslation),
5441 if (failed(
handleError(linearClauseProcessor.emitStoresForLinearVar(
5442 builder, moduleTranslation),
5450 for (
auto [i, tuple] : llvm::enumerate(
5451 llvm::zip(reductionDecls, isByRef, simdOp.getReductionVars(),
5452 privateReductionVariables))) {
5453 auto [decl, byRef, reductionVar, privateReductionVar] = tuple;
5455 OwningReductionGen gen =
makeReductionGen(decl, builder, moduleTranslation);
5456 llvm::Value *originalVariable = moduleTranslation.
lookupValue(reductionVar);
5457 llvm::Type *reductionType = moduleTranslation.
convertType(decl.getType());
5461 llvm::Value *redValue = originalVariable;
5464 builder.CreateLoad(reductionType, redValue,
"red.value." + Twine(i));
5465 llvm::Value *privateRedValue = builder.CreateLoad(
5466 reductionType, privateReductionVar,
"red.private.value." + Twine(i));
5467 llvm::Value *reduced;
5469 auto res = gen(builder.saveIP(), redValue, privateRedValue, reduced);
5472 builder.restoreIP(res.get());
5476 builder.CreateStore(reduced, originalVariable);
5481 llvm::transform(reductionDecls, std::back_inserter(reductionRegions),
5482 [](omp::DeclareReductionOp reductionDecl) {
5483 return &reductionDecl.getCleanupRegion();
5486 moduleTranslation, builder,
5487 "omp.reduction.cleanup")))
5499 auto loopOp = cast<omp::LoopNestOp>(opInst);
5505 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5510 auto bodyGen = [&](llvm::OpenMPIRBuilder::InsertPointTy ip,
5511 llvm::Value *iv) -> llvm::Error {
5514 loopOp.getRegion().front().getArgument(loopInfos.size()), iv);
5519 bodyInsertPoints.push_back(ip);
5521 if (loopInfos.size() != loopOp.getNumLoops() - 1)
5522 return llvm::Error::success();
5525 builder.restoreIP(ip);
5527 loopOp.getRegion(),
"omp.loop_nest.region", builder, moduleTranslation);
5529 return regionBlock.takeError();
5531 builder.SetInsertPoint((*regionBlock)->begin());
5532 return llvm::Error::success();
5540 for (
unsigned i = 0, e = loopOp.getNumLoops(); i < e; ++i) {
5541 llvm::Value *lowerBound =
5542 moduleTranslation.
lookupValue(loopOp.getLoopLowerBounds()[i]);
5543 llvm::Value *upperBound =
5544 moduleTranslation.
lookupValue(loopOp.getLoopUpperBounds()[i]);
5545 llvm::Value *step = moduleTranslation.
lookupValue(loopOp.getLoopSteps()[i]);
5550 llvm::OpenMPIRBuilder::LocationDescription loc = ompLoc;
5551 llvm::OpenMPIRBuilder::InsertPointTy computeIP = ompLoc.IP;
5553 loc = llvm::OpenMPIRBuilder::LocationDescription(bodyInsertPoints.back(),
5555 computeIP = loopInfos.front()->getPreheaderIP();
5559 ompBuilder->createCanonicalLoop(
5560 loc, bodyGen, lowerBound, upperBound, step,
5561 true, loopOp.getLoopInclusive(), computeIP);
5566 loopInfos.push_back(*loopResult);
5569 llvm::OpenMPIRBuilder::InsertPointTy afterIP =
5570 loopInfos.front()->getAfterIP();
5573 if (
const auto &tiles = loopOp.getTileSizes()) {
5574 llvm::Type *ivType = loopInfos.front()->getIndVarType();
5577 for (
auto tile : tiles.value()) {
5578 llvm::Value *tileVal = llvm::ConstantInt::get(ivType,
tile);
5579 tileSizes.push_back(tileVal);
5582 std::vector<llvm::CanonicalLoopInfo *> newLoops =
5583 ompBuilder->tileLoops(ompLoc.DL, loopInfos, tileSizes);
5587 llvm::BasicBlock *afterBB = newLoops.front()->getAfter();
5588 llvm::BasicBlock *afterAfterBB = afterBB->getSingleSuccessor();
5589 afterIP = afterAfterBB->begin();
5593 for (
const auto &newLoop : newLoops)
5594 loopInfos.push_back(newLoop);
5598 const auto &numCollapse = loopOp.getCollapseNumLoops();
5600 loopInfos.begin(), loopInfos.begin() + (numCollapse));
5602 auto newTopLoopInfo =
5603 ompBuilder->collapseLoops(ompLoc.DL, collapseLoopInfos, {});
5605 assert(newTopLoopInfo &&
"New top loop information is missing");
5606 moduleTranslation.
stackWalk<OpenMPLoopInfoStackFrame>(
5607 [&](OpenMPLoopInfoStackFrame &frame) {
5608 frame.loopInfo = newTopLoopInfo;
5616 builder.restoreIP(afterIP);
5626 llvm::OpenMPIRBuilder::LocationDescription loopLoc(builder);
5627 Value loopIV = op.getInductionVar();
5628 Value loopTC = op.getTripCount();
5630 llvm::Value *llvmTC = moduleTranslation.
lookupValue(loopTC);
5633 ompBuilder->createCanonicalLoop(
5635 [&](llvm::OpenMPIRBuilder::InsertPointTy ip, llvm::Value *llvmIV) {
5638 moduleTranslation.
mapValue(loopIV, llvmIV);
5640 builder.restoreIP(ip);
5645 return bodyGenStatus.takeError();
5647 llvmTC,
"omp.loop");
5649 return op.emitError(llvm::toString(llvmOrError.takeError()));
5651 llvm::CanonicalLoopInfo *llvmCLI = *llvmOrError;
5652 llvm::IRBuilderBase::InsertPoint afterIP = llvmCLI->getAfterIP();
5653 builder.restoreIP(afterIP);
5656 if (
Value cli = op.getCli())
5669 Value applyee = op.getApplyee();
5670 assert(applyee &&
"Loop to apply unrolling on required");
5672 llvm::CanonicalLoopInfo *consBuilderCLI =
5674 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
5675 ompBuilder->unrollLoopHeuristic(loc.DL, consBuilderCLI);
5688 Value applyee = op.getApplyee();
5689 assert(applyee &&
"Loop to apply unrolling on required");
5691 llvm::CanonicalLoopInfo *consBuilderCLI =
5693 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
5694 ompBuilder->unrollLoopFull(loc.DL, consBuilderCLI);
5707 Value applyee = op.getApplyee();
5708 assert(applyee &&
"Loop to apply unrolling on required");
5710 llvm::CanonicalLoopInfo *consBuilderCLI =
5712 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
5716 int32_t factor =
static_cast<int32_t
>(op.getUnrollFactor());
5717 ompBuilder->unrollLoopPartial(loc.DL, consBuilderCLI, factor,
5726static LogicalResult
applyTile(omp::TileOp op, llvm::IRBuilderBase &builder,
5729 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
5734 for (
Value size : op.getSizes()) {
5735 llvm::Value *translatedSize = moduleTranslation.
lookupValue(size);
5736 assert(translatedSize &&
5737 "sizes clause arguments must already be translated");
5738 translatedSizes.push_back(translatedSize);
5741 for (
Value applyee : op.getApplyees()) {
5742 llvm::CanonicalLoopInfo *consBuilderCLI =
5744 assert(applyee &&
"Canonical loop must already been translated");
5745 translatedLoops.push_back(consBuilderCLI);
5748 auto generatedLoops =
5749 ompBuilder->tileLoops(loc.DL, translatedLoops, translatedSizes);
5750 if (!op.getGeneratees().empty()) {
5751 for (
auto [mlirLoop,
genLoop] :
5752 zip_equal(op.getGeneratees(), generatedLoops))
5757 for (
Value applyee : op.getApplyees())
5765static LogicalResult
applyFuse(omp::FuseOp op, llvm::IRBuilderBase &builder,
5768 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
5772 for (
size_t i = 0; i < op.getApplyees().size(); i++) {
5773 Value applyee = op.getApplyees()[i];
5774 llvm::CanonicalLoopInfo *consBuilderCLI =
5776 assert(applyee &&
"Canonical loop must already been translated");
5777 if (op.getFirst().has_value() && i < op.getFirst().value() - 1)
5778 beforeFuse.push_back(consBuilderCLI);
5779 else if (op.getCount().has_value() &&
5780 i >= op.getFirst().value() + op.getCount().value() - 1)
5781 afterFuse.push_back(consBuilderCLI);
5783 toFuse.push_back(consBuilderCLI);
5786 (op.getGeneratees().empty() ||
5787 beforeFuse.size() + afterFuse.size() + 1 == op.getGeneratees().size()) &&
5788 "Wrong number of generatees");
5791 auto generatedLoop = ompBuilder->fuseLoops(loc.DL, toFuse);
5792 if (!op.getGeneratees().empty()) {
5794 for (; i < beforeFuse.size(); i++)
5795 moduleTranslation.
mapOmpLoop(op.getGeneratees()[i], beforeFuse[i]);
5796 moduleTranslation.
mapOmpLoop(op.getGeneratees()[i++], generatedLoop);
5797 for (; i < afterFuse.size(); i++)
5798 moduleTranslation.
mapOmpLoop(op.getGeneratees()[i], afterFuse[i]);
5802 for (
Value applyee : op.getApplyees())
5809static llvm::AtomicOrdering
5812 return llvm::AtomicOrdering::Monotonic;
5815 case omp::ClauseMemoryOrderKind::Seq_cst:
5816 return llvm::AtomicOrdering::SequentiallyConsistent;
5817 case omp::ClauseMemoryOrderKind::Acq_rel:
5818 return llvm::AtomicOrdering::AcquireRelease;
5819 case omp::ClauseMemoryOrderKind::Acquire:
5820 return llvm::AtomicOrdering::Acquire;
5821 case omp::ClauseMemoryOrderKind::Release:
5822 return llvm::AtomicOrdering::Release;
5823 case omp::ClauseMemoryOrderKind::Relaxed:
5824 return llvm::AtomicOrdering::Monotonic;
5826 llvm_unreachable(
"Unknown ClauseMemoryOrderKind kind");
5833static llvm::AtomicOrdering
5835 llvm::AtomicOrdering atomicOrdering) {
5836 if (atomicCompareOp.getFailMemoryOrder())
5838 return llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(atomicOrdering);
5845 auto readOp = cast<omp::AtomicReadOp>(opInst);
5850 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
5853 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5856 llvm::Value *x = moduleTranslation.
lookupValue(readOp.getX());
5857 llvm::Value *v = moduleTranslation.
lookupValue(readOp.getV());
5859 llvm::Type *elementType =
5860 moduleTranslation.
convertType(readOp.getElementType());
5862 llvm::OpenMPIRBuilder::AtomicOpValue V = {v, elementType,
false,
false};
5863 llvm::OpenMPIRBuilder::AtomicOpValue X = {x, elementType,
false,
false};
5864 builder.restoreIP(ompBuilder->createAtomicRead(ompLoc, X, V, AO, allocaIP));
5872 auto writeOp = cast<omp::AtomicWriteOp>(opInst);
5877 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
5880 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5882 llvm::Value *expr = moduleTranslation.
lookupValue(writeOp.getExpr());
5883 llvm::Value *dest = moduleTranslation.
lookupValue(writeOp.getX());
5884 llvm::Type *ty = moduleTranslation.
convertType(writeOp.getExpr().getType());
5885 llvm::OpenMPIRBuilder::AtomicOpValue x = {dest, ty,
false,
5888 ompBuilder->createAtomicWrite(ompLoc, x, expr, ao, allocaIP));
5896 .Case([&](LLVM::AddOp) {
return llvm::AtomicRMWInst::BinOp::Add; })
5897 .Case([&](LLVM::SubOp) {
return llvm::AtomicRMWInst::BinOp::Sub; })
5898 .Case([&](LLVM::AndOp) {
return llvm::AtomicRMWInst::BinOp::And; })
5899 .Case([&](LLVM::OrOp) {
return llvm::AtomicRMWInst::BinOp::Or; })
5900 .Case([&](LLVM::XOrOp) {
return llvm::AtomicRMWInst::BinOp::Xor; })
5901 .Case([&](LLVM::SMaxOp) {
return llvm::AtomicRMWInst::BinOp::Max; })
5902 .Case([&](LLVM::SMinOp) {
return llvm::AtomicRMWInst::BinOp::Min; })
5903 .Case([&](LLVM::UMaxOp) {
return llvm::AtomicRMWInst::BinOp::UMax; })
5904 .Case([&](LLVM::UMinOp) {
return llvm::AtomicRMWInst::BinOp::UMin; })
5905 .Case([&](LLVM::FAddOp) {
return llvm::AtomicRMWInst::BinOp::FAdd; })
5906 .Case([&](LLVM::FSubOp) {
return llvm::AtomicRMWInst::BinOp::FSub; })
5907 .Case([&](LLVM::MaxNumOp) {
return llvm::AtomicRMWInst::BinOp::FMax; })
5908 .Case([&](LLVM::MinNumOp) {
return llvm::AtomicRMWInst::BinOp::FMin; })
5910 [&](LLVM::MaximumOp) {
return llvm::AtomicRMWInst::BinOp::FMaximum; })
5912 [&](LLVM::MinimumOp) {
return llvm::AtomicRMWInst::BinOp::FMinimum; })
5913 .Default(llvm::AtomicRMWInst::BinOp::BAD_BINOP);
5917 bool &isIgnoreDenormalMode,
5918 bool &isFineGrainedMemory,
5919 bool &isRemoteMemory) {
5920 isIgnoreDenormalMode =
false;
5921 isFineGrainedMemory =
false;
5922 isRemoteMemory =
false;
5923 if (atomicUpdateOp && atomicUpdateOp.getAtomicControlAttr()) {
5924 mlir::omp::AtomicControlAttr atomicControlAttr =
5925 atomicUpdateOp.getAtomicControlAttr();
5926 isIgnoreDenormalMode = atomicControlAttr.getIgnoreDenormalMode();
5927 isFineGrainedMemory = atomicControlAttr.getFineGrainedMemory();
5928 isRemoteMemory = atomicControlAttr.getRemoteMemory();
5935 llvm::IRBuilderBase &builder,
5942 auto &innerOpList = opInst.getRegion().front().getOperations();
5943 bool isXBinopExpr{
false};
5944 llvm::AtomicRMWInst::BinOp binop;
5946 llvm::Value *llvmExpr =
nullptr;
5947 llvm::Value *llvmX =
nullptr;
5948 llvm::Type *llvmXElementType =
nullptr;
5949 if (innerOpList.size() == 2) {
5955 opInst.getRegion().getArgument(0))) {
5956 return opInst.emitError(
"no atomic update operation with region argument"
5957 " as operand found inside atomic.update region");
5960 isXBinopExpr = innerOp.
getOperand(0) == opInst.getRegion().getArgument(0);
5962 llvmExpr = moduleTranslation.
lookupValue(mlirExpr);
5966 binop = llvm::AtomicRMWInst::BinOp::BAD_BINOP;
5968 llvmX = moduleTranslation.
lookupValue(opInst.getX());
5970 opInst.getRegion().getArgument(0).getType());
5971 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {llvmX, llvmXElementType,
5975 llvm::AtomicOrdering atomicOrdering =
5980 [&opInst, &moduleTranslation](
5981 llvm::Value *atomicx,
5984 moduleTranslation.
mapValue(*opInst.getRegion().args_begin(), atomicx);
5985 moduleTranslation.
mapBlock(&bb, builder.GetInsertBlock());
5986 if (failed(moduleTranslation.
convertBlock(bb,
true, builder)))
5987 return llvm::make_error<PreviouslyReportedError>();
5989 omp::YieldOp yieldop = dyn_cast<omp::YieldOp>(bb.
getTerminator());
5990 assert(yieldop && yieldop.getResults().size() == 1 &&
5991 "terminator must be omp.yield op and it must have exactly one "
5993 return moduleTranslation.
lookupValue(yieldop.getResults()[0]);
5996 bool isIgnoreDenormalMode;
5997 bool isFineGrainedMemory;
5998 bool isRemoteMemory;
6003 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6004 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
6005 ompBuilder->createAtomicUpdate(ompLoc, allocaIP, llvmAtomicX, llvmExpr,
6006 atomicOrdering, binop, updateFn,
6007 isXBinopExpr, isIgnoreDenormalMode,
6008 isFineGrainedMemory, isRemoteMemory);
6013 builder.restoreIP(*afterIP);
6019static std::optional<llvm::omp::OMPAtomicCompareOp>
6021 switch (predicate) {
6022 case LLVM::ICmpPredicate::eq:
6023 return llvm::omp::OMPAtomicCompareOp::EQ;
6024 case LLVM::ICmpPredicate::slt:
6025 case LLVM::ICmpPredicate::ult:
6026 return llvm::omp::OMPAtomicCompareOp::MIN;
6027 case LLVM::ICmpPredicate::sgt:
6028 case LLVM::ICmpPredicate::ugt:
6029 return llvm::omp::OMPAtomicCompareOp::MAX;
6031 return std::nullopt;
6037static std::optional<llvm::omp::OMPAtomicCompareOp>
6039 switch (predicate) {
6040 case LLVM::FCmpPredicate::oeq:
6041 case LLVM::FCmpPredicate::ueq:
6042 return llvm::omp::OMPAtomicCompareOp::EQ;
6043 case LLVM::FCmpPredicate::olt:
6044 case LLVM::FCmpPredicate::ult:
6045 return llvm::omp::OMPAtomicCompareOp::MIN;
6046 case LLVM::FCmpPredicate::ogt:
6047 case LLVM::FCmpPredicate::ugt:
6048 return llvm::omp::OMPAtomicCompareOp::MAX;
6050 return std::nullopt;
6077 if (
auto extractOp = v.getDefiningOp<LLVM::ExtractValueOp>())
6078 return extractOp.getContainer();
6082 if (!isa<LLVM::AndOp, LLVM::OrOp>(op))
6086 if (!lhsFcmp || !rhsFcmp)
6088 mlir::Value lhsAgg0 = traceToAggregate(lhsFcmp.getOperand(0));
6089 mlir::Value lhsAgg1 = traceToAggregate(lhsFcmp.getOperand(1));
6090 bool lhsXIsOp0 = (lhsAgg0 == block.
getArgument(0));
6091 bool lhsXIsOp1 = (lhsAgg1 == block.
getArgument(0));
6092 if (!lhsXIsOp0 && !lhsXIsOp1)
6094 mlir::Value eAggregate = lhsXIsOp0 ? lhsAgg1 : lhsAgg0;
6098 result.isNE = isa<LLVM::OrOp>(op);
6099 result.eAggregate = eAggregate;
6100 result.isXBinopExpr = lhsXIsOp0;
6112 llvm::Value *llvmX, llvm::Type *complexTy,
6113 llvm::Value *eVal, llvm::Value *dVal,
6114 llvm::AtomicOrdering atomicOrdering,
6115 llvm::AtomicOrdering failOrdering,
6116 bool isWeak, llvm::Value *&oldComplex,
6117 llvm::Value *&cmpOk) {
6118 const llvm::DataLayout &DL = builder.getDataLayout();
6119 unsigned totalBits = DL.getTypeStoreSizeInBits(complexTy).getFixedValue();
6120 llvm::IntegerType *intTy =
6121 llvm::IntegerType::get(builder.getContext(), totalBits);
6122 llvm::Align complexAlign = DL.getABITypeAlign(complexTy);
6123 llvm::Align intAlign = DL.getABITypeAlign(intTy);
6124 llvm::Align maxAlign = std::max(complexAlign, intAlign);
6127 llvm::AllocaInst *dAlloca =
6128 builder.CreateAlloca(complexTy,
nullptr,
"cmplx.d");
6129 dAlloca->setAlignment(maxAlign);
6130 builder.CreateAlignedStore(dVal, dAlloca, maxAlign);
6132 builder.CreateAlignedLoad(intTy, dAlloca, maxAlign,
"cmplx.d.int");
6137 llvm::LoadInst *xCurr =
6138 builder.CreateAlignedLoad(intTy, llvmX, maxAlign,
"cmplx.x.load");
6139 xCurr->setAtomic(failOrdering);
6140 llvm::AllocaInst *xAlloca =
6141 builder.CreateAlloca(complexTy,
nullptr,
"cmplx.x");
6142 xAlloca->setAlignment(maxAlign);
6143 builder.CreateAlignedStore(xCurr, xAlloca, maxAlign);
6144 llvm::Value *xStruct =
6145 builder.CreateAlignedLoad(complexTy, xAlloca, maxAlign,
"cmplx.x.val");
6150 llvm::Value *reX = builder.CreateExtractValue(xStruct, 0);
6151 llvm::Value *imX = builder.CreateExtractValue(xStruct, 1);
6152 llvm::Value *reE = builder.CreateExtractValue(eVal, 0);
6153 llvm::Value *imE = builder.CreateExtractValue(eVal, 1);
6154 llvm::Value *reEq = builder.CreateFCmpOEQ(reX, reE,
"cmplx.re.eq");
6155 llvm::Value *imEq = builder.CreateFCmpOEQ(imX, imE,
"cmplx.im.eq");
6156 llvm::Value *fpEqual = builder.CreateAnd(reEq, imEq,
"cmplx.eq");
6161 llvm::BasicBlock *curBB = builder.GetInsertBlock();
6162 llvm::Function *fn = curBB->getParent();
6163 llvm::BasicBlock *swapBB =
6164 llvm::BasicBlock::Create(builder.getContext(),
"cmplx.atomic.swap", fn);
6165 llvm::BasicBlock *exitBB =
6166 llvm::BasicBlock::Create(builder.getContext(),
"cmplx.atomic.exit", fn);
6167 builder.CreateCondBr(fpEqual, swapBB, exitBB);
6169 builder.SetInsertPoint(swapBB);
6170 llvm::AtomicCmpXchgInst *cmpXchg = builder.CreateAtomicCmpXchg(
6171 llvmX, xCurr, dInt, maxAlign, atomicOrdering, failOrdering);
6172 cmpXchg->setWeak(isWeak);
6173 llvm::Value *oldSwap = builder.CreateExtractValue(cmpXchg, 0);
6174 llvm::Value *okSwap = builder.CreateExtractValue(cmpXchg, 1);
6175 builder.CreateBr(exitBB);
6178 builder.SetInsertPoint(exitBB);
6179 llvm::PHINode *oldIntPHI = builder.CreatePHI(intTy, 2,
"cmplx.old.int");
6180 oldIntPHI->addIncoming(oldSwap, swapBB);
6181 oldIntPHI->addIncoming(xCurr, curBB);
6182 llvm::PHINode *okPHI = builder.CreatePHI(builder.getInt1Ty(), 2,
"cmplx.ok");
6183 okPHI->addIncoming(okSwap, swapBB);
6184 okPHI->addIncoming(builder.getFalse(), curBB);
6187 llvm::AllocaInst *oldAlloca =
6188 builder.CreateAlloca(complexTy,
nullptr,
"cmplx.old");
6189 oldAlloca->setAlignment(maxAlign);
6190 builder.CreateAlignedStore(oldIntPHI, oldAlloca, maxAlign);
6191 oldComplex = builder.CreateAlignedLoad(complexTy, oldAlloca, maxAlign,
6199 llvm::omp::OMPAtomicCompareOp
compareOp = llvm::omp::OMPAtomicCompareOp::EQ;
6219 return atomicCompareOp.emitError(
6220 "unsupported comparison predicate (NE) for complex atomic compare");
6221 info.
compareOp = llvm::omp::OMPAtomicCompareOp::EQ;
6223 info.
eVal = materializeValue(cplx.eAggregate);
6225 if (
auto selectOp = dyn_cast<LLVM::SelectOp>(op)) {
6226 info.
dVal = materializeValue(selectOp.getTrueValue());
6236 if (
auto icmpOp = dyn_cast<LLVM::ICmpOp>(op);
6237 icmpOp && icmpOp.getOperand(0) != block.
getArgument(0) &&
6243 .Case<LLVM::ICmpOp>([&](LLVM::ICmpOp icmpOp) -> LogicalResult {
6247 return atomicCompareOp.emitError(
6248 "unsupported comparison predicate in atomic compare");
6250 LLVM::ICmpPredicate pred = icmpOp.getPredicate();
6251 info.
isSigned = (pred == LLVM::ICmpPredicate::slt ||
6252 pred == LLVM::ICmpPredicate::sgt ||
6253 pred == LLVM::ICmpPredicate::sle ||
6254 pred == LLVM::ICmpPredicate::sge);
6258 : icmpOp.getOperand(0);
6259 info.
eVal = materializeValue(eOperand);
6262 .Case<LLVM::FCmpOp>([&](LLVM::FCmpOp fcmpOp) -> LogicalResult {
6266 return atomicCompareOp.emitError(
6267 "unsupported comparison predicate in atomic compare");
6272 : fcmpOp.getOperand(0);
6273 info.
eVal = materializeValue(eOperand);
6276 .Case<LLVM::SelectOp>([&](LLVM::SelectOp selectOp) {
6278 info.
dVal = materializeValue(selectOp.getTrueValue());
6281 .Case<mlir::arith::MaxSIOp, mlir::arith::MinSIOp,
6282 mlir::arith::MaxUIOp, mlir::arith::MinUIOp,
6283 mlir::arith::MaximumFOp, mlir::arith::MinimumFOp,
6284 LLVM::SMaxOp, LLVM::SMinOp, LLVM::UMaxOp, LLVM::UMinOp,
6285 LLVM::MaxNumOp, LLVM::MinNumOp>([&](
Operation *) {
6290 bool isMax = isa<mlir::arith::MaxSIOp, mlir::arith::MaxUIOp,
6291 mlir::arith::MaximumFOp, LLVM::SMaxOp,
6292 LLVM::UMaxOp, LLVM::MaxNumOp>(op);
6293 info.
compareOp = isMax ? llvm::omp::OMPAtomicCompareOp::MIN
6294 : llvm::omp::OMPAtomicCompareOp::MAX;
6295 info.
isSigned = isa<mlir::arith::MaxSIOp, mlir::arith::MinSIOp,
6296 LLVM::SMaxOp, LLVM::SMinOp>(op);
6300 info.
eVal = materializeValue(eOperand);
6314 llvm::IRBuilderBase &builder,
6320 omp::AtomicUpdateOp atomicUpdateOp = atomicCaptureOp.getAtomicUpdateOp();
6321 omp::AtomicWriteOp atomicWriteOp = atomicCaptureOp.getAtomicWriteOp();
6322 omp::AtomicCompareOp atomicCompareOp = atomicCaptureOp.getAtomicCompareOp();
6326 if (atomicCompareOp) {
6327 omp::AtomicReadOp atomicReadOp = atomicCaptureOp.getAtomicReadOp();
6328 assert(atomicReadOp &&
"expected atomic.read in capture+compare");
6330 Region ®ion = atomicCompareOp.getRegion();
6333 llvm::Type *llvmXElementType =
6335 llvm::Value *llvmX = moduleTranslation.
lookupValue(atomicCompareOp.getX());
6336 llvm::Value *llvmV = moduleTranslation.
lookupValue(atomicReadOp.getV());
6338 bool isSigned =
false;
6339 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {
6340 llvmX, llvmXElementType, isSigned,
false};
6341 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicV = {
6342 llvmV, llvmXElementType,
false,
false};
6343 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicR = {
nullptr,
nullptr,
false,
6346 llvm::AtomicOrdering atomicOrdering =
6350 auto isAtomicComparePatternOp = [](
Operation &op) {
6351 return llvm::isa<LLVM::ICmpOp, LLVM::FCmpOp, LLVM::SelectOp, LLVM::AndOp,
6352 LLVM::OrOp, LLVM::SMaxOp, LLVM::SMinOp, LLVM::UMaxOp,
6353 LLVM::UMinOp, LLVM::MaxNumOp, LLVM::MinNumOp,
6354 mlir::arith::MaxSIOp, mlir::arith::MinSIOp,
6355 mlir::arith::MaxUIOp, mlir::arith::MinUIOp,
6356 mlir::arith::MaximumFOp, mlir::arith::MinimumFOp>(op);
6359 if (isAtomicComparePatternOp(op))
6361 bool allOperandsMapped =
6363 return moduleTranslation.lookupValue(v) != nullptr;
6365 if (!allOperandsMapped)
6368 return atomicCompareOp.emitError(
6369 "failed to translate operation inside atomic compare region");
6372 auto materializeValue = [&](
mlir::Value val) -> llvm::Value * {
6373 if (llvm::Value *existing = moduleTranslation.
lookupValue(val))
6375 if (
auto loadOp = val.getDefiningOp<LLVM::LoadOp>()) {
6376 if (loadOp->getParentRegion() == ®ion) {
6377 llvm::Value *loadAddr =
6381 llvm::Type *loadType =
6382 moduleTranslation.
convertType(loadOp.getResult().getType());
6383 return builder.CreateLoad(loadType, loadAddr);
6392 atomicCompareOp, patternInfo)))
6395 llvm::omp::OMPAtomicCompareOp compareOp = patternInfo.
compareOp;
6396 llvm::Value *eVal = patternInfo.
eVal;
6397 llvm::Value *dVal = patternInfo.
dVal;
6402 return atomicCompareOp.emitError(
6403 "failed to extract expected value (e) from atomic compare region");
6406 if (yieldOp.getResults().empty())
6407 return atomicCompareOp.emitError(
6408 "failed to extract desired value (d) from atomic compare region");
6409 dVal = materializeValue(yieldOp.getResults()[0]);
6412 llvmAtomicX.IsSigned = isSigned;
6414 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6415 bool isReadFirst = isa<omp::AtomicReadOp>(atomicCaptureOp.getFirstOp());
6416 bool isPostfixCapture = !isReadFirst;
6417 bool isFailOnly = atomicCaptureOp.getFailOnly();
6425 if (llvmXElementType->isStructTy()) {
6426 llvm::Value *oldComplex =
nullptr;
6427 llvm::Value *cmpOk =
nullptr;
6428 llvm::AtomicOrdering failOrdering =
6431 atomicOrdering, failOrdering,
6432 atomicCompareOp.getWeak(), oldComplex, cmpOk);
6436 llvm::Value *cmpFailed = builder.CreateNot(cmpOk);
6437 llvm::BasicBlock *curBB = builder.GetInsertBlock();
6438 llvm::Function *fn = curBB->getParent();
6439 llvm::BasicBlock *contBB = llvm::BasicBlock::Create(
6440 builder.getContext(),
"omp.atomic.cont", fn);
6441 llvm::BasicBlock *exitBB = llvm::BasicBlock::Create(
6442 builder.getContext(),
"omp.atomic.exit", fn);
6443 builder.CreateCondBr(cmpFailed, contBB, exitBB);
6444 builder.SetInsertPoint(contBB);
6445 builder.CreateStore(oldComplex, llvmAtomicV.Var,
6446 llvmAtomicV.IsVolatile);
6447 builder.CreateBr(exitBB);
6448 builder.SetInsertPoint(exitBB);
6449 }
else if (isPostfixCapture) {
6451 llvm::Value *newComplex = builder.CreateSelect(cmpOk, dVal, oldComplex);
6452 builder.CreateStore(newComplex, llvmAtomicV.Var,
6453 llvmAtomicV.IsVolatile);
6456 builder.CreateStore(oldComplex, llvmAtomicV.Var,
6457 llvmAtomicV.IsVolatile);
6461 if (atomicOrdering == llvm::AtomicOrdering::Release ||
6462 atomicOrdering == llvm::AtomicOrdering::AcquireRelease ||
6463 atomicOrdering == llvm::AtomicOrdering::SequentiallyConsistent) {
6464 llvm::OpenMPIRBuilder::LocationDescription flushLoc(builder);
6465 ompBuilder->createFlush(flushLoc);
6476 bool isMinMax = compareOp != llvm::omp::OMPAtomicCompareOp::EQ;
6478 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicVForCall = llvmAtomicV;
6485 bool minMaxManualCapture = isMinMax && (isPostfixCapture || isFailOnly);
6486 bool eqPostfixManualCapture = !isMinMax && isPostfixCapture && !isFailOnly;
6487 if (minMaxManualCapture || eqPostfixManualCapture)
6488 llvmAtomicVForCall = {
nullptr,
nullptr,
false,
false};
6492 bool builderFailOnly = isFailOnly && !isMinMax;
6499 bool isPostfixUpdate = !builderFailOnly;
6501 bool isWeak = atomicCompareOp.getWeak();
6502 bool savedHandleFPNegZero = ompBuilder->setHandleFPNegZero(
true);
6503 llvm::AtomicOrdering failureOrdering =
6505 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
6506 ompBuilder->createAtomicCompare(
6507 ompLoc, llvmAtomicX, llvmAtomicVForCall, llvmAtomicR, eVal, dVal,
6508 atomicOrdering, compareOp, isXBinopExpr, isPostfixUpdate,
6509 builderFailOnly, failureOrdering, isWeak);
6510 ompBuilder->setHandleFPNegZero(savedHandleFPNegZero);
6512 if (failed(
handleError(afterIP, *atomicCaptureOp)))
6515 builder.restoreIP(*afterIP);
6524 if (isMinMax && (isPostfixCapture || isFailOnly)) {
6525 llvm::BasicBlock *curBB = builder.GetInsertBlock();
6526 llvm::AtomicRMWInst *rmw =
nullptr;
6527 for (
auto &inst : llvm::reverse(*curBB)) {
6528 if (
auto *r = dyn_cast<llvm::AtomicRMWInst>(&inst)) {
6533 assert(rmw &&
"expected atomicrmw for min/max compare capture");
6534 llvm::Value *oldVal = rmw;
6535 llvm::Value *rhs = rmw->getValOperand();
6541 llvm::CmpInst::Predicate updatePred;
6542 switch (rmw->getOperation()) {
6543 case llvm::AtomicRMWInst::Min:
6544 updatePred = llvm::CmpInst::ICMP_SGT;
6546 case llvm::AtomicRMWInst::Max:
6547 updatePred = llvm::CmpInst::ICMP_SLT;
6549 case llvm::AtomicRMWInst::UMin:
6550 updatePred = llvm::CmpInst::ICMP_UGT;
6552 case llvm::AtomicRMWInst::UMax:
6553 updatePred = llvm::CmpInst::ICMP_ULT;
6555 case llvm::AtomicRMWInst::FMin:
6556 updatePred = llvm::CmpInst::FCMP_OGT;
6558 case llvm::AtomicRMWInst::FMax:
6559 updatePred = llvm::CmpInst::FCMP_OLT;
6563 "unexpected atomicrmw op for min/max compare capture");
6565 llvm::Value *updated = builder.CreateCmp(updatePred, oldVal, rhs);
6566 llvm::Value *failed = builder.CreateNot(updated);
6567 llvm::Function *fn = curBB->getParent();
6568 llvm::BasicBlock *contBB = llvm::BasicBlock::Create(
6569 builder.getContext(),
"omp.atomic.cont", fn);
6570 llvm::BasicBlock *exitBB = llvm::BasicBlock::Create(
6571 builder.getContext(),
"omp.atomic.exit", fn);
6572 builder.CreateCondBr(failed, contBB, exitBB);
6573 builder.SetInsertPoint(contBB);
6574 builder.CreateStore(oldVal, llvmAtomicV.Var, llvmAtomicV.IsVolatile);
6575 builder.CreateBr(exitBB);
6576 builder.SetInsertPoint(exitBB);
6578 llvm::Intrinsic::ID id;
6579 switch (rmw->getOperation()) {
6580 case llvm::AtomicRMWInst::Min:
6581 id = llvm::Intrinsic::smin;
6583 case llvm::AtomicRMWInst::Max:
6584 id = llvm::Intrinsic::smax;
6586 case llvm::AtomicRMWInst::UMin:
6587 id = llvm::Intrinsic::umin;
6589 case llvm::AtomicRMWInst::UMax:
6590 id = llvm::Intrinsic::umax;
6592 case llvm::AtomicRMWInst::FMin:
6593 id = llvm::Intrinsic::minnum;
6595 case llvm::AtomicRMWInst::FMax:
6596 id = llvm::Intrinsic::maxnum;
6600 "unexpected atomicrmw op for min/max compare capture");
6602 llvm::Value *newVal = builder.CreateBinaryIntrinsic(
id, oldVal, rhs);
6603 builder.CreateStore(newVal, llvmAtomicV.Var, llvmAtomicV.IsVolatile);
6609 if (!isMinMax && isPostfixCapture && !isFailOnly) {
6610 llvm::BasicBlock *curBB = builder.GetInsertBlock();
6611 llvm::Value *oldVal =
nullptr;
6612 llvm::Value *successVal =
nullptr;
6616 for (
auto &inst : llvm::reverse(*curBB)) {
6617 if (isa<llvm::AtomicCmpXchgInst>(&inst)) {
6618 oldVal = builder.CreateExtractValue(&inst, 0);
6619 successVal = builder.CreateExtractValue(&inst, 1);
6630 for (
auto &inst : *curBB) {
6631 auto *phi = dyn_cast<llvm::PHINode>(&inst);
6634 if (phi->getType()->isIntegerTy(1))
6637 for (
auto &inst : *curBB) {
6638 if (
auto *bc = dyn_cast<llvm::BitCastInst>(&inst)) {
6645 assert(oldVal &&
"expected cmpxchg or PHI+bitcast for compare capture");
6646 assert(successVal &&
"expected success flag for compare capture");
6647 llvm::Value *newVal = builder.CreateSelect(successVal, dVal, oldVal);
6648 builder.CreateStore(newVal, llvmAtomicV.Var, llvmAtomicV.IsVolatile);
6655 bool isXBinopExpr =
false, isPostfixUpdate =
false;
6656 llvm::AtomicRMWInst::BinOp binop = llvm::AtomicRMWInst::BinOp::BAD_BINOP;
6658 assert((atomicUpdateOp || atomicWriteOp) &&
6659 "internal op must be an atomic.update or atomic.write op");
6661 if (atomicWriteOp) {
6662 isPostfixUpdate =
true;
6663 mlirExpr = atomicWriteOp.getExpr();
6665 isPostfixUpdate = atomicCaptureOp.getSecondOp() ==
6666 atomicCaptureOp.getAtomicUpdateOp().getOperation();
6667 auto &innerOpList = atomicUpdateOp.getRegion().front().getOperations();
6670 if (innerOpList.size() == 2) {
6673 atomicUpdateOp.getRegion().getArgument(0))) {
6674 return atomicUpdateOp.emitError(
6675 "no atomic update operation with region argument"
6676 " as operand found inside atomic.update region");
6680 innerOp.
getOperand(0) == atomicUpdateOp.getRegion().getArgument(0);
6683 binop = llvm::AtomicRMWInst::BinOp::BAD_BINOP;
6687 llvm::Value *llvmExpr = moduleTranslation.
lookupValue(mlirExpr);
6688 llvm::Value *llvmX =
6689 moduleTranslation.
lookupValue(atomicCaptureOp.getAtomicReadOp().getX());
6690 llvm::Value *llvmV =
6691 moduleTranslation.
lookupValue(atomicCaptureOp.getAtomicReadOp().getV());
6692 llvm::Type *llvmXElementType = moduleTranslation.
convertType(
6693 atomicCaptureOp.getAtomicReadOp().getElementType());
6694 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {llvmX, llvmXElementType,
6697 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicV = {llvmV, llvmXElementType,
6701 llvm::AtomicOrdering atomicOrdering =
6705 [&](llvm::Value *atomicx,
6708 return moduleTranslation.
lookupValue(atomicWriteOp.getExpr());
6709 Block &bb = *atomicUpdateOp.getRegion().
begin();
6710 moduleTranslation.
mapValue(*atomicUpdateOp.getRegion().args_begin(),
6712 moduleTranslation.
mapBlock(&bb, builder.GetInsertBlock());
6713 if (failed(moduleTranslation.
convertBlock(bb,
true, builder)))
6714 return llvm::make_error<PreviouslyReportedError>();
6716 omp::YieldOp yieldop = dyn_cast<omp::YieldOp>(bb.
getTerminator());
6717 assert(yieldop && yieldop.getResults().size() == 1 &&
6718 "terminator must be omp.yield op and it must have exactly one "
6720 return moduleTranslation.
lookupValue(yieldop.getResults()[0]);
6723 bool isIgnoreDenormalMode;
6724 bool isFineGrainedMemory;
6725 bool isRemoteMemory;
6727 isFineGrainedMemory, isRemoteMemory);
6730 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6731 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
6732 ompBuilder->createAtomicCapture(
6733 ompLoc, allocaIP, llvmAtomicX, llvmAtomicV, llvmExpr, atomicOrdering,
6734 binop, updateFn, atomicUpdateOp, isPostfixUpdate, isXBinopExpr,
6735 isIgnoreDenormalMode, isFineGrainedMemory, isRemoteMemory);
6737 if (failed(
handleError(afterIP, *atomicCaptureOp)))
6740 builder.restoreIP(*afterIP);
6762 llvm::IRBuilderBase &builder,
6768 Region ®ion = atomicCompareOp.getRegion();
6772 llvm::Type *llvmXElementType =
6774 if (!llvmXElementType)
6775 return atomicCompareOp.emitError(
6776 "unable to determine element type for atomic compare");
6778 llvm::Value *llvmX = moduleTranslation.
lookupValue(atomicCompareOp.getX());
6783 bool isSigned =
false;
6784 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {llvmX, llvmXElementType,
6788 llvm::AtomicOrdering atomicOrdering =
6791 auto isAtomicComparePatternOp = [](
Operation &op) {
6792 return llvm::isa<LLVM::ICmpOp, LLVM::FCmpOp, LLVM::SelectOp, LLVM::AndOp,
6793 LLVM::OrOp, LLVM::SMaxOp, LLVM::SMinOp, LLVM::UMaxOp,
6794 LLVM::UMinOp, LLVM::MaxNumOp, LLVM::MinNumOp,
6795 mlir::arith::MaxSIOp, mlir::arith::MinSIOp,
6796 mlir::arith::MaxUIOp, mlir::arith::MinUIOp,
6797 mlir::arith::MaximumFOp, mlir::arith::MinimumFOp>(op);
6817 if (isAtomicComparePatternOp(op))
6822 return moduleTranslation.lookupValue(v) != nullptr;
6824 if (!allOperandsMapped)
6828 return atomicCompareOp.emitError(
6829 "failed to translate operation inside atomic compare region");
6834 auto materializeValue = [&](
mlir::Value val) -> llvm::Value * {
6836 if (llvm::Value *existing = moduleTranslation.
lookupValue(val))
6840 if (
auto loadOp = val.getDefiningOp<LLVM::LoadOp>()) {
6841 if (loadOp->getParentRegion() == ®ion) {
6842 llvm::Value *loadAddr = moduleTranslation.
lookupValue(loadOp.getAddr());
6845 llvm::Type *loadType =
6846 moduleTranslation.
convertType(loadOp.getResult().getType());
6847 return builder.CreateLoad(loadType, loadAddr);
6855 llvm::omp::OMPAtomicCompareOp compareOp = llvm::omp::OMPAtomicCompareOp::EQ;
6856 llvm::Value *eVal =
nullptr;
6857 llvm::Value *dVal =
nullptr;
6858 bool isXBinopExpr =
false;
6864 if (isComplexPattern) {
6867 return atomicCompareOp.emitError(
6868 "unsupported comparison predicate (NE) for complex atomic compare");
6869 compareOp = llvm::omp::OMPAtomicCompareOp::EQ;
6874 if (isComplexPattern) {
6877 if (
auto selectOp = dyn_cast<LLVM::SelectOp>(op)) {
6878 dVal = materializeValue(selectOp.getTrueValue());
6884 if (yieldOp.getResults().empty())
6885 return atomicCompareOp.emitError(
6886 "failed to extract desired value (d) from atomic compare region");
6887 dVal = materializeValue(yieldOp.getResults()[0]);
6890 llvm::Value *oldComplex =
nullptr;
6891 llvm::Value *cmpOk =
nullptr;
6892 llvm::AtomicOrdering failOrdering =
6895 atomicOrdering, failOrdering,
6896 atomicCompareOp.getWeak(), oldComplex, cmpOk);
6902 if (atomicOrdering == llvm::AtomicOrdering::Release ||
6903 atomicOrdering == llvm::AtomicOrdering::AcquireRelease ||
6904 atomicOrdering == llvm::AtomicOrdering::SequentiallyConsistent) {
6905 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6906 ompBuilder->createFlush(ompLoc);
6912 atomicCompareOp, patternInfo)))
6915 eVal = patternInfo.
eVal;
6916 dVal = patternInfo.
dVal;
6922 return atomicCompareOp.emitError(
6923 "failed to extract expected value (e) from atomic compare region");
6927 if (yieldOp.getResults().empty())
6928 return atomicCompareOp.emitError(
6929 "failed to extract desired value (d) from atomic compare region");
6930 dVal = materializeValue(yieldOp.getResults()[0]);
6933 llvmAtomicX.IsSigned = isSigned;
6935 llvm::OpenMPIRBuilder::AtomicOpValue vOpVal = {
nullptr,
nullptr,
false,
6937 llvm::OpenMPIRBuilder::AtomicOpValue rOpVal = {
nullptr,
nullptr,
false,
6939 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6941 bool isWeak = atomicCompareOp.getWeak();
6943 bool savedHandleFPNegZero = ompBuilder->setHandleFPNegZero(
true);
6944 llvm::AtomicOrdering failureOrdering =
6946 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
6947 ompBuilder->createAtomicCompare(
6948 ompLoc, llvmAtomicX, vOpVal, rOpVal, eVal, dVal, atomicOrdering,
6949 compareOp, isXBinopExpr,
false,
6950 false, failureOrdering, isWeak);
6951 ompBuilder->setHandleFPNegZero(savedHandleFPNegZero);
6953 if (failed(
handleError(afterIP, *atomicCompareOp)))
6956 builder.restoreIP(*afterIP);
6961 omp::ClauseCancellationConstructType directive) {
6962 switch (directive) {
6963 case omp::ClauseCancellationConstructType::Loop:
6964 return llvm::omp::Directive::OMPD_for;
6965 case omp::ClauseCancellationConstructType::Parallel:
6966 return llvm::omp::Directive::OMPD_parallel;
6967 case omp::ClauseCancellationConstructType::Sections:
6968 return llvm::omp::Directive::OMPD_sections;
6969 case omp::ClauseCancellationConstructType::Taskgroup:
6970 return llvm::omp::Directive::OMPD_taskgroup;
6972 llvm_unreachable(
"Unhandled cancellation construct type");
6981 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6984 llvm::Value *ifCond =
nullptr;
6985 if (
Value ifVar = op.getIfExpr())
6988 llvm::omp::Directive cancelledDirective =
6991 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
6992 ompBuilder->createCancel(ompLoc, ifCond, cancelledDirective);
6994 if (failed(
handleError(afterIP, *op.getOperation())))
6997 builder.restoreIP(afterIP.get());
7004 llvm::IRBuilderBase &builder,
7009 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
7012 llvm::omp::Directive cancelledDirective =
7015 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
7016 ompBuilder->createCancellationPoint(ompLoc, cancelledDirective);
7018 if (failed(
handleError(afterIP, *op.getOperation())))
7021 builder.restoreIP(afterIP.get());
7031 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
7033 auto threadprivateOp = cast<omp::ThreadprivateOp>(opInst);
7038 Value symAddr = threadprivateOp.getSymAddr();
7041 if (
auto asCast = dyn_cast<LLVM::AddrSpaceCastOp>(symOp))
7044 if (!isa<LLVM::AddressOfOp>(symOp))
7045 return opInst.
emitError(
"Addressing symbol not found");
7046 LLVM::AddressOfOp addressOfOp = dyn_cast<LLVM::AddressOfOp>(symOp);
7048 LLVM::GlobalOp global =
7049 addressOfOp.getGlobal(moduleTranslation.
symbolTable());
7050 llvm::GlobalValue *globalValue = moduleTranslation.
lookupGlobal(global);
7051 llvm::Type *type = globalValue->getValueType();
7052 llvm::TypeSize typeSize = builder.getDataLayout().getTypeStoreSize(type);
7053 llvm::ConstantInt *size = builder.getInt64(typeSize.getFixedValue());
7054 llvm::Value *callInst = ompBuilder->createCachedThreadPrivate(
7055 ompLoc, globalValue, size, global.getSymName() +
".cache");
7061static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind
7063 switch (deviceClause) {
7064 case mlir::omp::DeclareTargetDeviceType::host:
7065 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseHost;
7067 case mlir::omp::DeclareTargetDeviceType::nohost:
7068 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNoHost;
7070 case mlir::omp::DeclareTargetDeviceType::any:
7071 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny;
7074 llvm_unreachable(
"unhandled device clause");
7077static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind
7079 mlir::omp::DeclareTargetCaptureClause captureClause) {
7080 switch (captureClause) {
7081 case mlir::omp::DeclareTargetCaptureClause::to:
7082 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo;
7083 case mlir::omp::DeclareTargetCaptureClause::link:
7084 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink;
7085 case mlir::omp::DeclareTargetCaptureClause::enter:
7086 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter;
7087 case mlir::omp::DeclareTargetCaptureClause::none:
7088 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
7090 llvm_unreachable(
"unhandled capture clause");
7095 if (
auto addrCast = dyn_cast_if_present<LLVM::AddrSpaceCastOp>(op))
7097 if (
auto addressOfOp = dyn_cast_if_present<LLVM::AddressOfOp>(op)) {
7098 auto modOp = addressOfOp->getParentOfType<mlir::ModuleOp>();
7099 return modOp.lookupSymbol(addressOfOp.getGlobalName());
7106 if (
auto addrCast = dyn_cast_if_present<LLVM::AddrSpaceCastOp>(op))
7107 value = addrCast.getOperand();
7131 if (!llvmVarTy->isPointerTy())
7135 if (
auto gop = dyn_cast<LLVM::GlobalOp>(globalOp))
7136 return moduleTranslation.
convertType(gop.getGlobalType());
7139 dyn_cast_if_present<LLVM::AllocaOp>(baseVar.
getDefiningOp()))
7140 return moduleTranslation.
convertType(allocaOp.getElemType());
7142 if (llvm::Value *baseLlvm = moduleTranslation.
lookupValue(baseVar))
7143 if (
auto *allocaInst = dyn_cast<llvm::AllocaInst>(baseLlvm))
7144 return allocaInst->getAllocatedType();
7153 llvm::IRBuilderBase &builder,
const llvm::DataLayout &dataLayout) {
7155 dyn_cast_if_present<LLVM::AllocaOp>(baseVar.
getDefiningOp())) {
7156 if (
Value arraySize = allocaOp.getArraySize()) {
7157 llvm::Type *elemTy =
7158 moduleTranslation.
convertType(allocaOp.getElemType());
7159 llvm::Value *numElems = moduleTranslation.
lookupValue(arraySize);
7160 if (!numElems->getType()->isIntegerTy(64))
7161 numElems = builder.CreateZExt(numElems, builder.getInt64Ty());
7162 uint64_t elemSize = dataLayout.getTypeAllocSize(elemTy).getFixedValue();
7163 return builder.CreateMul(numElems, builder.getInt64(elemSize));
7166 if (llvm::Value *baseLlvm = moduleTranslation.
lookupValue(baseVar)) {
7167 if (
auto *allocaInst = dyn_cast<llvm::AllocaInst>(baseLlvm)) {
7168 if (allocaInst->isArrayAllocation() &&
7169 !llvm::isa<llvm::ArrayType>(allocaInst->getAllocatedType())) {
7171 dataLayout.getTypeAllocSize(allocaInst->getAllocatedType())
7173 return builder.CreateMul(allocaInst->getArraySize(),
7174 builder.getInt64(elemSize));
7178 return std::nullopt;
7181static llvm::SmallString<64>
7183 llvm::OpenMPIRBuilder &ompBuilder,
7184 llvm::vfs::FileSystem &vfs) {
7186 llvm::raw_svector_ostream os(suffix);
7189 auto fileInfoCallBack = [&loc]() {
7190 return std::pair<std::string, uint64_t>(
7191 llvm::StringRef(loc.getFilename()), loc.getLine());
7196 ompBuilder.getTargetEntryUniqueInfo(fileInfoCallBack, vfs).FileID);
7198 os <<
"_decl_tgt_ref_ptr";
7204 if (
auto declareTargetGlobal =
7205 dyn_cast_if_present<omp::DeclareTargetInterface>(
7207 omp::DeclareTargetAttr declareTargetAttr =
7208 declareTargetGlobal.getDeclareTarget();
7209 if (declareTargetAttr && declareTargetAttr.getCaptureClause() ==
7210 omp::DeclareTargetCaptureClause::link)
7217 if (
auto declareTargetGlobal =
7218 dyn_cast_if_present<omp::DeclareTargetInterface>(
7220 omp::DeclareTargetAttr declareTargetAttr =
7221 declareTargetGlobal.getDeclareTarget();
7222 if (declareTargetAttr && (declareTargetAttr.getCaptureClause() ==
7223 omp::DeclareTargetCaptureClause::to ||
7224 declareTargetAttr.getCaptureClause() ==
7225 omp::DeclareTargetCaptureClause::enter))
7244 ompBuilder->Config.hasRequiresUnifiedSharedMemory())) {
7248 if (gOp.getSymName().contains(suffix))
7253 (gOp.getSymName().str() + suffix.str()).str());
7261struct MapInfosTy : llvm::OpenMPIRBuilder::MapInfosTy {
7262 SmallVector<Operation *, 4> Mappers;
7265 void append(MapInfosTy &curInfo) {
7266 Mappers.append(curInfo.Mappers.begin(), curInfo.Mappers.end());
7267 llvm::OpenMPIRBuilder::MapInfosTy::append(curInfo);
7276struct MapInfoData : MapInfosTy {
7277 llvm::SmallVector<bool, 4> IsDeclareTarget;
7278 llvm::SmallVector<bool, 4> IsAMember;
7280 llvm::SmallVector<bool, 4> IsAMapping;
7281 llvm::SmallVector<mlir::Operation *, 4> MapClause;
7282 llvm::SmallVector<llvm::Value *, 4> OriginalValue;
7285 llvm::SmallVector<llvm::Type *, 4> BaseType;
7288 void append(MapInfoData &CurInfo) {
7289 IsDeclareTarget.append(CurInfo.IsDeclareTarget.begin(),
7290 CurInfo.IsDeclareTarget.end());
7291 MapClause.append(CurInfo.MapClause.begin(), CurInfo.MapClause.end());
7292 OriginalValue.append(CurInfo.OriginalValue.begin(),
7293 CurInfo.OriginalValue.end());
7294 BaseType.append(CurInfo.BaseType.begin(), CurInfo.BaseType.end());
7295 MapInfosTy::append(CurInfo);
7299enum class TargetDirectiveEnumTy : uint32_t {
7303 TargetEnterData = 3,
7308static TargetDirectiveEnumTy getTargetDirectiveEnumTyFromOp(Operation *op) {
7309 return llvm::TypeSwitch<Operation *, TargetDirectiveEnumTy>(op)
7310 .Case([](omp::TargetDataOp) {
return TargetDirectiveEnumTy::TargetData; })
7311 .Case([](omp::TargetEnterDataOp) {
7312 return TargetDirectiveEnumTy::TargetEnterData;
7314 .Case([&](omp::TargetExitDataOp) {
7315 return TargetDirectiveEnumTy::TargetExitData;
7317 .Case([&](omp::TargetUpdateOp) {
7318 return TargetDirectiveEnumTy::TargetUpdate;
7320 .Case([&](omp::TargetOp) {
return TargetDirectiveEnumTy::Target; })
7321 .Default([&](Operation *op) {
return TargetDirectiveEnumTy::None; });
7328 if (
auto nestedArrTy = llvm::dyn_cast_if_present<LLVM::LLVMArrayType>(
7329 arrTy.getElementType()))
7343 if (mapOp.getVarPtrPtr())
7360 return bitEnumContainsAll(mapType, omp::ClauseMapFlags::priv |
7361 omp::ClauseMapFlags::target_param |
7362 omp::ClauseMapFlags::attach);
7377 llvm::Value *basePointer,
7378 llvm::Type *baseType,
7379 llvm::IRBuilderBase &builder,
7381 if (
auto memberClause =
7382 mlir::dyn_cast_if_present<mlir::omp::MapInfoOp>(clauseOp)) {
7387 if (!memberClause.getBounds().empty()) {
7388 llvm::Value *elementCount = builder.getInt64(1);
7389 for (
auto bounds : memberClause.getBounds()) {
7390 if (
auto boundOp = mlir::dyn_cast_if_present<mlir::omp::MapBoundsOp>(
7391 bounds.getDefiningOp())) {
7396 elementCount = builder.CreateMul(
7400 moduleTranslation.
lookupValue(boundOp.getUpperBound()),
7401 moduleTranslation.
lookupValue(boundOp.getLowerBound())),
7402 builder.getInt64(1)));
7409 if (
auto arrTy = llvm::dyn_cast_if_present<LLVM::LLVMArrayType>(type))
7417 llvm::Value *sizeCalc = builder.CreateMul(
7418 elementCount, builder.getInt64(underlyingTypeSzInBits / 8),
7456 return builder.CreateSelect(
7457 builder.CreateICmpEQ(sizeCalc, builder.getInt64(0)),
7458 builder.getInt64(1), sizeCalc);
7472static llvm::omp::OpenMPOffloadMappingFlags
7474 const bool hasExplicitMap =
7475 (mlirFlags &
~omp::ClauseMapFlags::is_device_ptr) !=
7476 omp::ClauseMapFlags::none;
7478 llvm::omp::OpenMPOffloadMappingFlags mapType =
7479 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7481 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::to))
7482 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
7484 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::from))
7485 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7487 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::always))
7488 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
7490 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::del))
7491 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
7493 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::return_param))
7494 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
7496 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::priv))
7497 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRIVATE;
7499 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::literal))
7500 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL;
7502 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::implicit))
7503 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
7505 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::close))
7506 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
7508 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::present))
7509 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
7511 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::ompx_hold))
7512 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
7514 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::attach))
7515 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH;
7517 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::target_param))
7518 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7520 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::is_device_ptr)) {
7521 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7522 if (!hasExplicitMap)
7523 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL;
7530 if (StringAttr name = mapOp.getNameAttr())
7531 return name.getValue();
7539 ArrayRef<Value> useDevAddrOperands = {},
7540 ArrayRef<Value> hasDevAddrOperands = {}) {
7542 auto checkRefPtrOrPteeMapWithAttach = [](omp::ClauseMapFlags mapType) {
7544 bitEnumContainsAll(mapType, omp::ClauseMapFlags::ref_ptr) ||
7545 bitEnumContainsAll(mapType, omp::ClauseMapFlags::ref_ptee);
7546 return hasRefType &&
7547 bitEnumContainsAll(mapType, omp::ClauseMapFlags::attach);
7550 auto checkIsAMember = [](
const auto &mapVars,
auto mapOp) {
7558 for (Value mapValue : mapVars) {
7559 auto map = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
7560 for (
auto member : map.getMembers())
7561 if (member == mapOp)
7568 for (Value mapValue : mapVars) {
7569 auto mapOp = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
7570 bool isAttachStyleMap =
7571 checkRefPtrOrPteeMapWithAttach(mapOp.getMapType()) ||
7573 Value offloadPtr = (mapOp.getVarPtrPtr() && !isAttachStyleMap)
7574 ? mapOp.getVarPtrPtr()
7575 : mapOp.getVarPtr();
7576 mapData.OriginalValue.push_back(moduleTranslation.
lookupValue(offloadPtr));
7577 mapData.Pointers.push_back(
7578 isAttachStyleMap ? moduleTranslation.
lookupValue(mapOp.getVarPtrPtr())
7579 : mapData.OriginalValue.back());
7581 if (llvm::Value *refPtr =
7583 mapData.IsDeclareTarget.push_back(
true);
7584 mapData.BasePointers.push_back(refPtr);
7586 mapData.IsDeclareTarget.push_back(
true);
7587 mapData.BasePointers.push_back(mapData.OriginalValue.back());
7589 mapData.IsDeclareTarget.push_back(
false);
7590 mapData.BasePointers.push_back(mapData.OriginalValue.back());
7596 mapData.BaseType.push_back(moduleTranslation.
convertType(
7597 mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtrType().value()
7598 : mapOp.getVarPtrType()));
7605 mlir::Type sizeType = (isAttachStyleMap || !mapOp.getVarPtrPtr())
7606 ? mapOp.getVarPtrType()
7607 : mapOp.getVarPtrPtrType().value();
7609 dl, sizeType, isAttachStyleMap ?
nullptr : mapOp,
7610 mapData.Pointers.back(), moduleTranslation.
convertType(sizeType),
7611 builder, moduleTranslation));
7612 mapData.MapClause.push_back(mapOp.getOperation());
7615 mapData.HasAttachPtr.push_back(
false);
7619 mapData.DevicePointers.push_back(llvm::OpenMPIRBuilder::DeviceInfoTy::None);
7620 if (mapOp.getMapperId())
7621 mapData.Mappers.push_back(
7623 mapOp, mapOp.getMapperIdAttr()));
7625 mapData.Mappers.push_back(
nullptr);
7626 mapData.IsAMapping.push_back(
true);
7627 mapData.IsAMember.push_back(checkIsAMember(mapVars, mapOp));
7630 auto findMapInfo = [&mapData](llvm::Value *val,
7631 llvm::OpenMPIRBuilder::DeviceInfoTy devInfoTy,
7632 size_t memberCount) {
7635 for (llvm::Value *basePtr : mapData.OriginalValue) {
7636 auto mapOp = cast<omp::MapInfoOp>(mapData.MapClause[index]);
7647 (mapData.Types[index] &
7648 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH) ==
7649 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH;
7650 if (!isAttachMap && basePtr == val && mapData.IsAMapping[index] &&
7651 memberCount == mapOp.getMembers().size()) {
7653 mapData.Types[index] |=
7654 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
7655 mapData.DevicePointers[index] = devInfoTy;
7663 auto addDevInfos = [&](
const llvm::ArrayRef<Value> &useDevOperands,
7664 llvm::OpenMPIRBuilder::DeviceInfoTy devInfoTy) {
7665 for (Value mapValue : useDevOperands) {
7666 auto mapOp = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
7668 mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtr() : mapOp.getVarPtr();
7669 llvm::Value *origValue = moduleTranslation.
lookupValue(offloadPtr);
7672 if (!findMapInfo(origValue, devInfoTy, mapOp.getMembers().size())) {
7673 mapData.OriginalValue.push_back(origValue);
7674 mapData.Pointers.push_back(mapData.OriginalValue.back());
7675 mapData.IsDeclareTarget.push_back(
false);
7676 mapData.BasePointers.push_back(mapData.OriginalValue.back());
7677 mlir::Type baseTy = mapOp.getVarPtrPtr()
7678 ? mapOp.getVarPtrPtrType().value()
7679 : mapOp.getVarPtrType();
7680 mapData.BaseType.push_back(moduleTranslation.
convertType(baseTy));
7681 mapData.Sizes.push_back(builder.getInt64(0));
7682 mapData.MapClause.push_back(mapOp.getOperation());
7683 mapData.Types.push_back(
7684 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM);
7686 mapData.HasAttachPtr.push_back(
false);
7690 mapData.DevicePointers.push_back(devInfoTy);
7691 mapData.Mappers.push_back(
nullptr);
7692 mapData.IsAMapping.push_back(
false);
7693 mapData.IsAMember.push_back(checkIsAMember(useDevOperands, mapOp));
7698 addDevInfos(useDevAddrOperands, llvm::OpenMPIRBuilder::DeviceInfoTy::Address);
7699 addDevInfos(useDevPtrOperands, llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer);
7701 for (Value mapValue : hasDevAddrOperands) {
7702 auto mapOp = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
7704 mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtr() : mapOp.getVarPtr();
7705 llvm::Value *origValue = moduleTranslation.
lookupValue(offloadPtr);
7707 auto mapTypeAlways = llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
7709 (mapOp.getMapType() & omp::ClauseMapFlags::is_device_ptr) !=
7710 omp::ClauseMapFlags::none;
7712 mapData.OriginalValue.push_back(origValue);
7713 mapData.BasePointers.push_back(origValue);
7714 mapData.Pointers.push_back(origValue);
7715 mapData.IsDeclareTarget.push_back(
false);
7717 mlir::Type baseTy = mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtrType().value()
7718 : mapOp.getVarPtrType();
7719 mapData.BaseType.push_back(moduleTranslation.
convertType(baseTy));
7720 mapData.Sizes.push_back(builder.getInt64(dl.
getTypeSize(baseTy)));
7722 mapData.MapClause.push_back(mapOp.getOperation());
7723 if (llvm::to_underlying(mapType & mapTypeAlways)) {
7727 mapData.Types.push_back(mapType);
7729 mapData.HasAttachPtr.push_back(
false);
7733 if (mapOp.getMapperId()) {
7734 mapData.Mappers.push_back(
7736 mapOp, mapOp.getMapperIdAttr()));
7738 mapData.Mappers.push_back(
nullptr);
7743 mapData.Types.push_back(
7744 isDevicePtr ? mapType
7745 : llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
7747 mapData.HasAttachPtr.push_back(
false);
7748 mapData.Mappers.push_back(
nullptr);
7753 mapData.DevicePointers.push_back(
7754 isDevicePtr ? llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer
7755 : llvm::OpenMPIRBuilder::DeviceInfoTy::Address);
7756 mapData.IsAMapping.push_back(
false);
7757 mapData.IsAMember.push_back(checkIsAMember(hasDevAddrOperands, mapOp));
7762 auto *res = llvm::find(mapData.MapClause, memberOp);
7763 assert(res != mapData.MapClause.end() &&
7764 "MapInfoOp for member not found in MapData, cannot return index");
7765 return std::distance(mapData.MapClause.begin(), res);
7769 omp::MapInfoOp mapInfo,
bool first =
true) {
7770 ArrayAttr indexAttr = mapInfo.getMembersIndexAttr();
7780 auto memberIndicesA = cast<ArrayAttr>(indexAttr[a]);
7781 auto memberIndicesB = cast<ArrayAttr>(indexAttr[b]);
7783 for (auto it : llvm::zip(memberIndicesA, memberIndicesB)) {
7784 int64_t aIndex = mlir::cast<IntegerAttr>(std::get<0>(it)).getInt();
7785 int64_t bIndex = mlir::cast<IntegerAttr>(std::get<1>(it)).getInt();
7787 if (aIndex == bIndex)
7790 if (aIndex < bIndex)
7793 if (aIndex > bIndex)
7800 bool memberAParent = memberIndicesA.size() < memberIndicesB.size();
7802 occludedChildren.push_back(
b);
7804 occludedChildren.push_back(a);
7805 return memberAParent;
7808 for (
auto v : occludedChildren)
7815 ArrayAttr indexAttr = mapInfo.getMembersIndexAttr();
7817 if (indexAttr.size() == 1)
7818 return cast<omp::MapInfoOp>(mapInfo.getMembers()[0].getDefiningOp());
7822 return llvm::cast<omp::MapInfoOp>(
7823 mapInfo.getMembers()[
indices.front()].getDefiningOp());
7846static std::vector<llvm::Value *>
7848 llvm::IRBuilderBase &builder,
bool isArrayTy,
7850 std::vector<llvm::Value *> idx;
7851 isByteOffset =
false;
7862 idx.push_back(builder.getInt64(0));
7863 for (
int i = bounds.size() - 1; i >= 0; --i) {
7864 if (
auto boundOp = dyn_cast_if_present<omp::MapBoundsOp>(
7865 bounds[i].getDefiningOp())) {
7866 idx.push_back(moduleTranslation.
lookupValue(boundOp.getLowerBound()));
7871 llvm::Value *offset = builder.getInt64(0);
7872 for (
Value bound : bounds) {
7874 dyn_cast_if_present<omp::MapBoundsOp>(bound.getDefiningOp());
7875 if (!boundOp || !boundOp.getStride())
7880 isByteOffset = boundOp.getStrideInBytes();
7883 for (
Value bound : bounds) {
7885 dyn_cast_if_present<omp::MapBoundsOp>(bound.getDefiningOp());
7886 if (!boundOp || !boundOp.getStride())
7901 moduleTranslation.
lookupValue(boundOp.getLowerBound());
7902 llvm::Value *stride =
7903 moduleTranslation.
lookupValue(boundOp.getStride());
7904 offset = builder.CreateAdd(offset, builder.CreateMul(lb, stride));
7906 idx.push_back(offset);
7908 for (
int i = bounds.size() - 1; i >= 0; --i) {
7909 if (
auto boundOp = dyn_cast_if_present<omp::MapBoundsOp>(
7910 bounds[i].getDefiningOp())) {
7923 if (i == ((
int)bounds.size() - 1))
7925 moduleTranslation.
lookupValue(boundOp.getLowerBound()));
7927 idx.back() = builder.CreateAdd(
7928 builder.CreateMul(idx.back(), moduleTranslation.
lookupValue(
7929 boundOp.getExtent())),
7930 moduleTranslation.
lookupValue(boundOp.getLowerBound()));
7940 llvm::transform(values, std::back_inserter(ints), [](
Attribute value) {
7941 return cast<IntegerAttr>(value).getInt();
7949 omp::MapInfoOp parentOp) {
7951 if (parentOp.getMembers().empty())
7955 if (parentOp.getMembers().size() == 1) {
7956 overlapMapDataIdxs.push_back(0);
7960 ArrayAttr indexAttr = parentOp.getMembersIndexAttr();
7961 size_t numMembers = indexAttr.size();
7965 for (
auto [i, indicesAttr] : llvm::enumerate(indexAttr))
7966 getAsIntegers(cast<ArrayAttr>(indicesAttr), memberIndices[i]);
7972 llvm::SmallDenseSet<size_t> skipIndices;
7973 for (
size_t i = 0; i < numMembers; ++i) {
7974 const auto &iIndices = memberIndices[i];
7975 for (
size_t j = 0;
j < numMembers; ++
j) {
7978 const auto &jIndices = memberIndices[
j];
7980 if (jIndices.size() < iIndices.size() &&
7981 std::equal(jIndices.begin(), jIndices.end(), iIndices.begin())) {
7982 skipIndices.insert(i);
7989 for (
size_t i = 0; i < numMembers; ++i)
7990 if (!skipIndices.contains(i))
7991 overlapMapDataIdxs.push_back(i);
8005 llvm::OpenMPIRBuilder &ompBuilder, MapInfoData &mapData,
8006 size_t mapDataIdx, MapInfosTy &combinedInfo,
8007 TargetDirectiveEnumTy targetDirective,
8008 llvm::omp::OpenMPOffloadMappingFlags memberOfFlag =
8009 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE,
8010 bool isTargetParam =
true,
int mapDataParentIdx = -1) {
8011 auto mapFlag = mapData.Types[mapDataIdx];
8012 auto mapInfoOp = llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIdx]);
8016 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH) ==
8017 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
8023 if (isTargetParam &&
8024 (targetDirective == TargetDirectiveEnumTy::Target &&
8025 !mapData.IsDeclareTarget[mapDataIdx]) &&
8027 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
8029 if (mapInfoOp.getMapCaptureType() == omp::VariableCaptureKind::ByCopy &&
8031 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL;
8040 if (memberOfFlag != llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE) {
8041 if (!isPtrTy && !isAttachMap)
8042 ompBuilder.setCorrectMemberOfFlag(mapFlag, memberOfFlag);
8049 mapFlag &=
~llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
8059 if (isPtrTy && !isAttachMap && mapData.IsDeclareTarget[mapDataIdx])
8060 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
8069 !bitEnumContainsAll(mapInfoOp.getMapType(),
8070 omp::ClauseMapFlags::ref_ptr) &&
8071 bitEnumContainsAll(mapInfoOp.getMapType(), omp::ClauseMapFlags::ref_ptee);
8072 bool isRefPtrPtee = bitEnumContainsAll(mapInfoOp.getMapType(),
8073 omp::ClauseMapFlags::ref_ptr |
8074 omp::ClauseMapFlags::ref_ptee);
8076 if (!mapInfoOp->getParentOfType<omp::DeclareMapperOp>() &&
8077 mapDataParentIdx >= 0 && !(isRefPtee || (isRefPtrPtee && isPtrTy))) {
8078 combinedInfo.BasePointers.emplace_back(
8079 mapData.BasePointers[mapDataParentIdx]);
8081 combinedInfo.BasePointers.emplace_back(mapData.BasePointers[mapDataIdx]);
8084 combinedInfo.Pointers.emplace_back(mapData.Pointers[mapDataIdx]);
8085 combinedInfo.DevicePointers.emplace_back(
8086 memberOfFlag != llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE
8087 ? llvm::OpenMPIRBuilder::DeviceInfoTy::None
8088 : mapData.DevicePointers[mapDataIdx]);
8089 combinedInfo.Mappers.emplace_back(mapData.Mappers[mapDataIdx]);
8090 combinedInfo.Names.emplace_back(mapData.Names[mapDataIdx]);
8091 combinedInfo.Types.emplace_back(mapFlag);
8093 combinedInfo.HasAttachPtr.emplace_back(
false);
8097 combinedInfo.Sizes.emplace_back(
8099 ? builder.CreateSelect(
8100 builder.CreateIsNull(mapData.Pointers[mapDataIdx]),
8101 builder.getInt64(0), mapData.Sizes[mapDataIdx])
8102 : mapData.Sizes[mapDataIdx]);
8122 llvm::OpenMPIRBuilder &ompBuilder,
DataLayout &dl, MapInfosTy &combinedInfo,
8123 MapInfoData &mapData, uint64_t mapDataIndex,
8124 llvm::omp::OpenMPOffloadMappingFlags memberOfFlag,
8125 TargetDirectiveEnumTy targetDirective) {
8126 using MapFlags = llvm::omp::OpenMPOffloadMappingFlags;
8127 assert(!ompBuilder.Config.isTargetDevice() &&
8128 "function only supported for host device codegen");
8130 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
8131 auto *parentMapper = mapData.Mappers[mapDataIndex];
8137 MapFlags baseFlag = (targetDirective == TargetDirectiveEnumTy::Target &&
8138 !mapData.IsDeclareTarget[mapDataIndex])
8139 ? MapFlags::OMP_MAP_TARGET_PARAM
8140 : MapFlags::OMP_MAP_NONE;
8146 MapFlags parentFlags = mapData.Types[mapDataIndex];
8147 MapFlags preserve = MapFlags::OMP_MAP_TO | MapFlags::OMP_MAP_FROM |
8148 MapFlags::OMP_MAP_ALWAYS | MapFlags::OMP_MAP_CLOSE |
8149 MapFlags::OMP_MAP_PRESENT |
8150 MapFlags::OMP_MAP_OMPX_HOLD |
8151 MapFlags::OMP_MAP_IMPLICIT;
8152 baseFlag |= (parentFlags & preserve);
8154 MapFlags parentFlags = mapData.Types[mapDataIndex];
8155 MapFlags preserve = MapFlags::OMP_MAP_TO | MapFlags::OMP_MAP_FROM |
8156 MapFlags::OMP_MAP_PRESENT |
8157 MapFlags::OMP_MAP_RETURN_PARAM |
8158 MapFlags::OMP_MAP_IMPLICIT;
8159 baseFlag |= (parentFlags & preserve);
8162 combinedInfo.Types.emplace_back(baseFlag);
8164 combinedInfo.HasAttachPtr.emplace_back(
false);
8165 combinedInfo.DevicePointers.emplace_back(
8166 mapData.DevicePointers[mapDataIndex]);
8170 combinedInfo.Mappers.emplace_back(
8171 parentMapper && !parentClause.getPartialMap() ? parentMapper :
nullptr);
8173 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder,
8175 combinedInfo.BasePointers.emplace_back(mapData.BasePointers[mapDataIndex]);
8184 llvm::Value *lowAddr, *highAddr;
8185 if (!parentClause.getPartialMap()) {
8186 lowAddr = builder.CreatePointerCast(mapData.Pointers[mapDataIndex],
8187 builder.getPtrTy());
8188 highAddr = builder.CreatePointerCast(
8189 builder.CreateConstGEP1_32(mapData.BaseType[mapDataIndex],
8190 mapData.Pointers[mapDataIndex], 1),
8191 builder.getPtrTy());
8192 combinedInfo.Pointers.emplace_back(mapData.Pointers[mapDataIndex]);
8194 auto mapOp = dyn_cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
8197 lowAddr = builder.CreatePointerCast(mapData.BasePointers[firstMemberIdx],
8198 builder.getPtrTy());
8202 auto lastMemberMapInfo =
8203 cast<omp::MapInfoOp>(mapData.MapClause[lastMemberIdx]);
8212 bool isRefPteeMap = bitEnumContainsAll(lastMemberMapInfo.getMapType(),
8213 omp::ClauseMapFlags::ref_ptee) &&
8214 !bitEnumContainsAll(lastMemberMapInfo.getMapType(),
8215 omp::ClauseMapFlags::ref_ptr);
8216 llvm::Type *castType = mapData.BaseType[lastMemberIdx];
8219 moduleTranslation.
convertType(lastMemberMapInfo.getVarPtrType());
8220 highAddr = builder.CreatePointerCast(
8221 builder.CreateGEP(castType, mapData.BasePointers[lastMemberIdx],
8222 builder.getInt64(1)),
8223 builder.getPtrTy());
8224 combinedInfo.Pointers.emplace_back(mapData.BasePointers[firstMemberIdx]);
8227 llvm::Value *size = builder.CreateIntCast(
8228 builder.CreatePtrDiff(builder.getInt8Ty(), highAddr, lowAddr),
8229 builder.getInt64Ty(),
8231 combinedInfo.Sizes.push_back(size);
8239 if (!parentClause.getPartialMap()) {
8244 MapFlags mapFlag = mapData.Types[mapDataIndex];
8245 bool hasMapClose = (MapFlags(mapFlag) & MapFlags::OMP_MAP_CLOSE) ==
8246 MapFlags::OMP_MAP_CLOSE;
8247 ompBuilder.setCorrectMemberOfFlag(mapFlag, memberOfFlag);
8263 if (targetDirective == TargetDirectiveEnumTy::TargetUpdate || hasMapClose ||
8264 overlapIdxs.size() == 1) {
8265 combinedInfo.Types.emplace_back(mapFlag);
8267 combinedInfo.HasAttachPtr.emplace_back(
false);
8268 combinedInfo.DevicePointers.emplace_back(
8269 mapData.DevicePointers[mapDataIndex]);
8271 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder,
8273 cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]))));
8274 combinedInfo.BasePointers.emplace_back(
8275 mapData.BasePointers[mapDataIndex]);
8276 combinedInfo.Pointers.emplace_back(mapData.Pointers[mapDataIndex]);
8277 combinedInfo.Sizes.emplace_back(mapData.Sizes[mapDataIndex]);
8278 combinedInfo.Mappers.emplace_back(
nullptr);
8284 lowAddr = builder.CreatePointerCast(mapData.Pointers[mapDataIndex],
8285 builder.getPtrTy());
8286 highAddr = builder.CreatePointerCast(
8287 builder.CreateConstGEP1_32(mapData.BaseType[mapDataIndex],
8288 mapData.Pointers[mapDataIndex], 1),
8289 builder.getPtrTy());
8296 mapFlag &=
~llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
8303 for (
auto v : overlapIdxs) {
8306 cast<omp::MapInfoOp>(parentClause.getMembers()[v].getDefiningOp()));
8308 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataOverlapIdx]));
8309 combinedInfo.Types.emplace_back(mapFlag);
8311 combinedInfo.HasAttachPtr.emplace_back(
false);
8312 combinedInfo.DevicePointers.emplace_back(
8313 llvm::OpenMPIRBuilder::DeviceInfoTy::None);
8315 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder,
8317 cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]))));
8318 combinedInfo.BasePointers.emplace_back(
8319 mapData.BasePointers[mapDataIndex]);
8320 combinedInfo.Mappers.emplace_back(
nullptr);
8321 combinedInfo.Pointers.emplace_back(lowAddr);
8322 auto sizeCalc = builder.CreateIntCast(
8323 builder.CreatePtrDiff(builder.getInt8Ty(),
8324 mapData.OriginalValue[mapDataOverlapIdx],
8326 builder.getInt64Ty(),
true);
8331 llvm::DataLayout dataLayout = builder.getDataLayout();
8332 auto sizeSel = builder.CreateSelect(
8333 builder.CreateICmpNE(builder.getInt64(0), sizeCalc), sizeCalc,
8334 isPtrMap ? builder.getInt64(dataLayout.getPointerSize())
8335 : mapData.Sizes[mapDataOverlapIdx]);
8336 combinedInfo.Sizes.emplace_back(sizeSel);
8337 lowAddr = builder.CreateConstGEP1_32(
8338 isPtrMap ? builder.getPtrTy() : mapData.BaseType[mapDataOverlapIdx],
8339 mapData.BasePointers[mapDataOverlapIdx], 1);
8342 combinedInfo.Types.emplace_back(mapFlag);
8344 combinedInfo.HasAttachPtr.emplace_back(
false);
8345 combinedInfo.DevicePointers.emplace_back(
8346 llvm::OpenMPIRBuilder::DeviceInfoTy::None);
8348 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder,
8350 cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]))));
8351 combinedInfo.BasePointers.emplace_back(
8352 mapData.BasePointers[mapDataIndex]);
8353 combinedInfo.Mappers.emplace_back(
nullptr);
8354 combinedInfo.Pointers.emplace_back(lowAddr);
8355 combinedInfo.Sizes.emplace_back(builder.CreateIntCast(
8356 builder.CreatePtrDiff(builder.getInt8Ty(), highAddr, lowAddr),
8357 builder.getInt64Ty(),
true));
8363 llvm::IRBuilderBase &builder,
8364 llvm::OpenMPIRBuilder &ompBuilder,
8366 MapInfoData &mapData, uint64_t mapDataIndex,
8367 TargetDirectiveEnumTy targetDirective) {
8368 assert(!ompBuilder.Config.isTargetDevice() &&
8369 "function only supported for host device codegen");
8372 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
8377 if (parentClause.getMembers().size() == 1 && parentClause.getPartialMap()) {
8378 auto memberClause = llvm::cast<omp::MapInfoOp>(
8379 parentClause.getMembers()[0].getDefiningOp());
8392 builder, ompBuilder, mapData, memberDataIdx, combinedInfo,
8394 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE,
8395 true, mapDataIndex);
8399 auto collectMapInfoIdxs =
8402 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
8404 for (
auto member : parentClause.getMembers())
8406 mapData, llvm::cast<omp::MapInfoOp>(member.getDefiningOp())));
8410 collectMapInfoIdxs(mapInfoIdx);
8412 llvm::omp::OpenMPOffloadMappingFlags memberOfFlag =
8413 ompBuilder.getMemberOfFlag(combinedInfo.Types.size());
8423 bool parentIsPrivatizeableAttach =
8425 for (
auto [i, idx] : llvm::enumerate(mapInfoIdx)) {
8426 bool emitParentMap = i == 0 && !parentIsPrivatizeableAttach;
8427 if (emitParentMap) {
8429 combinedInfo, mapData, idx, memberOfFlag,
8433 builder, ompBuilder, mapData, idx, combinedInfo, targetDirective,
8434 parentIsPrivatizeableAttach
8435 ? llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE
8437 false, mapDataIndex);
8449 llvm::IRBuilderBase &builder) {
8451 "function only supported for host device codegen");
8452 for (
size_t i = 0; i < mapData.MapClause.size(); ++i) {
8453 auto mapOp = cast<omp::MapInfoOp>(mapData.MapClause[i]);
8456 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH) ==
8457 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
8462 if (!mapData.IsDeclareTarget[i] ||
8463 (mapData.IsDeclareTarget[i] && isAttachMap)) {
8464 omp::VariableCaptureKind captureKind = mapOp.getMapCaptureType();
8474 switch (captureKind) {
8475 case omp::VariableCaptureKind::ByRef: {
8476 llvm::Value *newV = mapData.Pointers[i];
8477 bool isByteOffset =
false;
8479 moduleTranslation, builder, mapData.BaseType[i]->isArrayTy(),
8480 mapOp.getBounds(), isByteOffset);
8482 newV = builder.CreateLoad(builder.getPtrTy(), newV);
8484 if (!offsetIdx.empty())
8485 newV = builder.CreateInBoundsGEP(isByteOffset ? builder.getInt8Ty()
8486 : mapData.BaseType[i],
8487 newV, offsetIdx,
"array_offset");
8488 mapData.Pointers[i] = newV;
8490 case omp::VariableCaptureKind::ByCopy: {
8491 llvm::Type *type = mapData.BaseType[i];
8493 if (mapData.Pointers[i]->getType()->isPointerTy())
8494 newV = builder.CreateLoad(type, mapData.Pointers[i]);
8496 newV = mapData.Pointers[i];
8499 auto curInsert = builder.saveIP();
8500 llvm::DebugLoc DbgLoc = builder.getCurrentDebugLocation();
8502 auto *memTempAlloc =
8503 builder.CreateAlloca(builder.getPtrTy(),
nullptr,
".casted");
8504 builder.SetCurrentDebugLocation(DbgLoc);
8505 builder.restoreIP(curInsert);
8507 builder.CreateStore(newV, memTempAlloc);
8508 newV = builder.CreateLoad(builder.getPtrTy(), memTempAlloc);
8511 mapData.Pointers[i] = newV;
8512 mapData.BasePointers[i] = newV;
8514 case omp::VariableCaptureKind::This:
8515 case omp::VariableCaptureKind::VLAType:
8516 mapData.MapClause[i]->emitOpError(
"Unhandled capture kind");
8527 MapInfoData &mapData,
8528 TargetDirectiveEnumTy targetDirective) {
8530 "function only supported for host device codegen");
8551 for (
size_t i = 0; i < mapData.MapClause.size(); ++i) {
8552 if (mapData.IsAMember[i])
8555 auto mapInfoOp = dyn_cast<omp::MapInfoOp>(mapData.MapClause[i]);
8556 if (!mapInfoOp.getMembers().empty()) {
8558 combinedInfo, mapData, i, targetDirective);
8567static llvm::Expected<llvm::Function *>
8569 LLVM::ModuleTranslation &moduleTranslation,
8570 llvm::StringRef mapperFuncName,
8571 TargetDirectiveEnumTy targetDirective);
8573static llvm::Expected<llvm::Function *>
8576 TargetDirectiveEnumTy targetDirective) {
8578 "function only supported for host device codegen");
8579 auto declMapperOp = cast<omp::DeclareMapperOp>(op);
8580 std::string mapperFuncName =
8582 {
"omp_mapper", declMapperOp.getSymName()});
8584 if (
auto *lookupFunc = moduleTranslation.
lookupFunction(mapperFuncName))
8592 if (llvm::Function *existingFunc =
8593 moduleTranslation.
getLLVMModule()->getFunction(mapperFuncName)) {
8594 moduleTranslation.
mapFunction(mapperFuncName, existingFunc);
8595 return existingFunc;
8599 mapperFuncName, targetDirective);
8602static llvm::Expected<llvm::Function *>
8605 llvm::StringRef mapperFuncName,
8606 TargetDirectiveEnumTy targetDirective) {
8608 "function only supported for host device codegen");
8609 auto declMapperOp = cast<omp::DeclareMapperOp>(op);
8610 auto declMapperInfoOp = declMapperOp.getDeclareMapperInfo();
8612 return llvm::make_error<PreviouslyReportedError>();
8616 llvm::Type *varType = moduleTranslation.
convertType(declMapperOp.getType());
8619 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
8622 MapInfosTy combinedInfo;
8624 [&](InsertPointTy codeGenIP, llvm::Value *ptrPHI,
8625 llvm::Value *unused2) -> llvm::OpenMPIRBuilder::MapInfosOrErrorTy {
8626 builder.restoreIP(codeGenIP);
8627 moduleTranslation.
mapValue(declMapperOp.getSymVal(), ptrPHI);
8628 moduleTranslation.
mapBlock(&declMapperOp.getRegion().front(),
8629 builder.GetInsertBlock());
8630 if (failed(moduleTranslation.
convertBlock(declMapperOp.getRegion().front(),
8633 return llvm::make_error<PreviouslyReportedError>();
8634 MapInfoData mapData;
8637 genMapInfos(builder, moduleTranslation, dl, combinedInfo, mapData,
8643 return combinedInfo;
8647 if (!combinedInfo.Mappers[i])
8650 moduleTranslation, targetDirective);
8654 genMapInfoCB, varType, mapperFuncName, customMapperCB,
8657 return newFn.takeError();
8658 if ([[maybe_unused]] llvm::Function *mappedFunc =
8660 assert(mappedFunc == *newFn &&
8661 "mapper function mapping disagrees with emitted function");
8663 moduleTranslation.
mapFunction(mapperFuncName, *newFn);
8669 llvm::OpenMPIRBuilder &ompBuilder,
8675 llvm::Function *parentFn = builder.GetInsertBlock()->getParent();
8676 llvm::StringRef fnName = parentFn ? parentFn->getName() :
"";
8678 fileLoc, ompBuilder, fnName, strSize);
8679 return ompBuilder.getOrCreateIdent(srcStr, strSize);
8685 llvm::Value *ifCond =
nullptr;
8686 llvm::Value *deviceID = builder.getInt64(llvm::omp::OMP_DEVICEID_UNDEF);
8690 llvm::omp::RuntimeFunction RTLFn;
8692 TargetDirectiveEnumTy targetDirective = getTargetDirectiveEnumTyFromOp(op);
8695 llvm::OpenMPIRBuilder::TargetDataInfo info(
8699 if (ompBuilder->Config.isTargetDevice())
8700 return op->
emitOpError() <<
"not allowed in a target device";
8702 bool isOffloadEntry = !ompBuilder->Config.TargetTriples.empty();
8704 auto getDeviceID = [&](
mlir::Value dev) -> llvm::Value * {
8705 llvm::Value *v = moduleTranslation.
lookupValue(dev);
8706 return builder.CreateIntCast(v, builder.getInt64Ty(),
true);
8711 .Case([&](omp::TargetDataOp dataOp) {
8715 if (
auto ifVar = dataOp.getIfExpr())
8719 deviceID = getDeviceID(devId);
8721 mapVars = dataOp.getMapVars();
8722 useDevicePtrVars = dataOp.getUseDevicePtrVars();
8723 useDeviceAddrVars = dataOp.getUseDeviceAddrVars();
8726 .Case([&](omp::TargetEnterDataOp enterDataOp) -> LogicalResult {
8730 if (
auto ifVar = enterDataOp.getIfExpr())
8734 deviceID = getDeviceID(devId);
8737 enterDataOp.getNowait()
8738 ? llvm::omp::OMPRTL___tgt_target_data_begin_nowait_mapper
8739 : llvm::omp::OMPRTL___tgt_target_data_begin_mapper;
8740 mapVars = enterDataOp.getMapVars();
8741 info.HasNoWait = enterDataOp.getNowait();
8744 .Case([&](omp::TargetExitDataOp exitDataOp) -> LogicalResult {
8748 if (
auto ifVar = exitDataOp.getIfExpr())
8752 deviceID = getDeviceID(devId);
8754 RTLFn = exitDataOp.getNowait()
8755 ? llvm::omp::OMPRTL___tgt_target_data_end_nowait_mapper
8756 : llvm::omp::OMPRTL___tgt_target_data_end_mapper;
8757 mapVars = exitDataOp.getMapVars();
8758 info.HasNoWait = exitDataOp.getNowait();
8761 .Case([&](omp::TargetUpdateOp updateDataOp) -> LogicalResult {
8765 if (
auto ifVar = updateDataOp.getIfExpr())
8769 deviceID = getDeviceID(devId);
8772 updateDataOp.getNowait()
8773 ? llvm::omp::OMPRTL___tgt_target_data_update_nowait_mapper
8774 : llvm::omp::OMPRTL___tgt_target_data_update_mapper;
8775 mapVars = updateDataOp.getMapVars();
8776 info.HasNoWait = updateDataOp.getNowait();
8779 .DefaultUnreachable(
"unexpected operation");
8784 if (!isOffloadEntry)
8785 ifCond = builder.getFalse();
8787 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
8788 MapInfoData mapData;
8790 builder, useDevicePtrVars, useDeviceAddrVars);
8793 MapInfosTy combinedInfo;
8794 auto genMapInfoCB = [&](InsertPointTy codeGenIP) -> MapInfosTy & {
8795 builder.restoreIP(codeGenIP);
8796 genMapInfos(builder, moduleTranslation, DL, combinedInfo, mapData,
8798 return combinedInfo;
8804 [&moduleTranslation](
8805 llvm::OpenMPIRBuilder::DeviceInfoTy type,
8809 for (
auto [arg, useDevVar] :
8810 llvm::zip_equal(blockArgs, useDeviceVars)) {
8812 auto getMapBasePtr = [](omp::MapInfoOp mapInfoOp) {
8813 return mapInfoOp.getVarPtrPtr() ? mapInfoOp.getVarPtrPtr()
8814 : mapInfoOp.getVarPtr();
8817 auto useDevMap = cast<omp::MapInfoOp>(useDevVar.getDefiningOp());
8818 for (
auto [mapClause, devicePointer, basePointer] : llvm::zip_equal(
8819 mapInfoData.MapClause, mapInfoData.DevicePointers,
8820 mapInfoData.BasePointers)) {
8821 auto mapOp = cast<omp::MapInfoOp>(mapClause);
8822 if (getMapBasePtr(mapOp) != getMapBasePtr(useDevMap) ||
8823 devicePointer != type)
8826 if (llvm::Value *devPtrInfoMap =
8827 mapper ? mapper(basePointer) : basePointer) {
8828 moduleTranslation.
mapValue(arg, devPtrInfoMap);
8835 using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy;
8836 auto bodyGenCB = [&](InsertPointTy codeGenIP, BodyGenTy bodyGenType)
8837 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
8840 builder.restoreIP(codeGenIP);
8841 assert(isa<omp::TargetDataOp>(op) &&
8842 "BodyGen requested for non TargetDataOp");
8843 auto blockArgIface = cast<omp::BlockArgOpenMPOpInterface>(op);
8844 Region ®ion = cast<omp::TargetDataOp>(op).getRegion();
8845 switch (bodyGenType) {
8846 case BodyGenTy::Priv:
8848 if (!info.DevicePtrInfoMap.empty()) {
8849 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Address,
8850 blockArgIface.getUseDeviceAddrBlockArgs(),
8851 useDeviceAddrVars, mapData,
8852 [&](llvm::Value *basePointer) -> llvm::Value * {
8853 if (!info.DevicePtrInfoMap[basePointer].second)
8855 return builder.CreateLoad(
8857 info.DevicePtrInfoMap[basePointer].second);
8859 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer,
8860 blockArgIface.getUseDevicePtrBlockArgs(), useDevicePtrVars,
8861 mapData, [&](llvm::Value *basePointer) {
8862 return info.DevicePtrInfoMap[basePointer].second;
8866 moduleTranslation)))
8867 return llvm::make_error<PreviouslyReportedError>();
8870 case BodyGenTy::DupNoPriv:
8871 if (info.DevicePtrInfoMap.empty()) {
8874 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Address,
8875 blockArgIface.getUseDeviceAddrBlockArgs(),
8876 useDeviceAddrVars, mapData);
8877 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer,
8878 blockArgIface.getUseDevicePtrBlockArgs(), useDevicePtrVars,
8882 case BodyGenTy::NoPriv:
8884 if (info.DevicePtrInfoMap.empty()) {
8886 moduleTranslation)))
8887 return llvm::make_error<PreviouslyReportedError>();
8891 return builder.saveIP();
8894 auto customMapperCB =
8896 if (!combinedInfo.Mappers[i])
8898 info.HasMapper =
true;
8900 moduleTranslation, targetDirective);
8903 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
8905 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
8912 llvm::Value *srcLocOverride =
8916 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP = [&]() {
8917 if (isa<omp::TargetDataOp>(op))
8918 return ompBuilder->createTargetData(
8919 ompLoc, allocaIP, builder.saveIP(), deallocBlocks, deviceID, ifCond,
8920 info, genMapInfoCB, customMapperCB,
8922 nullptr, srcLocOverride);
8923 return ompBuilder->createTargetData(
8924 ompLoc, allocaIP, builder.saveIP(), deallocBlocks, deviceID, ifCond,
8925 info, genMapInfoCB, customMapperCB, &RTLFn,
8927 nullptr, srcLocOverride);
8933 builder.restoreIP(*afterIP);
8941 auto distributeOp = cast<omp::DistributeOp>(opInst);
8948 bool doDistributeReduction =
8952 unsigned numReductionVars = teamsOp ? teamsOp.getNumReductionVars() : 0;
8957 if (doDistributeReduction) {
8958 isByRef =
getIsByRef(teamsOp.getReductionByref());
8959 assert(isByRef.size() == teamsOp.getNumReductionVars());
8962 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
8966 llvm::cast<omp::BlockArgOpenMPOpInterface>(*teamsOp)
8967 .getReductionBlockArgs();
8970 teamsOp, reductionArgs, builder, moduleTranslation, allocaIP,
8971 reductionDecls, privateReductionVariables, reductionVariableMap,
8976 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
8978 [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
8980 llvm::BasicBlock *allocaBlock = allocaIP.getNodeParent();
8982 builder.restoreIP(codeGenIP);
8986 distributeOp, builder, moduleTranslation, privVarsInfo, allocaIP);
8988 return llvm::make_error<PreviouslyReportedError>();
8994 moduleTranslation, allocaIP.getNodeParent(), deallocBlocks);
8999 return llvm::make_error<PreviouslyReportedError>();
9004 distributeOp.getPrivateNeedsBarrier())))
9005 return llvm::make_error<PreviouslyReportedError>();
9008 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
9011 builder, moduleTranslation);
9013 return regionBlock.takeError();
9014 builder.SetInsertPoint((*regionBlock)->begin());
9019 if (!isa_and_present<omp::WsloopOp>(distributeOp.getNestedWrapper())) {
9022 bool hasDistSchedule = distributeOp.getDistScheduleStatic();
9023 auto schedule = hasDistSchedule ? omp::ClauseScheduleKind::Distribute
9024 : omp::ClauseScheduleKind::Static;
9026 bool isOrdered = hasDistSchedule;
9027 std::optional<omp::ScheduleModifier> scheduleMod;
9028 bool isSimd =
false;
9029 llvm::omp::WorksharingLoopType workshareLoopType =
9030 llvm::omp::WorksharingLoopType::DistributeStaticLoop;
9031 bool loopNeedsBarrier =
false;
9032 llvm::Value *chunk = moduleTranslation.
lookupValue(
9033 distributeOp.getDistScheduleChunkSize());
9034 llvm::CanonicalLoopInfo *loopInfo =
9037 allocaIP = allocaBlock->getFirstInsertionPt();
9038 llvm::OpenMPIRBuilder::InsertPointOrErrorTy wsloopIP =
9039 ompBuilder->applyWorkshareLoop(
9040 ompLoc.DL, loopInfo, allocaIP, loopNeedsBarrier,
9041 convertToScheduleKind(schedule), chunk, isSimd,
9042 scheduleMod == omp::ScheduleModifier::monotonic,
9043 scheduleMod == omp::ScheduleModifier::nonmonotonic, isOrdered,
9044 workshareLoopType,
false, hasDistSchedule, chunk);
9047 return wsloopIP.takeError();
9050 distributeOp.getLoc(), privVarsInfo)))
9051 return llvm::make_error<PreviouslyReportedError>();
9053 return llvm::Error::success();
9057 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
9059 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
9060 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
9061 ompBuilder->createDistribute(ompLoc, allocaIP, deallocBlocks, bodyGenCB);
9066 builder.restoreIP(*afterIP);
9068 if (doDistributeReduction) {
9071 teamsOp, builder, moduleTranslation, allocaIP, reductionDecls,
9072 privateReductionVariables, isByRef,
9084 auto offloadMod = dyn_cast<omp::OffloadModuleInterface>(op);
9086 return op->
emitOpError() <<
"omp flags attached to non offload module op";
9090 if (offloadMod.getIsTargetDevice())
9091 ompBuilder->M.addModuleFlag(llvm::Module::Max,
"openmp-device",
9092 attribute.getOpenmpDeviceVersion());
9095 if (!offloadMod.getIsGPU())
9098 if (attribute.getNoGpuLib())
9101 ompBuilder->createGlobalFlag(attribute.getDebugKind(),
9102 "__omp_rtl_debug_kind");
9103 ompBuilder->createGlobalFlag(attribute.getAssumeTeamsOversubscription(),
9104 "__omp_rtl_assume_teams_oversubscription");
9105 ompBuilder->createGlobalFlag(attribute.getAssumeThreadsOversubscription(),
9106 "__omp_rtl_assume_threads_oversubscription");
9107 ompBuilder->createGlobalFlag(attribute.getAssumeNoThreadState(),
9108 "__omp_rtl_assume_no_thread_state");
9109 ompBuilder->createGlobalFlag(attribute.getAssumeNoNestedParallelism(),
9110 "__omp_rtl_assume_no_nested_parallelism");
9115 omp::TargetOp targetOp,
9116 llvm::OpenMPIRBuilder &ompBuilder,
9117 llvm::vfs::FileSystem &vfs,
9118 llvm::StringRef parentName =
"") {
9119 auto fileLoc = targetOp.getLoc()->findInstanceOf<
FileLineColLoc>();
9120 assert(fileLoc &&
"No file found from location");
9122 auto fileInfoCallBack = [&fileLoc]() {
9123 return std::pair<std::string, uint64_t>(
9124 llvm::StringRef(fileLoc.getFilename()), fileLoc.getLine());
9128 ompBuilder.getTargetEntryUniqueInfo(fileInfoCallBack, vfs, parentName);
9171 omp::TargetOp targetOp, MapInfoData &mapData, llvm::Argument &arg,
9172 llvm::Value *input, llvm::Value *&retVal, llvm::IRBuilderBase &builder,
9173 llvm::OpenMPIRBuilder &ompBuilder,
9175 llvm::IRBuilderBase::InsertPoint allocaIP,
9176 llvm::IRBuilderBase::InsertPoint codeGenIP,
9178 assert(ompBuilder.Config.isTargetDevice() &&
9179 "function only supported for target device codegen");
9180 builder.restoreIP(allocaIP);
9182 omp::VariableCaptureKind capture = omp::VariableCaptureKind::ByRef;
9184 ompBuilder.M.getContext());
9185 unsigned alignmentValue = 0;
9188 cast<omp::BlockArgOpenMPOpInterface>(*targetOp).getBlockArgsPairs(
9191 for (
size_t i = 0; i < mapData.MapClause.size(); ++i) {
9192 if (mapData.OriginalValue[i] == input) {
9193 auto mapOp = cast<omp::MapInfoOp>(mapData.MapClause[i]);
9194 capture = mapOp.getMapCaptureType();
9197 mapOp.getVarPtrType(), ompBuilder.M.getDataLayout());
9201 for (
auto &[val, arg] : blockArgsPairs) {
9202 if (mapOp.getResult() == val) {
9207 assert(mlirArg &&
"expected to find entry block argument for map clause");
9212 unsigned int allocaAS = ompBuilder.M.getDataLayout().getAllocaAddrSpace();
9213 unsigned int defaultAS =
9214 ompBuilder.M.getDataLayout().getProgramAddressSpace();
9217 llvm::Value *v =
nullptr;
9225 builder.SetInsertPoint(codeGenIP.getNodeParent()->getFirstInsertionPt());
9226 v = ompBuilder.createOMPAllocShared(builder, arg.getType());
9230 llvm::IRBuilderBase::InsertPointGuard guard(builder);
9231 for (
auto deallocIP : deallocIPs) {
9232 builder.SetInsertPoint(deallocIP);
9233 ompBuilder.createOMPFreeShared(builder, v, arg.getType());
9237 v = builder.CreateAlloca(arg.getType(), allocaAS);
9239 if (allocaAS != defaultAS && arg.getType()->isPointerTy())
9240 v = builder.CreateAddrSpaceCast(v, builder.getPtrTy(defaultAS));
9243 builder.CreateStore(&arg, v);
9245 builder.restoreIP(codeGenIP);
9248 case omp::VariableCaptureKind::ByCopy: {
9252 case omp::VariableCaptureKind::ByRef: {
9253 llvm::LoadInst *loadInst = builder.CreateAlignedLoad(
9255 ompBuilder.M.getDataLayout().getPrefTypeAlign(v->getType()));
9270 if (v->getType()->isPointerTy() && alignmentValue) {
9271 llvm::MDBuilder MDB(builder.getContext());
9272 loadInst->setMetadata(
9273 llvm::LLVMContext::MD_align,
9274 llvm::MDNode::get(builder.getContext(),
9275 MDB.createConstant(llvm::ConstantInt::get(
9276 llvm::Type::getInt64Ty(builder.getContext()),
9283 case omp::VariableCaptureKind::This:
9284 case omp::VariableCaptureKind::VLAType:
9287 assert(
false &&
"Currently unsupported capture kind");
9291 return builder.saveIP();
9308 auto blockArgIface = llvm::cast<omp::BlockArgOpenMPOpInterface>(*targetOp);
9309 for (
auto item : llvm::zip_equal(targetOp.getHostEvalVars(),
9310 blockArgIface.getHostEvalBlockArgs())) {
9311 Value hostEvalVar = std::get<0>(item), blockArg = std::get<1>(item);
9315 .Case([&](omp::TeamsOp teamsOp) {
9316 if (teamsOp.getNumTeamsLower() == blockArg)
9317 numTeamsLower = hostEvalVar;
9318 else if (llvm::is_contained(teamsOp.getNumTeamsUpperVars(),
9320 numTeamsUpper = hostEvalVar;
9321 else if (!teamsOp.getThreadLimitVars().empty() &&
9322 teamsOp.getThreadLimit(0) == blockArg)
9323 threadLimit = hostEvalVar;
9325 llvm_unreachable(
"unsupported host_eval use");
9327 .Case([&](omp::ParallelOp parallelOp) {
9328 if (!parallelOp.getNumThreadsVars().empty() &&
9329 parallelOp.getNumThreads(0) == blockArg)
9330 numThreads = hostEvalVar;
9332 llvm_unreachable(
"unsupported host_eval use");
9334 .Case([&](omp::LoopNestOp loopOp) {
9335 auto processBounds =
9339 for (
auto [i, lb] : llvm::enumerate(opBounds)) {
9340 if (lb == blockArg) {
9343 (*outBounds)[i] = hostEvalVar;
9349 processBounds(loopOp.getLoopLowerBounds(), lowerBounds);
9350 found = processBounds(loopOp.getLoopUpperBounds(), upperBounds) ||
9352 found = processBounds(loopOp.getLoopSteps(), steps) || found;
9354 assert(found &&
"unsupported host_eval use");
9356 .DefaultUnreachable(
"unsupported host_eval use");
9368template <
typename OpTy>
9373 if (OpTy casted = dyn_cast<OpTy>(op))
9376 if (immediateParent)
9377 return dyn_cast_if_present<OpTy>(op->
getParentOp());
9386 return std::nullopt;
9389 if (
auto constAttr = dyn_cast<IntegerAttr>(constOp.getValue()))
9390 return constAttr.getInt();
9392 return std::nullopt;
9397 uint64_t sizeInBytes = sizeInBits / 8;
9401template <
typename OpTy>
9403 if (op.getNumReductionVars() > 0) {
9408 members.reserve(reductions.size());
9409 for (omp::DeclareReductionOp &red : reductions) {
9413 if (red.getByrefElementType())
9414 members.push_back(*red.getByrefElementType());
9416 members.push_back(red.getType());
9419 auto structType = mlir::LLVM::LLVMStructType::getLiteral(
9435 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &attrs,
9436 bool isTargetDevice,
bool isGPU) {
9439 Value numThreads, numTeamsLower, numTeamsUpper, threadLimit;
9440 if (!isTargetDevice) {
9448 numTeamsLower = teamsOp.getNumTeamsLower();
9450 if (!teamsOp.getNumTeamsUpperVars().empty())
9451 numTeamsUpper = teamsOp.getNumTeams(0);
9452 if (!teamsOp.getThreadLimitVars().empty())
9453 threadLimit = teamsOp.getThreadLimit(0);
9457 if (!parallelOp.getNumThreadsVars().empty())
9458 numThreads = parallelOp.getNumThreads(0);
9464 int32_t minTeamsVal = 1, maxTeamsVal = -1;
9468 if (numTeamsUpper) {
9470 minTeamsVal = maxTeamsVal = *val;
9472 minTeamsVal = maxTeamsVal = 0;
9478 minTeamsVal = maxTeamsVal = 1;
9480 minTeamsVal = maxTeamsVal = -1;
9485 auto setMaxValueFromClause = [](
Value clauseValue, int32_t &
result) {
9499 int32_t targetThreadLimitVal = -1, teamsThreadLimitVal = -1;
9500 if (!targetOp.getThreadLimitVars().empty())
9501 setMaxValueFromClause(targetOp.getThreadLimit(0), targetThreadLimitVal);
9502 setMaxValueFromClause(threadLimit, teamsThreadLimitVal);
9505 int32_t maxThreadsVal = -1;
9507 setMaxValueFromClause(numThreads, maxThreadsVal);
9515 int32_t combinedMaxThreadsVal = targetThreadLimitVal;
9516 if (combinedMaxThreadsVal < 0 ||
9517 (teamsThreadLimitVal >= 0 && teamsThreadLimitVal < combinedMaxThreadsVal))
9518 combinedMaxThreadsVal = teamsThreadLimitVal;
9520 if (combinedMaxThreadsVal < 0 ||
9521 (maxThreadsVal >= 0 && maxThreadsVal < combinedMaxThreadsVal))
9522 combinedMaxThreadsVal = maxThreadsVal;
9524 int32_t reductionDataSize = 0;
9525 if (isGPU && capturedOp) {
9532 omp::TargetExecMode execMode = targetOp.getKernelType();
9534 case omp::TargetExecMode::bare:
9535 attrs.ExecFlags = llvm::omp::OMP_TGT_EXEC_MODE_BARE;
9537 case omp::TargetExecMode::generic:
9538 attrs.ExecFlags = llvm::omp::OMP_TGT_EXEC_MODE_GENERIC;
9540 case omp::TargetExecMode::spmd:
9541 attrs.ExecFlags = llvm::omp::OMP_TGT_EXEC_MODE_SPMD;
9543 case omp::TargetExecMode::spmd_no_loop:
9544 attrs.ExecFlags = llvm::omp::OMP_TGT_EXEC_MODE_SPMD_NO_LOOP;
9547 attrs.MinTeams.front() = minTeamsVal;
9548 attrs.MaxTeams.front() = maxTeamsVal;
9549 attrs.MinThreads.front() = 1;
9550 attrs.MaxThreads.front() = combinedMaxThreadsVal;
9551 attrs.ReductionDataSize = reductionDataSize;
9563 omp::TargetOp targetOp,
Operation *capturedOp,
9564 llvm::OpenMPIRBuilder::TargetKernelRuntimeAttrs &attrs) {
9566 unsigned numLoops = loopOp ? loopOp.getNumLoops() : 0;
9568 Value numThreads, numTeamsLower, numTeamsUpper, teamsThreadLimit;
9572 teamsThreadLimit, &lowerBounds, &upperBounds, &steps);
9575 if (!targetOp.getThreadLimitVars().empty()) {
9576 Value targetThreadLimit = targetOp.getThreadLimit(0);
9577 attrs.TargetThreadLimit.front() =
9585 attrs.MinTeams.front() = builder.CreateSExtOrTrunc(
9586 moduleTranslation.
lookupValue(numTeamsLower), builder.getInt32Ty());
9589 attrs.MaxTeams.front() = builder.CreateSExtOrTrunc(
9590 moduleTranslation.
lookupValue(numTeamsUpper), builder.getInt32Ty());
9592 if (teamsThreadLimit)
9593 attrs.TeamsThreadLimit.front() = builder.CreateSExtOrTrunc(
9594 moduleTranslation.
lookupValue(teamsThreadLimit), builder.getInt32Ty());
9597 attrs.MaxThreads.front() = moduleTranslation.
lookupValue(numThreads);
9599 if (targetOp.hasHostEvalTripCount()) {
9601 attrs.LoopTripCount =
nullptr;
9606 for (
auto [loopLower, loopUpper, loopStep] :
9607 llvm::zip_equal(lowerBounds, upperBounds, steps)) {
9608 llvm::Value *lowerBound = moduleTranslation.
lookupValue(loopLower);
9609 llvm::Value *upperBound = moduleTranslation.
lookupValue(loopUpper);
9610 llvm::Value *step = moduleTranslation.
lookupValue(loopStep);
9612 if (!lowerBound || !upperBound || !step) {
9613 attrs.LoopTripCount =
nullptr;
9617 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
9618 llvm::Value *tripCount = ompBuilder->calculateCanonicalLoopTripCount(
9619 loc, lowerBound, upperBound, step,
true,
9620 loopOp.getLoopInclusive());
9622 if (!attrs.LoopTripCount) {
9623 attrs.LoopTripCount = tripCount;
9628 attrs.LoopTripCount = builder.CreateMul(attrs.LoopTripCount, tripCount,
9633 attrs.DeviceID = builder.getInt64(llvm::omp::OMP_DEVICEID_UNDEF);
9635 attrs.DeviceID = moduleTranslation.
lookupValue(devId);
9637 builder.CreateSExtOrTrunc(attrs.DeviceID, builder.getInt64Ty());
9641static llvm::omp::OMPDynGroupprivateFallbackType
9643 omp::FallbackModifier fb = fallbackAttr ? fallbackAttr.getValue()
9644 : omp::FallbackModifier::default_mem;
9646 case omp::FallbackModifier::abort:
9647 return llvm::omp::OMPDynGroupprivateFallbackType::Abort;
9648 case omp::FallbackModifier::null:
9649 return llvm::omp::OMPDynGroupprivateFallbackType::Null;
9650 case omp::FallbackModifier::default_mem:
9651 return llvm::omp::OMPDynGroupprivateFallbackType::DefaultMem;
9654 llvm_unreachable(
"unexpected dyn_groupprivate fallback type");
9660 auto targetOp = cast<omp::TargetOp>(opInst);
9665 llvm::DebugLoc outlinedFnLoc = builder.getCurrentDebugLocation();
9674 llvm::BasicBlock *parentBB = builder.GetInsertBlock();
9675 assert(parentBB &&
"No insert block is set for the builder");
9676 llvm::Function *parentLLVMFn = parentBB->getParent();
9677 assert(parentLLVMFn &&
"Parent Function must be valid");
9678 if (llvm::DISubprogram *SP = parentLLVMFn->getSubprogram())
9679 builder.SetCurrentDebugLocation(llvm::DILocation::get(
9680 parentLLVMFn->getContext(), outlinedFnLoc.getLine(),
9681 outlinedFnLoc.getCol(), SP, outlinedFnLoc.getInlinedAt()));
9689 llvm::DebugLoc outlinedFnDbgLoc;
9690 if (outlinedFnLoc && parentLLVMFn->getSubprogram())
9691 outlinedFnDbgLoc = outlinedFnLoc;
9694 bool isTargetDevice = ompBuilder->Config.isTargetDevice();
9695 bool isGPU = ompBuilder->Config.isGPU();
9698 auto argIface = cast<omp::BlockArgOpenMPOpInterface>(opInst);
9699 auto &targetRegion = targetOp.getRegion();
9716 llvm::Function *llvmOutlinedFn =
nullptr;
9717 TargetDirectiveEnumTy targetDirective =
9718 getTargetDirectiveEnumTyFromOp(&opInst);
9722 bool isOffloadEntry =
9723 isTargetDevice || !ompBuilder->Config.TargetTriples.empty();
9743 if (!targetOp.getInReductionVars().empty() && !isTargetDevice) {
9744 inRedOrigPtrs.reserve(targetOp.getInReductionVars().size());
9745 inRedMapArgIdx.reserve(targetOp.getInReductionVars().size());
9746 for (
Value v : targetOp.getInReductionVars()) {
9751 std::optional<unsigned> matchIdx;
9752 for (
auto [idx, mapV] : llvm::enumerate(targetOp.getMapVars())) {
9753 auto mapInfo = mapV.getDefiningOp<omp::MapInfoOp>();
9754 if (v != mapInfo.getVarPtr())
9757 return targetOp.emitError()
9758 <<
"in_reduction variable on omp.target has multiple matching "
9759 "map_entries entries; the redirect target is ambiguous";
9765 "TargetOp verifier guarantees a matching map_entries entry for "
9766 "each in_reduction variable");
9767 inRedMapArgIdx.push_back(*matchIdx);
9770 inRedOrigPtrs.push_back(moduleTranslation.
lookupValue(v));
9779 if (!targetOp.getPrivateVars().empty() && !targetOp.getMapVars().empty()) {
9781 std::optional<ArrayAttr> privateSyms = targetOp.getPrivateSyms();
9782 std::optional<DenseI64ArrayAttr> privateMapIndices =
9783 targetOp.getPrivateMapsAttr();
9785 for (
auto [privVarIdx, privVarSymPair] :
9786 llvm::enumerate(llvm::zip_equal(privateVars, *privateSyms))) {
9787 auto privVar = std::get<0>(privVarSymPair);
9788 auto privSym = std::get<1>(privVarSymPair);
9790 SymbolRefAttr privatizerName = llvm::cast<SymbolRefAttr>(privSym);
9791 omp::PrivateClauseOp privatizer =
9794 if (!privatizer.needsMap())
9798 targetOp.getMappedValueForPrivateVar(privVarIdx);
9799 assert(mappedValue &&
"Expected to find mapped value for a privatized "
9800 "variable that needs mapping");
9805 auto mapInfoOp = mappedValue.
getDefiningOp<omp::MapInfoOp>();
9806 [[maybe_unused]]
Type varType = mapInfoOp.getVarPtrType();
9810 if (!isa<LLVM::LLVMPointerType>(privVar.getType()))
9812 varType == privVar.getType() &&
9813 "Type of private var doesn't match the type of the mapped value");
9817 mappedPrivateVars.insert(
9819 targetRegion.getArgument(argIface.getMapBlockArgsStart() +
9820 (*privateMapIndices)[privVarIdx])});
9824 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
9825 auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
9827 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
9828 llvm::IRBuilderBase::InsertPointGuard guard(builder);
9829 builder.SetCurrentDebugLocation(llvm::DebugLoc());
9832 llvm::Function *llvmParentFn =
9834 llvmOutlinedFn = codeGenIP.getNodeParent()->getParent();
9835 assert(llvmParentFn && llvmOutlinedFn &&
9836 "Both parent and outlined functions must exist at this point");
9838 if (outlinedFnLoc && llvmParentFn->getSubprogram())
9839 llvmOutlinedFn->setSubprogram(outlinedFnLoc->getScope()->getSubprogram());
9841 if (
auto attr = llvmParentFn->getFnAttribute(
"target-cpu");
9842 attr.isStringAttribute())
9843 llvmOutlinedFn->addFnAttr(attr);
9845 if (
auto attr = llvmParentFn->getFnAttribute(
"target-features");
9846 attr.isStringAttribute())
9847 llvmOutlinedFn->addFnAttr(attr);
9849 for (
auto [idx, arg] : llvm::enumerate(mapBlockArgs)) {
9855 if (llvm::is_contained(inRedMapArgIdx, idx))
9857 auto mapInfoOp = cast<omp::MapInfoOp>(mapVars[idx].getDefiningOp());
9858 llvm::Value *mapOpValue =
9859 moduleTranslation.
lookupValue(mapInfoOp.getVarPtr());
9860 moduleTranslation.
mapValue(arg, mapOpValue);
9862 for (
auto [arg, mapOp] : llvm::zip_equal(hdaBlockArgs, hdaVars)) {
9863 auto mapInfoOp = cast<omp::MapInfoOp>(mapOp.getDefiningOp());
9864 llvm::Value *mapOpValue =
9865 moduleTranslation.
lookupValue(mapInfoOp.getVarPtr());
9866 moduleTranslation.
mapValue(arg, mapOpValue);
9875 privateVarsInfo, allocaIP, &mappedPrivateVars);
9878 return llvm::make_error<PreviouslyReportedError>();
9880 builder.restoreIP(codeGenIP);
9882 &mappedPrivateVars),
9885 return llvm::make_error<PreviouslyReportedError>();
9888 targetOp, builder, moduleTranslation, privateVarsInfo.
mlirVars,
9890 targetOp.getPrivateNeedsBarrier(), &mappedPrivateVars)))
9891 return llvm::make_error<PreviouslyReportedError>();
9902 if (!inRedOrigPtrs.empty()) {
9908 inRedResultPtrTys.reserve(inRedMapArgIdx.size());
9909 for (
unsigned mapArgIdx : inRedMapArgIdx)
9910 inRedResultPtrTys.push_back(
9911 moduleTranslation.
convertType(mapBlockArgs[mapArgIdx].getType()));
9913 llvm::OpenMPIRBuilder::LocationDescription bodyLoc(builder);
9914 llvm::OpenMPIRBuilder::InsertPointTy redIP =
9915 ompBuilder->createTargetInReduction(
9916 bodyLoc, inRedOrigPtrs, inRedResultPtrTys,
9917 [&](
unsigned idx, llvm::Value *priv) {
9918 moduleTranslation.
mapValue(mapBlockArgs[inRedMapArgIdx[idx]],
9921 builder.restoreIP(redIP);
9925 moduleTranslation, allocaIP.getNodeParent(), deallocBlocks);
9927 targetRegion,
"omp.target", builder, moduleTranslation);
9930 return llvm::make_error<PreviouslyReportedError>();
9932 builder.SetInsertPoint(exitBlock.get()->getTerminator());
9935 targetOp.getLoc(), privateVarsInfo)))
9936 return llvm::make_error<PreviouslyReportedError>();
9938 return builder.saveIP();
9941 StringRef parentName = parentFn.getName();
9943 llvm::TargetRegionEntryInfo entryInfo;
9949 MapInfoData mapData;
9954 MapInfosTy combinedInfos;
9956 [&](llvm::OpenMPIRBuilder::InsertPointTy codeGenIP) -> MapInfosTy & {
9957 builder.restoreIP(codeGenIP);
9958 genMapInfos(builder, moduleTranslation, dl, combinedInfos, mapData,
9963 auto *nullPtr = llvm::Constant::getNullValue(builder.getPtrTy());
9964 combinedInfos.BasePointers.push_back(nullPtr);
9965 combinedInfos.Pointers.push_back(nullPtr);
9966 combinedInfos.DevicePointers.push_back(
9967 llvm::OpenMPIRBuilder::DeviceInfoTy::None);
9968 combinedInfos.Sizes.push_back(builder.getInt64(0));
9969 combinedInfos.Types.push_back(
9970 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
9971 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
9973 combinedInfos.HasAttachPtr.push_back(
false);
9974 if (!combinedInfos.Names.empty())
9975 combinedInfos.Names.push_back(nullPtr);
9976 combinedInfos.Mappers.push_back(
nullptr);
9978 return combinedInfos;
9981 auto argAccessorCB = [&](llvm::Argument &arg, llvm::Value *input,
9982 llvm::Value *&retVal, InsertPointTy allocaIP,
9983 InsertPointTy codeGenIP,
9985 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
9986 llvm::IRBuilderBase::InsertPointGuard guard(builder);
9987 builder.SetCurrentDebugLocation(llvm::DebugLoc());
9993 if (!isTargetDevice) {
9994 retVal = cast<llvm::Value>(&arg);
9999 builder, *ompBuilder, moduleTranslation,
10000 allocaIP, codeGenIP, deallocIPs);
10003 llvm::OpenMPIRBuilder::TargetKernelRuntimeAttrs runtimeAttrs;
10004 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs defaultAttrs;
10006 cast<omp::ComposableOpInterface>(*targetOp).findCapturedOp();
10008 isTargetDevice, isGPU);
10012 if (!isTargetDevice)
10014 targetCapturedOp, runtimeAttrs);
10022 for (
auto [arg, var] : llvm::zip_equal(hostEvalBlockArgs, hostEvalVars)) {
10023 llvm::Value *value = moduleTranslation.
lookupValue(var);
10024 moduleTranslation.
mapValue(arg, value);
10026 if (!llvm::isa<llvm::Constant>(value))
10027 kernelInput.push_back(value);
10030 for (
size_t i = 0, e = mapData.OriginalValue.size(); i != e; ++i) {
10040 using MapFlags = llvm::omp::OpenMPOffloadMappingFlags;
10041 bool isAttachMap = (mapData.Types[i] & MapFlags::OMP_MAP_ATTACH) ==
10042 MapFlags::OMP_MAP_ATTACH;
10043 bool isPrivateTargetParam =
10044 (mapData.Types[i] &
10045 (MapFlags::OMP_MAP_PRIVATE | MapFlags::OMP_MAP_TARGET_PARAM)) ==
10046 (MapFlags::OMP_MAP_PRIVATE | MapFlags::OMP_MAP_TARGET_PARAM);
10048 if (!mapData.IsDeclareTarget[i] && !mapData.IsAMember[i] &&
10049 (!isAttachMap || (isAttachMap && isPrivateTargetParam)))
10050 kernelInput.push_back(mapData.OriginalValue[i]);
10054 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
10057 llvm::OpenMPIRBuilder::DependenciesInfo dds;
10059 targetOp.getDependVars(), targetOp.getDependKinds(),
10060 targetOp.getDependIterated(), targetOp.getDependIteratedKinds(),
10061 builder, moduleTranslation, dds)))
10064 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
10066 llvm::OpenMPIRBuilder::TargetDataInfo info(
10070 auto customMapperCB =
10072 if (!combinedInfos.Mappers[i])
10074 info.HasMapper =
true;
10076 moduleTranslation, targetDirective);
10079 llvm::Value *ifCond =
nullptr;
10080 if (
Value targetIfCond = targetOp.getIfExpr())
10081 ifCond = moduleTranslation.
lookupValue(targetIfCond);
10083 Value dynGroupPrivateSize = targetOp.getDynGroupprivateSize();
10084 llvm::Value *dynSizeVal =
nullptr;
10085 if (dynGroupPrivateSize) {
10086 dynSizeVal = moduleTranslation.
lookupValue(dynGroupPrivateSize);
10087 dynSizeVal = builder.CreateIntCast(dynSizeVal, builder.getInt32Ty(),
10091 llvm::omp::OMPDynGroupprivateFallbackType fallbackType =
10097 llvm::Value *rtLocOverride =
10098 (!isTargetDevice && isOffloadEntry)
10102 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
10104 ompLoc, isOffloadEntry, allocaIP, builder.saveIP(), deallocBlocks,
10105 info, entryInfo, defaultAttrs, runtimeAttrs, ifCond, kernelInput,
10106 genMapInfoCB, bodyCB, argAccessorCB, customMapperCB, dds,
10107 targetOp.getNowait(), dynSizeVal, fallbackType, outlinedFnDbgLoc,
10113 builder.restoreIP(*afterIP);
10116 builder.CreateFree(dds.DepArray);
10121static LogicalResult
10123 llvm::OpenMPIRBuilder *ompBuilder,
10132 if (FunctionOpInterface funcOp = dyn_cast<FunctionOpInterface>(op)) {
10133 if (
auto offloadMod = dyn_cast<omp::OffloadModuleInterface>(
10135 if (!offloadMod.getIsTargetDevice())
10138 omp::DeclareTargetDeviceType declareType = attribute.getDeviceType();
10140 if (declareType == omp::DeclareTargetDeviceType::host) {
10141 llvm::Function *llvmFunc =
10143 llvmFunc->dropAllReferences();
10144 llvmFunc->eraseFromParent();
10148 ompBuilder->Builder.ClearInsertionPoint();
10149 ompBuilder->Builder.SetCurrentDebugLocation(llvm::DebugLoc());
10150 }
else if (llvm::Function *llvmFunc =
10162 if (!llvmFunc->isDeclaration() && llvmFunc->hasExternalLinkage() &&
10163 llvmFunc->getVisibility() == llvm::GlobalValue::DefaultVisibility)
10164 llvmFunc->setVisibility(llvm::GlobalValue::HiddenVisibility);
10170 if (LLVM::GlobalOp gOp = dyn_cast<LLVM::GlobalOp>(op)) {
10171 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
10172 if (
auto *gVal = llvmModule->getNamedValue(gOp.getSymName())) {
10173 auto *gVar = cast<llvm::GlobalVariable>(gVal);
10175 bool isDeclaration = gOp.isDeclaration();
10176 bool isExternallyVisible =
10179 llvm::StringRef mangledName = gOp.getSymName();
10180 mlir::omp::DeclareTargetCaptureClause captureClause =
10181 attribute.getCaptureClause();
10184 llvm::StringRef entryMangledName = mangledName;
10185 llvm::Constant *entryAddr = llvm::cast<llvm::Constant>(gVal);
10186 std::function<llvm::GlobalValue::LinkageTypes()> variableLinkage;
10188 bool requiresUSM = ompBuilder->Config.hasRequiresUnifiedSharedMemory();
10190 captureClause == omp::DeclareTargetCaptureClause::to ||
10191 captureClause == omp::DeclareTargetCaptureClause::enter;
10193 attribute.getDeviceType() == omp::DeclareTargetDeviceType::host;
10198 if (isToOrEnter && !isHostOnly && !requiresUSM &&
10199 gVar->hasLocalLinkage()) {
10200 gVar->setLinkage(llvm::GlobalValue::ExternalLinkage);
10201 isExternallyVisible =
true;
10205 if (ompBuilder->Config.isTargetDevice())
10206 gVar->setDSOLocal(
false);
10211 llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny &&
10212 !requiresUSM && !isDeclaration &&
10213 (gVal->hasLocalLinkage() || gVal->hasHiddenVisibility())) {
10217 entryNameStorage = (mangledName + llvm::Twine(
"_decl_tgt_entry")).str();
10218 entryMangledName = entryNameStorage;
10219 if (llvm::GlobalValue *existing =
10220 llvmModule->getNamedValue(entryMangledName)) {
10221 entryAddr = llvm::cast<llvm::Constant>(existing);
10223 entryAddr = llvm::GlobalAlias::create(
10224 gVal->getValueType(), gVal->getAddressSpace(),
10225 llvm::GlobalValue::WeakAnyLinkage, entryMangledName, entryAddr,
10227 llvm::cast<llvm::GlobalAlias>(entryAddr)->setVisibility(
10228 llvm::GlobalValue::DefaultVisibility);
10230 variableLinkage = [] {
return llvm::GlobalValue::WeakAnyLinkage; };
10234 std::vector<llvm::GlobalVariable *> generatedRefs;
10236 std::vector<llvm::Triple> targetTriple;
10237 auto targetTripleAttr = dyn_cast_or_null<mlir::StringAttr>(
10239 LLVM::LLVMDialect::getTargetTripleAttrName()));
10240 if (targetTripleAttr)
10241 targetTriple.emplace_back(targetTripleAttr.data());
10243 auto fileInfoCallBack = [&loc]() {
10244 std::string filename =
"";
10245 std::uint64_t lineNo = 0;
10248 filename = loc.getFilename().str();
10249 lineNo = loc.getLine();
10252 return std::pair<std::string, std::uint64_t>(llvm::StringRef(filename),
10256 llvm::vfs::FileSystem &vfs = moduleTranslation.
getFileSystem();
10257 ompBuilder->registerTargetGlobalVariable(
10258 captureClauseKind, deviceClause, isDeclaration, isExternallyVisible,
10259 ompBuilder->getTargetEntryUniqueInfo(fileInfoCallBack, vfs),
10260 entryMangledName, generatedRefs,
false, targetTriple,
10261 nullptr, variableLinkage, gVal->getType(),
10264 if (ompBuilder->Config.isTargetDevice() &&
10265 (captureClause == omp::DeclareTargetCaptureClause::link ||
10270 llvm::Type *ptrTy = llvm::PointerType::get(llvmModule->getContext(), 0);
10271 llvm::Constant *refPtr = ompBuilder->getAddrOfDeclareTargetVar(
10272 captureClauseKind, deviceClause, isDeclaration, isExternallyVisible,
10273 ompBuilder->getTargetEntryUniqueInfo(fileInfoCallBack, vfs),
10274 mangledName, generatedRefs,
false, targetTriple,
10285 if (!gVar->isDeclaration())
10286 gVar->setLinkage(llvm::GlobalValue::InternalLinkage);
10292 dyn_cast<llvm::GlobalValue>(refPtr->stripPointerCasts()))
10293 ompBuilder->registerDeclareTargetGlobalReplacement(gVal, newGV);
10300 if (ompBuilder->Config.isTargetDevice() && isHostOnly && isToOrEnter) {
10301 gVar->setLinkage(llvm::GlobalValue::ExternalLinkage);
10302 gVar->setInitializer(
nullptr);
10314class OpenMPDialectLLVMIRTranslationInterface
10315 :
public LLVMTranslationDialectInterface {
10317 using LLVMTranslationDialectInterface::LLVMTranslationDialectInterface;
10322 convertOperation(Operation *op, llvm::IRBuilderBase &builder,
10323 LLVM::ModuleTranslation &moduleTranslation)
const final;
10328 amendOperation(Operation *op, ArrayRef<llvm::Instruction *> instructions,
10329 NamedAttribute attribute,
10330 LLVM::ModuleTranslation &moduleTranslation)
const final;
10335 void registerAllocatedPtr(Value var, llvm::Value *ptr)
const {
10336 ompAllocatedPtrs[var] = ptr;
10341 llvm::Value *lookupAllocatedPtr(Value var)
const {
10342 auto it = ompAllocatedPtrs.find(var);
10343 return it != ompAllocatedPtrs.end() ? it->second :
nullptr;
10355LogicalResult OpenMPDialectLLVMIRTranslationInterface::amendOperation(
10356 Operation *op, ArrayRef<llvm::Instruction *> instructions,
10357 NamedAttribute attribute,
10358 LLVM::ModuleTranslation &moduleTranslation)
const {
10359 return llvm::StringSwitch<llvm::function_ref<LogicalResult(Attribute)>>(
10361 .Case(
"omp.is_target_device",
10362 [&](Attribute attr) {
10363 if (
auto deviceAttr = dyn_cast<BoolAttr>(attr)) {
10364 llvm::OpenMPIRBuilderConfig &config =
10366 config.setIsTargetDevice(deviceAttr.getValue());
10371 .Case(
"omp.is_gpu",
10372 [&](Attribute attr) {
10373 if (
auto gpuAttr = dyn_cast<BoolAttr>(attr)) {
10374 llvm::OpenMPIRBuilderConfig &config =
10376 config.setIsGPU(gpuAttr.getValue());
10381 .Case(
"omp.host_ir_filepath",
10382 [&](Attribute attr) {
10383 if (
auto filepathAttr = dyn_cast<StringAttr>(attr)) {
10384 llvm::OpenMPIRBuilder *ompBuilder =
10386 ompBuilder->loadOffloadInfoMetadata(
10387 moduleTranslation.
getFileSystem(), filepathAttr.getValue());
10393 [&](Attribute attr) {
10394 if (
auto rtlAttr = dyn_cast<omp::FlagsAttr>(attr))
10398 .Case(
"omp.version",
10399 [&](Attribute attr) {
10400 if (
auto versionAttr = dyn_cast<omp::VersionAttr>(attr)) {
10401 llvm::OpenMPIRBuilder *ompBuilder =
10403 ompBuilder->M.addModuleFlag(llvm::Module::Max,
"openmp",
10404 versionAttr.getVersion());
10409 .Case(
"omp.declare_target",
10410 [&](Attribute attr) {
10411 if (
auto declareTargetAttr =
10412 dyn_cast<omp::DeclareTargetAttr>(attr)) {
10413 llvm::OpenMPIRBuilder *ompBuilder =
10416 ompBuilder, moduleTranslation);
10420 .Case(
"omp.requires",
10421 [&](Attribute attr) {
10422 if (
auto requiresAttr = dyn_cast<omp::ClauseRequiresAttr>(attr)) {
10423 using Requires = omp::ClauseRequires;
10424 Requires flags = requiresAttr.getValue();
10425 llvm::OpenMPIRBuilderConfig &config =
10427 config.setHasRequiresReverseOffload(
10428 bitEnumContainsAll(flags, Requires::reverse_offload));
10429 config.setHasRequiresUnifiedAddress(
10430 bitEnumContainsAll(flags, Requires::unified_address));
10431 config.setHasRequiresUnifiedSharedMemory(
10432 bitEnumContainsAll(flags, Requires::unified_shared_memory));
10433 config.setHasRequiresDynamicAllocators(
10434 bitEnumContainsAll(flags, Requires::dynamic_allocators));
10439 .Case(
"omp.target_triples",
10440 [&](Attribute attr) {
10441 if (
auto triplesAttr = dyn_cast<ArrayAttr>(attr)) {
10442 llvm::OpenMPIRBuilderConfig &config =
10444 config.TargetTriples.clear();
10445 config.TargetTriples.reserve(triplesAttr.size());
10446 for (Attribute tripleAttr : triplesAttr) {
10447 if (
auto tripleStrAttr = dyn_cast<StringAttr>(tripleAttr))
10448 config.TargetTriples.emplace_back(tripleStrAttr.getValue());
10456 .Case(
"omp.integer_wrap_around",
10457 [&](Attribute attr) {
10458 if (
auto wrapAttr = dyn_cast<omp::IntegerWrapAroundAttr>(attr)) {
10459 llvm::OpenMPIRBuilderConfig &config =
10461 config.setNoSignedWrap(!wrapAttr.getIntegerWrapAround());
10466 .Default([](Attribute) {
10482 if (
auto declareTargetIface =
10483 llvm::dyn_cast<mlir::omp::DeclareTargetInterface>(
10484 parentFn.getOperation())) {
10485 omp::DeclareTargetAttr declareTargetAttr =
10486 declareTargetIface.getDeclareTarget();
10487 if (declareTargetAttr && declareTargetAttr.getDeviceType() !=
10488 mlir::omp::DeclareTargetDeviceType::host)
10499 llvm::Module *llvmModule) {
10500 llvm::Type *i64Ty = builder.getInt64Ty();
10501 llvm::Type *i32Ty = builder.getInt32Ty();
10502 llvm::Type *returnType = builder.getPtrTy(0);
10503 llvm::FunctionType *fnType =
10504 llvm::FunctionType::get(returnType, {i64Ty, i32Ty},
false);
10505 llvm::Function *
func = cast<llvm::Function>(
10506 llvmModule->getOrInsertFunction(
"omp_target_alloc", fnType).getCallee());
10510template <
typename T>
10511static llvm::Value *
10514 llvm::DataLayout dataLayout =
10516 llvm::Type *llvmHeapTy =
10517 moduleTranslation.
convertType(op.getMemElemTypeAttr().getValue());
10519 auto alignment = op.getMemAlignment();
10520 llvm::TypeSize typeSize = llvm::alignTo(
10521 dataLayout.getTypeStoreSize(llvmHeapTy),
10522 alignment ? *alignment : dataLayout.getABITypeAlign(llvmHeapTy).value());
10524 llvm::Value *allocSize = builder.getInt64(typeSize.getFixedValue());
10525 return builder.CreateMul(
10527 builder.CreateIntCast(moduleTranslation.
lookupValue(op.getMemArraySize()),
10528 builder.getInt64Ty(),
10535 omp::TargetAllocMemOp op) {
10536 llvm::DataLayout dataLayout =
10538 llvm::Type *llvmHeapTy = moduleTranslation.
convertType(op.getAllocatedType());
10539 llvm::TypeSize typeSize = dataLayout.getTypeAllocSize(llvmHeapTy);
10540 llvm::Value *allocSize = builder.getInt64(typeSize.getFixedValue());
10541 for (
auto typeParam : op.getTypeparams()) {
10542 allocSize = builder.CreateMul(
10544 builder.CreateIntCast(moduleTranslation.
lookupValue(typeParam),
10545 builder.getInt64Ty(),
10551static LogicalResult
10554 auto allocMemOp = cast<omp::TargetAllocMemOp>(opInst);
10559 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
10563 llvm::Value *llvmDeviceNum = moduleTranslation.
lookupValue(deviceNum);
10565 llvm::Value *allocSize =
10568 llvm::CallInst *call =
10569 builder.CreateCall(ompTargetAllocFunc, {allocSize, llvmDeviceNum});
10570 llvm::Value *resultI64 = builder.CreatePtrToInt(call, builder.getInt64Ty());
10573 moduleTranslation.
mapValue(allocMemOp.getResult(), resultI64);
10577static LogicalResult
10579 llvm::IRBuilderBase &builder,
10583 moduleTranslation.
mapValue(allocMemOp.getResult(),
10584 ompBuilder->createOMPAllocShared(builder, size));
10588static LogicalResult
10591 const OpenMPDialectLLVMIRTranslationInterface &ompIface) {
10592 auto allocateDirOp = cast<omp::AllocateDirOp>(opInst);
10595 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
10596 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
10597 llvm::DataLayout dataLayout = llvmModule->getDataLayout();
10599 std::optional<int64_t> alignAttr = allocateDirOp.getAlign();
10601 llvm::Value *allocator;
10602 if (
auto allocatorVar = allocateDirOp.getAllocator()) {
10603 allocator = moduleTranslation.
lookupValue(allocatorVar);
10604 if (allocator->getType()->isIntegerTy())
10605 allocator = builder.CreateIntToPtr(allocator, builder.getPtrTy());
10606 else if (allocator->getType()->isPointerTy())
10607 allocator = builder.CreatePointerBitCastOrAddrSpaceCast(
10608 allocator, builder.getPtrTy());
10610 allocator = llvm::ConstantPointerNull::get(builder.getPtrTy());
10613 for (
Value var : vars) {
10615 llvm::Type *typeToInspect =
10620 var, baseVar, moduleTranslation, builder, dataLayout)) {
10621 size = *dynamicSize;
10622 }
else if (typeToInspect->isArrayTy()) {
10623 size = builder.getInt64(
10624 dataLayout.getTypeAllocSize(typeToInspect).getFixedValue());
10626 size = builder.getInt64(
10627 dataLayout.getTypeAllocSize(typeToInspect).getFixedValue());
10630 uint64_t alignValue =
10631 alignAttr ? alignAttr.value()
10632 : dataLayout.getABITypeAlign(typeToInspect).value();
10633 llvm::Value *alignConst = builder.getInt64(alignValue);
10635 size = builder.CreateAdd(size, builder.getInt64(alignValue - 1),
"",
true);
10636 size = builder.CreateUDiv(size, alignConst);
10637 size = builder.CreateMul(size, alignConst,
"",
true);
10639 std::string allocName =
10640 ompBuilder->createPlatformSpecificName({
".void.addr"});
10641 llvm::CallInst *allocCall;
10642 if (alignAttr.has_value()) {
10643 allocCall = ompBuilder->createOMPAlignedAlloc(
10644 ompLoc, builder.getInt64(alignAttr.value()), size, allocator,
10648 ompBuilder->createOMPAlloc(ompLoc, size, allocator, allocName);
10651 ompIface.registerAllocatedPtr(var, allocCall);
10653 if (llvm::Value *baseLlvm = moduleTranslation.
lookupValue(baseVar)) {
10654 llvm::Value *boundPtr = builder.CreatePointerBitCastOrAddrSpaceCast(
10655 allocCall, baseLlvm->getType());
10657 }
else if (llvm::Value *varLlvm = moduleTranslation.
lookupValue(var)) {
10658 llvm::Value *boundPtr = builder.CreatePointerBitCastOrAddrSpaceCast(
10659 allocCall, varLlvm->getType());
10667static LogicalResult
10670 const OpenMPDialectLLVMIRTranslationInterface &ompIface) {
10671 auto freeOp = cast<omp::AllocateFreeOp>(opInst);
10673 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
10675 llvm::Value *allocator;
10676 if (
auto allocatorVar = freeOp.getAllocator()) {
10677 allocator = moduleTranslation.
lookupValue(allocatorVar);
10678 if (allocator->getType()->isIntegerTy())
10679 allocator = builder.CreateIntToPtr(allocator, builder.getPtrTy());
10680 else if (allocator->getType()->isPointerTy())
10681 allocator = builder.CreatePointerBitCastOrAddrSpaceCast(
10682 allocator, builder.getPtrTy());
10684 allocator = llvm::ConstantPointerNull::get(builder.getPtrTy());
10689 for (
Value var : llvm::reverse(vars)) {
10690 llvm::Value *allocPtr = ompIface.lookupAllocatedPtr(var);
10692 return opInst.
emitError(
"omp.allocate_free: no allocation recorded");
10693 ompBuilder->createOMPFree(ompLoc, allocPtr, allocator,
"");
10700 llvm::Module *llvmModule) {
10701 llvm::Type *ptrTy = builder.getPtrTy(0);
10702 llvm::Type *i32Ty = builder.getInt32Ty();
10703 llvm::Type *voidTy = builder.getVoidTy();
10704 llvm::FunctionType *fnType =
10705 llvm::FunctionType::get(voidTy, {ptrTy, i32Ty},
false);
10706 llvm::Function *
func = dyn_cast<llvm::Function>(
10707 llvmModule->getOrInsertFunction(
"omp_target_free", fnType).getCallee());
10711static LogicalResult
10714 auto freeMemOp = cast<omp::TargetFreeMemOp>(opInst);
10719 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
10720 llvm::Function *ompTragetFreeFunc =
getOmpTargetFree(builder, llvmModule);
10723 llvm::Value *llvmDeviceNum = moduleTranslation.
lookupValue(deviceNum);
10726 llvm::Value *llvmHeapref = moduleTranslation.
lookupValue(heapref);
10728 llvm::Value *intToPtr =
10729 builder.CreateIntToPtr(llvmHeapref, builder.getPtrTy(0));
10730 builder.CreateCall(ompTragetFreeFunc, {intToPtr, llvmDeviceNum});
10734static LogicalResult
10736 llvm::IRBuilderBase &builder,
10740 ompBuilder->createOMPFreeShared(
10741 builder, moduleTranslation.
lookupValue(freeMemOp.getHeapref()), size);
10746static LogicalResult
10750 auto groupprivateOp = cast<omp::GroupprivateOp>(opInst);
10755 bool isTargetDevice = ompBuilder->Config.isTargetDevice();
10759 bool shouldAllocate =
true;
10760 switch (groupprivateOp.getDeviceType().value_or(
10761 mlir::omp::DeclareTargetDeviceType::any)) {
10762 case mlir::omp::DeclareTargetDeviceType::host:
10763 shouldAllocate = !isTargetDevice;
10765 case mlir::omp::DeclareTargetDeviceType::nohost:
10766 shouldAllocate = isTargetDevice;
10768 case mlir::omp::DeclareTargetDeviceType::any:
10769 shouldAllocate =
true;
10775 &opInst, groupprivateOp.getSymNameAttr());
10778 <<
"expected symbol '" << groupprivateOp.getSymName()
10779 <<
"' to reference an LLVM global variable";
10781 llvm::GlobalValue *globalValue = moduleTranslation.
lookupGlobal(global);
10782 llvm::Type *varType = moduleTranslation.
convertType(global.getType());
10783 std::string varName = globalValue->getName().str();
10785 llvm::Value *resultPtr;
10786 if (shouldAllocate && isTargetDevice) {
10787 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
10788 llvm::Triple targetTriple(llvmModule->getTargetTriple());
10789 unsigned sharedAddressSpace;
10790 if (targetTriple.isAMDGCN())
10791 sharedAddressSpace = llvm::AMDGPUAS::LOCAL_ADDRESS;
10792 else if (targetTriple.isNVPTX())
10793 sharedAddressSpace = llvm::NVPTXAS::ADDRESS_SPACE_SHARED;
10795 return opInst.
emitError() <<
"groupprivate is not supported for target: "
10796 << targetTriple.str();
10797 llvm::GlobalVariable *sharedVar =
new llvm::GlobalVariable(
10798 *llvmModule, varType,
false,
10799 llvm::GlobalValue::InternalLinkage, llvm::PoisonValue::get(varType),
10800 varName,
nullptr, llvm::GlobalValue::NotThreadLocal,
10801 sharedAddressSpace,
10803 resultPtr = sharedVar;
10805 if (shouldAllocate && !isTargetDevice)
10806 opInst.
emitWarning(
"groupprivate directive is currently ignored on the "
10807 "host, using original global");
10808 resultPtr = globalValue;
10817LogicalResult OpenMPDialectLLVMIRTranslationInterface::convertOperation(
10818 Operation *op, llvm::IRBuilderBase &builder,
10819 LLVM::ModuleTranslation &moduleTranslation)
const {
10822 if (ompBuilder->Config.isTargetDevice() &&
10823 !isa<omp::TargetOp, omp::MapInfoOp, omp::TerminatorOp, omp::YieldOp>(
10826 return op->
emitOpError() <<
"unsupported host op found in device";
10834 bool isOutermostLoopWrapper =
10835 isa_and_present<omp::LoopWrapperInterface>(op) &&
10836 !dyn_cast_if_present<omp::LoopWrapperInterface>(op->
getParentOp());
10845 if (isa<omp::TaskloopContextOp>(op))
10846 isOutermostLoopWrapper =
true;
10847 else if (isa<omp::TaskloopWrapperOp>(op))
10848 isOutermostLoopWrapper =
false;
10850 if (isOutermostLoopWrapper)
10851 moduleTranslation.
stackPush<OpenMPLoopInfoStackFrame>();
10854 llvm::TypeSwitch<Operation *, LogicalResult>(op)
10855 .Case([&](omp::BarrierOp op) -> LogicalResult {
10859 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
10860 ompBuilder->createBarrier(builder, llvm::omp::OMPD_barrier);
10862 if (res.succeeded()) {
10865 builder.restoreIP(*afterIP);
10869 .Case([&](omp::TaskyieldOp op) {
10873 ompBuilder->createTaskyield(builder);
10876 .Case([&](omp::FlushOp op) {
10888 ompBuilder->createFlush(builder);
10891 .Case([&](omp::ErrorOp op) {
10895 llvm::Value *message =
nullptr;
10896 if (mlir::Value messageExpr = op.getMessageExpr())
10897 message = moduleTranslation.
lookupValue(messageExpr);
10898 else if (std::optional<StringRef> msg = op.getMessage();
10899 msg && !msg->empty())
10900 message = builder.CreateGlobalString(*msg);
10901 ompBuilder->createError(
10902 llvm::OpenMPIRBuilder::LocationDescription(builder),
10903 op.getSeverity() == omp::ClauseSeverity::fatal, message);
10906 .Case([&](omp::ParallelOp op) {
10909 .Case([&](omp::DispatchOp) {
10912 .Case([&](omp::MaskedOp) {
10915 .Case([&](omp::MasterOp) {
10918 .Case([&](omp::CriticalOp) {
10921 .Case([&](omp::OrderedRegionOp) {
10924 .Case([&](omp::OrderedOp) {
10927 .Case([&](omp::WsloopOp) {
10930 .Case([&](omp::SimdOp) {
10933 .Case([&](omp::AtomicReadOp) {
10936 .Case([&](omp::AtomicWriteOp) {
10939 .Case([&](omp::AtomicUpdateOp op) {
10942 .Case([&](omp::AtomicCaptureOp op) {
10945 .Case([&](omp::AtomicCompareOp op) {
10948 .Case([&](omp::CancelOp op) {
10951 .Case([&](omp::CancellationPointOp op) {
10954 .Case([&](omp::SectionsOp) {
10957 .Case([&](omp::ScopeOp op) {
10960 .Case([&](omp::SingleOp op) {
10963 .Case([&](omp::TeamsOp op) {
10966 .Case([&](omp::TaskOp op) {
10969 .Case([&](omp::TaskloopWrapperOp op) {
10972 .Case([&](omp::TaskloopContextOp op) {
10975 .Case([&](omp::TaskgroupOp op) {
10978 .Case([&](omp::TaskwaitOp op) {
10981 .Case([&](omp::InteropInitOp op) {
10984 .Case([&](omp::InteropDestroyOp op) {
10987 .Case([&](omp::InteropUseOp op) {
10990 .Case<omp::YieldOp, omp::TerminatorOp, omp::DeclareMapperOp,
10991 omp::DeclareMapperInfoOp, omp::DeclareReductionOp,
10992 omp::CriticalDeclareOp>([](
auto op) {
11005 .Case([&](omp::ThreadprivateOp) {
11008 .Case<omp::TargetDataOp, omp::TargetEnterDataOp,
11009 omp::TargetExitDataOp, omp::TargetUpdateOp>([&](
auto op) {
11012 .Case([&](omp::TargetOp) {
11015 .Case([&](omp::DistributeOp) {
11018 .Case([&](omp::LoopNestOp) {
11021 .Case<omp::MapInfoOp, omp::MapBoundsOp, omp::PrivateClauseOp,
11022 omp::AffinityEntryOp, omp::IteratorOp>([&](
auto op) {
11028 .Case([&](omp::NewCliOp op) {
11033 .Case([&](omp::CanonicalLoopOp op) {
11036 .Case([&](omp::UnrollHeuristicOp op) {
11045 .Case([&](omp::UnrollFullOp op) {
11048 .Case([&](omp::UnrollPartialOp op) {
11051 .Case([&](omp::TileOp op) {
11052 return applyTile(op, builder, moduleTranslation);
11054 .Case([&](omp::FuseOp op) {
11055 return applyFuse(op, builder, moduleTranslation);
11057 .Case([&](omp::TargetAllocMemOp) {
11060 .Case([&](omp::TargetFreeMemOp) {
11063 .Case([&](omp::AllocateDirOp) {
11066 .Case([&](omp::AllocateFreeOp) {
11070 .Case([&](omp::AllocSharedMemOp op) {
11073 .Case([&](omp::FreeSharedMemOp op) {
11076 .Case([&](omp::GroupprivateOp) {
11079 .Case([&](omp::DeclareSimdOp) {
11086 .Default([&](Operation *inst) {
11088 <<
"not yet implemented: " << inst->
getName();
11091 if (isOutermostLoopWrapper)
11098 registry.
insert<omp::OpenMPDialect>();
11100 dialect->addInterfaces<OpenMPDialectLLVMIRTranslationInterface>();
if(failed(verifyVectorMemoryOp(getOperation(), memrefType, getVectorType()))) return failure()
static void copy(Location loc, Value dst, Value src, Value size, OpBuilder &builder)
Copies the given number of bytes from src to dst pointers.
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 omp::MapInfoOp getFirstOrLastMappedMemberPtr(omp::MapInfoOp mapInfo, bool first)
static LogicalResult convertOmpDispatch(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Convert 'dispatch' operation into LLVM IR.
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 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 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)
static mlir::LogicalResult convertIteratorRegion(llvm::Value *linearIV, IteratorInfo &iterInfo, mlir::Region &iteratorRegion, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
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 llvm::Expected< llvm::BasicBlock * > allocatePrivateVars(T op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, PrivateVarsInfo &privateVarsInfo, llvm::OpenMPIRBuilder::InsertPointTy &allocaIP, llvm::DenseMap< Value, Value > *mappedPrivateVars=nullptr, std::optional< llvm::OpenMPIRBuilder::InsertPointTy > allocatorIP=std::nullopt)
Allocate and initialize delayed private variables. Returns the basic block which comes after all of t...
static LogicalResult applyUnrollPartial(omp::UnrollPartialOp op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Apply a #pragma omp unroll partial / !$omp unroll partial transformation using the OpenMPIRBuilder.
static LogicalResult convertOmpCritical(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP 'critical' operation into LLVM IR using OpenMPIRBuilder.
static LogicalResult convertTargetAllocMemOp(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static omp::DistributeOp getDistributeCapturingTeamsReduction(omp::TeamsOp teamsOp)
static LogicalResult convertOmpCanonicalLoopOp(omp::CanonicalLoopOp op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Convert an omp.canonical_loop to LLVM-IR.
static LogicalResult convertOmpTargetData(Operation *op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static std::optional< int64_t > extractConstInteger(Value value)
If the given value is defined by an llvm.mlir.constant operation and it is of an integer type,...
static llvm::Expected< llvm::Value * > initPrivateVar(llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, omp::PrivateClauseOp &privDecl, llvm::Value *nonPrivateVar, BlockArgument &blockArg, llvm::Value *llvmPrivateVar, llvm::BasicBlock *privInitBlock, llvm::DenseMap< Value, Value > *mappedPrivateVars=nullptr)
Initialize a single (first)private variable. You probably want to use allocateAndInitPrivateVars inst...
static mlir::LogicalResult buildAffinityData(mlir::omp::TaskOp &taskOp, llvm::IRBuilderBase &builder, mlir::LLVM::ModuleTranslation &moduleTranslation, llvm::OpenMPIRBuilder::AffinityData &ad)
static LogicalResult allocAndInitializeReductionVars(OP op, ArrayRef< BlockArgument > reductionArgs, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, llvm::OpenMPIRBuilder::InsertPointTy &allocaIP, SmallVectorImpl< omp::DeclareReductionOp > &reductionDecls, SmallVectorImpl< llvm::Value * > &privateReductionVariables, DenseMap< Value, llvm::Value * > &reductionVariableMap, llvm::ArrayRef< bool > isByRef)
static LogicalResult convertOmpSimd(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP simd loop into LLVM IR using OpenMPIRBuilder.
static LogicalResult convertOmpInteropDestroyOp(omp::InteropDestroyOp destroyOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static LogicalResult convertOmpDistribute(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static llvm::Value * getAllocationSize(llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, T op)
static llvm::Function * getOmpTargetAlloc(llvm::IRBuilderBase &builder, llvm::Module *llvmModule)
static llvm::omp::OMPDynGroupprivateFallbackType getDynGroupprivateFallbackType(omp::FallbackModifierAttr fallbackAttr)
static llvm::Expected< llvm::Function * > emitUserDefinedMapper(Operation *declMapperOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, llvm::StringRef mapperFuncName, TargetDirectiveEnumTy targetDirective)
static LogicalResult convertOmpOrdered(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP 'ordered' operation into LLVM IR using OpenMPIRBuilder.
static LogicalResult cleanupPrivateVars(T op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, Location loc, PrivateVarsInfo &privateVarsInfo)
static void processMapWithMembersOf(LLVM::ModuleTranslation &moduleTranslation, llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder &ompBuilder, DataLayout &dl, MapInfosTy &combinedInfo, MapInfoData &mapData, uint64_t mapDataIndex, TargetDirectiveEnumTy targetDirective)
static LogicalResult convertOmpMasked(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP 'masked' operation into LLVM IR using OpenMPIRBuilder.
static llvm::AtomicRMWInst::BinOp convertBinOpToAtomic(Operation &op)
Converts an LLVM dialect binary operation to the corresponding enum value for atomicrmw supported bin...
static LogicalResult convertOmpCancel(omp::CancelOp op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static int getMapDataMemberIdx(MapInfoData &mapData, omp::MapInfoOp memberOp)
allocatedType moduleTranslation static convertType(allocatedType) LogicalResult inlineOmpRegionCleanup(llvm::SmallVectorImpl< Region * > &cleanupRegions, llvm::ArrayRef< llvm::Value * > privateVariables, LLVM::ModuleTranslation &moduleTranslation, llvm::IRBuilderBase &builder, StringRef regionName, bool shouldLoadCleanupRegionArg=true)
handling of DeclareReductionOp's cleanup region
static LogicalResult applyFuse(omp::FuseOp op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Apply a #pragma omp fuse / !$omp fuse transformation using the OpenMPIRBuilder.
static llvm::Value * materializeRegionArgValue(llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, BlockArgument regionArg, llvm::Value *value)
static LogicalResult convertOmpScope(omp::ScopeOp &scopeOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP scope construct into LLVM IR.
static bool isPrivatizeableAttachMap(omp::ClauseMapFlags mapType)
static llvm::Value * getSizeInBytes(DataLayout &dl, const mlir::Type &type, Operation *clauseOp, llvm::Value *basePointer, llvm::Type *baseType, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static llvm::Error initPrivateVars(llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, PrivateVarsInfo &privateVarsInfo, llvm::DenseMap< Value, Value > *mappedPrivateVars=nullptr)
static LogicalResult convertAllocSharedMemOp(omp::AllocSharedMemOp allocMemOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static llvm::CanonicalLoopInfo * findCurrentLoopInfo(LLVM::ModuleTranslation &moduleTranslation)
Find the loop information structure for the loop nest being translated.
static OwningReductionGen makeReductionGen(omp::DeclareReductionOp decl, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Create an OpenMPIRBuilder-compatible reduction generator for the given reduction declaration.
static 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 llvm::Value * getSourceLocIdentFromOp(llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder &ompBuilder, Operation *op)
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 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 LogicalResult convertAllocatorVars(Operation &op, ValueRange allocatorVars, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, PrivateVarsInfo &privateVarsInfo)
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 llvm::Expected< llvm::Value * > getPrivateDataAddress(llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, omp::PrivateClauseOp privatizer, llvm::Value *var)
Returns the address of the data in var, via the data_address region.
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 popCancelFinalizationCB(const ArrayRef< llvm::UncondBrInst * > cancelTerminators, llvm::OpenMPIRBuilder &ompBuilder, llvm::BasicBlock *afterBB)
If we cancelled the construct, we should branch to the finalization block of that construct....
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 uint64_t getReductionDataSize(OpTy &op)
static bool opMightBeSafeForBarriers(mlir::Operation *op)
A compiler-generated barrier is unsafe when only part of the current team can reach it....
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 LogicalResult emitPrivatizationBarrier(mlir::Operation *op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
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 LogicalResult completePrivateVars(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 bool isDeclareTargetLink(Value value)
static LogicalResult convertFlagsAttr(Operation *op, mlir::omp::FlagsAttr attribute, LLVM::ModuleTranslation &moduleTranslation)
Lowers the FlagsAttr which is applied to the module when offloading. This attribute contains OpenMP R...
static bool checkIfPointerMap(omp::MapInfoOp mapOp)
static llvm::Type * getAllocatedLlvmTypeForVariable(Value var, Value baseVar, LLVM::ModuleTranslation &moduleTranslation)
static LogicalResult applyTile(omp::TileOp op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Apply a #pragma omp tile / !$omp tile transformation using the OpenMPIRBuilder.
static LogicalResult convertAllocateFreeOp(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, const OpenMPDialectLLVMIRTranslationInterface &ompIface)
static StringRef getMapClauseName(omp::MapInfoOp mapOp)
static std::vector< llvm::Value * > calculateBoundsOffset(LLVM::ModuleTranslation &moduleTranslation, llvm::IRBuilderBase &builder, bool isArrayTy, OperandRange bounds, bool &isByteOffset)
This function calculates the array/pointer offset for map data provided with bounds operations,...
static llvm::Function * getOmpTargetFree(llvm::IRBuilderBase &builder, llvm::Module *llvmModule)
static LogicalResult convertOmpTaskgroupOp(omp::TaskgroupOp tgOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP taskgroup construct into LLVM IR using OpenMPIRBuilder.
static std::optional< llvm::Value * > getDynamicAllocatedSize(Value var, Value baseVar, LLVM::ModuleTranslation &moduleTranslation, llvm::IRBuilderBase &builder, const llvm::DataLayout &dataLayout)
static void collectMapDataFromMapOperands(MapInfoData &mapData, SmallVectorImpl< Value > &mapVars, LLVM::ModuleTranslation &moduleTranslation, DataLayout &dl, llvm::IRBuilderBase &builder, ArrayRef< Value > useDevPtrOperands={}, ArrayRef< Value > useDevAddrOperands={}, ArrayRef< Value > hasDevAddrOperands={})
static void extractAtomicControlFlags(omp::AtomicUpdateOp atomicUpdateOp, bool &isIgnoreDenormalMode, bool &isFineGrainedMemory, bool &isRemoteMemory)
static Operation * genLoop(CodegenEnv &env, OpBuilder &builder, LoopId curr, unsigned numCases, bool needsUniv, ArrayRef< TensorLevel > tidLvls)
Generates a for-loop or a while-loop, depending on whether it implements singleton iteration or co-it...
#define MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(CLASS_NAME)
Attributes are known-constant values of operations.
This class represents an argument of a Block.
Block represents an ordered list of Operations.
BlockArgument getArgument(unsigned i)
unsigned getNumArguments()
OpListType & getOperations()
Operation * getTerminator()
Get the terminator operation of this block.
iterator_range< iterator > without_terminator()
Return an iterator range over the operation within this block excluding the terminator operation at t...
The main mechanism for performing data layout queries.
llvm::TypeSize getTypeSize(Type t) const
Returns the size of the given type in the current scope.
llvm::TypeSize getTypeSizeInBits(Type t) const
Returns the size in bits of the given type in the current scope.
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
bool addExtension(TypeID extensionID, std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
An instance of this location represents a tuple of file, line number, and column number.
Implementation class for module translation.
llvm::BasicBlock * lookupBlock(Block *block) const
Finds an LLVM IR basic block that corresponds to the given MLIR block.
WalkResult stackWalk(llvm::function_ref< WalkResult(T &)> callback)
Calls callback for every ModuleTranslation stack frame of type T starting from the top of the stack.
void stackPush(Args &&...args)
Creates a stack frame of type T on ModuleTranslation stack.
LogicalResult convertBlock(Block &bb, bool ignoreArguments, llvm::IRBuilderBase &builder)
Translates the contents of the given block to LLVM IR using this translator.
SmallVector< llvm::Value * > lookupValues(ValueRange values)
Looks up remapped a list of remapped values.
void mapFunction(StringRef name, llvm::Function *func)
Stores the mapping between a function name and its LLVM IR representation.
llvm::Value * lookupValue(Value value) const
Finds an LLVM IR value corresponding to the given MLIR value.
void invalidateOmpLoop(omp::NewCliOp mlir)
Mark an OpenMP loop as having been consumed.
SymbolTableCollection & symbolTable()
llvm::Type * convertType(Type type)
Converts the type from MLIR LLVM dialect to LLVM.
llvm::OpenMPIRBuilder * getOpenMPBuilder()
Returns the OpenMP IR builder associated with the LLVM IR module being constructed.
llvm::vfs::FileSystem & getFileSystem()
Returns the virtual filesystem to use for file operations.
void mapOmpLoop(omp::NewCliOp mlir, llvm::CanonicalLoopInfo *llvm)
Map an MLIR OpenMP dialect CanonicalLoopInfo to its lowered LLVM-IR OpenMPIRBuilder CanonicalLoopInfo...
llvm::GlobalValue * lookupGlobal(Operation *op)
Finds an LLVM IR global value that corresponds to the given MLIR operation defining a global value.
SaveStateStack< T, ModuleTranslation > SaveStack
RAII object calling stackPush/stackPop on construction/destruction.
void remapAllValuesWith(llvm::Value *oldValue, llvm::Value *newValue)
Remap old value with new value in the MLIR-to-LLVM value map so later translations use the replacemen...
LogicalResult convertOperation(Operation &op, llvm::IRBuilderBase &builder)
Converts the given MLIR operation into LLVM IR using this translator.
llvm::Function * lookupFunction(StringRef name) const
Finds an LLVM IR function by its name.
void mapBlock(Block *mlir, llvm::BasicBlock *llvm)
Stores the mapping between an MLIR block and LLVM IR basic block.
llvm::Module * getLLVMModule()
Returns the LLVM module in which the IR is being constructed.
void stackPop()
Pops the last element from the ModuleTranslation stack.
void forgetMapping(Region ®ion)
Removes the mapping for blocks contained in the region and values defined in these blocks.
void mapValue(Value mlir, llvm::Value *llvm)
Stores the mapping between an MLIR value and its LLVM IR counterpart.
llvm::CanonicalLoopInfo * lookupOMPLoop(omp::NewCliOp mlir) const
Find the LLVM-IR loop that represents an MLIR loop.
llvm::LLVMContext & getLLVMContext() const
Returns the LLVM context in which the IR is being constructed.
Utility class to translate MLIR LLVM dialect types to LLVM IR.
unsigned getPreferredAlignment(Type type, const llvm::DataLayout &layout)
Returns the preferred alignment for the type given the data layout.
T findInstanceOf()
Return an instance of the given location type if one is nested under the current location.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
void appendDialectRegistry(const DialectRegistry ®istry)
Append the contents of the given dialect registry to the registry associated with this context.
StringAttr getName() const
Return the name of the attribute.
Attribute getValue() const
Return the value of the attribute.
This class implements the operand iterators for the Operation class.
StringAttr getIdentifier() const
Return the name of this operation as a StringAttr.
Operation is the basic unit of execution within MLIR.
Region & getRegion(unsigned index)
Returns the region held by this operation at position 'index'.
Value getOperand(unsigned idx)
InFlightDiagnostic emitWarning(const Twine &message={})
Emit a warning about this operation, reporting up to any diagnostic handlers that may be listening.
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
unsigned getNumRegions()
Returns the number of regions held by this operation.
Location getLoc()
The source location the operation was defined or derived from.
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
unsigned getNumOperands()
OperandRange operand_range
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
OperationName getName()
The name of an operation is the key identifier for it.
operand_range getOperands()
Returns an iterator on the underlying Value's.
std::enable_if_t< llvm::function_traits< std::decay_t< FnT > >::num_args==1, RetT > walk(FnT &&callback)
Walk the operation by calling the callback for each nested operation (including this one),...
user_range getUsers()
Returns a range of all users.
result_range getResults()
MLIRContext * getContext()
Return the context this operation is associated with.
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
unsigned getNumResults()
Return the number of results held by this operation.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
BlockArgListType getArguments()
unsigned getNumArguments()
Operation * getParentOp()
Return the parent operation this region is attached to.
BlockListType & getBlocks()
bool hasOneBlock()
Return true if this region has exactly one block.
Concrete CRTP base class for StateStack frames.
@ Private
The symbol is private and may only be referenced by SymbolRefAttrs local to the operations within the...
static Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
user_range getUsers() const
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
A utility result that is used to signal how to proceed with an ongoing walk:
static WalkResult advance()
bool wasInterrupted() const
Returns true if the walk was interrupted.
static WalkResult interrupt()
The OpAsmOpInterface, see OpAsmInterface.td for more details.
void connectPHINodes(Region ®ion, const ModuleTranslation &state)
For all blocks in the region that were converted to LLVM IR using the given ModuleTranslation,...
llvm::Constant * createMappingInformation(Location loc, llvm::OpenMPIRBuilder &builder, StringRef mapName={})
Create a constant string representing the mapping information extracted from the MLIR location inform...
llvm::Constant * createSourceLocStrFromLocation(Location loc, llvm::OpenMPIRBuilder &builder, StringRef name, uint32_t &strLen, bool ForOffloadMap=false)
Create a constant string location from the MLIR Location information.
int64_t getOpenMPVersionAttribute(ModuleOp module, int64_t fallback=-1)
Returns the value of the omp.version attribute, if present, or the fallback.
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.
size_t numPrivateVars
Number of private variables before the linear ones.
SmallVector< BlockArgument > blockArgs
SmallVector< mlir::Value > mlirVars
SmallVector< omp::PrivateClauseOp > privatizers
llvm::DenseMap< Value, llvm::Value * > convertedAllocators
void addLinearVars(OP op)
Adds the linear variables of op, which are privatized by their linear privatizers,...
SmallVector< llvm::Value * > llvmVars
SmallVector< AllocatorPrivateInfo > allocatorPrivates
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.