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/CommandLine.h"
40#include "llvm/Support/FileSystem.h"
41#include "llvm/Support/MathExtras.h"
42#include "llvm/Support/NVPTXAddrSpace.h"
43#include "llvm/Support/SaveAndRestore.h"
44#include "llvm/Support/VirtualFileSystem.h"
45#include "llvm/TargetParser/Triple.h"
46#include "llvm/Transforms/Utils/ModuleUtils.h"
59 omp::PrivateClauseOp privatizer, llvm::Value *var);
66static bool disableVirtualCollapse =
false;
68static llvm::omp::ScheduleKind
69convertToScheduleKind(std::optional<omp::ClauseScheduleKind> schedKind) {
70 if (!schedKind.has_value())
71 return llvm::omp::OMP_SCHEDULE_Default;
72 switch (schedKind.value()) {
73 case omp::ClauseScheduleKind::Static:
74 return llvm::omp::OMP_SCHEDULE_Static;
75 case omp::ClauseScheduleKind::Dynamic:
76 return llvm::omp::OMP_SCHEDULE_Dynamic;
77 case omp::ClauseScheduleKind::Guided:
78 return llvm::omp::OMP_SCHEDULE_Guided;
79 case omp::ClauseScheduleKind::Auto:
80 return llvm::omp::OMP_SCHEDULE_Auto;
81 case omp::ClauseScheduleKind::Runtime:
82 return llvm::omp::OMP_SCHEDULE_Runtime;
83 case omp::ClauseScheduleKind::Distribute:
84 return llvm::omp::OMP_SCHEDULE_Distribute;
86 llvm_unreachable(
"unhandled schedule clause argument");
91class OpenMPAllocStackFrame
96 explicit OpenMPAllocStackFrame(
97 llvm::BasicBlock *allocBlock,
98 llvm::ArrayRef<llvm::BasicBlock *> deallocBlocks)
99 : allocBlock(allocBlock), deallocBlocks(deallocBlocks) {}
100 llvm::BasicBlock *allocBlock;
101 llvm::SmallVector<llvm::BasicBlock *> deallocBlocks;
107class OpenMPLoopInfoStackFrame
111 llvm::CanonicalLoopInfo *loopInfo =
nullptr;
121 explicit OpenMPTranslationState(llvm::Module &module) : ompBuilder(module) {
125 llvm::OpenMPIRBuilderConfig config(
132 config.setDefaultTargetAS(module.getDataLayout().getProgramAddressSpace());
133 config.setRuntimeCC(module.getTargetTriple().isSPIRV()
134 ? llvm::CallingConv::SPIR_FUNC
135 : llvm::CallingConv::C);
136 ompBuilder.setConfig(std::move(config));
137 ompBuilder.initialize();
140 ~OpenMPTranslationState()
override {
141 if (!ompBuilder.isFinalized())
142 ompBuilder.finalize();
145 LogicalResult finalize()
override {
146 ompBuilder.finalize();
151 llvm::OpenMPIRBuilder ompBuilder;
161static OpenMPTranslationState &
169static llvm::OpenMPIRBuilder *
175static llvm::CanonicalLoopInfo *
177 auto cli =
mlir.getDefiningOp<omp::NewCliOp>();
178 llvm::CanonicalLoopInfo *
result =
180 assert(
result &&
"attempt to get non-existing loop");
187 auto cli =
mlir.getDefiningOp<omp::NewCliOp>();
194 llvm::CanonicalLoopInfo *
llvm) {
195 assert(
llvm &&
"argument must be non-null");
196 auto cli =
mlir.getDefiningOp<omp::NewCliOp>();
197 llvm::CanonicalLoopInfo *&cur =
199 assert(cur ==
nullptr &&
"attempting to map a loop that is already mapped");
220class PreviouslyReportedError
221 :
public llvm::ErrorInfo<PreviouslyReportedError> {
223 void log(raw_ostream &)
const override {
227 std::error_code convertToErrorCode()
const override {
229 "PreviouslyReportedError doesn't support ECError conversion");
236char PreviouslyReportedError::ID = 0;
247class LinearClauseProcessor {
250 SmallVector<llvm::Type *> linearVarTypes;
251 SmallVector<llvm::Value *> linearSteps;
253 SmallVector<omp::PrivateClauseOp> linearPrivatizers;
254 SmallVector<llvm::Value *> linearOrigVars;
255 SmallVector<llvm::Value *> linearPrivateVars;
257 SmallVector<llvm::Value *> linearStartVals;
258 llvm::BasicBlock *linearFinalizationBB;
259 llvm::BasicBlock *linearExitBB;
260 llvm::BasicBlock *linearLastIterExitBB;
261 std::optional<size_t> linearLoopIVIndex;
264 llvm::Expected<llvm::Value *>
265 getAddress(llvm::IRBuilderBase &builder,
266 LLVM::ModuleTranslation &moduleTranslation,
size_t index,
269 linearPrivatizers[index], var);
273 llvm::Error storeLinearVars(llvm::IRBuilderBase &builder,
274 LLVM::ModuleTranslation &moduleTranslation) {
275 for (
size_t index = 0; index < linearOrigVars.size(); index++) {
276 llvm::Expected<llvm::Value *> from = getAddress(
277 builder, moduleTranslation, index, linearPrivateVars[index]);
279 return from.takeError();
280 llvm::LoadInst *linearVarTemp =
281 builder.CreateLoad(linearVarTypes[index], *from);
282 llvm::Expected<llvm::Value *> to =
283 getAddress(builder, moduleTranslation, index, linearOrigVars[index]);
285 return to.takeError();
286 builder.CreateStore(linearVarTemp, *to);
288 return llvm::Error::success();
293 void registerType(LLVM::ModuleTranslation &moduleTranslation,
294 mlir::Attribute &ty) {
295 linearVarTypes.push_back(moduleTranslation.
convertType(
296 mlir::cast<mlir::TypeAttr>(ty).getValue()));
300 void createLinearVar(llvm::IRBuilderBase &builder,
301 const llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
302 omp::PrivateClauseOp privatizer, llvm::Value *origVar,
303 llvm::Value *privateVar,
int idx) {
304 llvm::IRBuilderBase::InsertPointGuard guard(builder);
305 builder.SetInsertPoint(allocaIP.getNodeParent()->getTerminator());
306 linearStartVals.push_back(
307 builder.CreateAlloca(linearVarTypes[idx],
nullptr,
".linear_var"));
308 linearPrivatizers.push_back(privatizer);
309 linearOrigVars.push_back(origVar);
310 linearPrivateVars.push_back(privateVar);
314 inline void initLinearStep(LLVM::ModuleTranslation &moduleTranslation,
315 mlir::Value &linearStep) {
316 linearSteps.push_back(moduleTranslation.
lookupValue(linearStep));
320 llvm::Error initLinearVar(llvm::IRBuilderBase &builder,
321 LLVM::ModuleTranslation &moduleTranslation,
322 llvm::BasicBlock *loopPreHeader) {
323 builder.SetInsertPoint(loopPreHeader->getTerminator());
324 for (
size_t index = 0; index < linearOrigVars.size(); index++) {
325 llvm::Expected<llvm::Value *> orig =
326 getAddress(builder, moduleTranslation, index, linearOrigVars[index]);
328 return orig.takeError();
329 llvm::LoadInst *linearVarLoad =
330 builder.CreateLoad(linearVarTypes[index], *orig);
331 builder.CreateStore(linearVarLoad, linearStartVals[index]);
333 return llvm::Error::success();
337 LogicalResult initLinearIV(omp::SimdOp simdOp) {
338 auto loopOp = cast<omp::LoopNestOp>(simdOp.getWrappedLoop());
340 if (loopOp.getIVs().size() != 1)
348 MutableArrayRef<BlockArgument> linearArgs =
349 cast<omp::BlockArgOpenMPOpInterface>(*simdOp).getLinearBlockArgs();
350 SmallVector<Value> ivValues{loopOp.getIVs().front()};
351 for (Operation *user : loopOp.getIVs().front().getUsers())
352 if (isa<LLVM::SExtOp, LLVM::ZExtOp, LLVM::TruncOp>(user))
353 ivValues.push_back(user->getResult(0));
355 for (Value ivValue : ivValues) {
356 for (Operation *user : ivValue.getUsers()) {
357 auto storeOp = dyn_cast<LLVM::StoreOp>(user);
358 if (!storeOp || storeOp.getValue() != ivValue)
362 Value addr = storeOp.getAddr();
365 if (
auto load = dyn_cast_if_present<LLVM::LoadOp>(def)) {
366 addr =
load.getAddr();
367 }
else if (
auto gep = dyn_cast_if_present<LLVM::GEPOp>(def)) {
368 addr = gep.getBase();
370 auto copy = llvm::find_if(addr.
getUsers(), [&](Operation *user) {
371 auto memcpy = dyn_cast<LLVM::MemcpyOp>(user);
372 return memcpy && memcpy.getDst() == addr &&
373 llvm::is_contained(linearArgs, memcpy.getSrc());
377 addr = cast<LLVM::MemcpyOp>(*copy).getSrc();
380 auto *it = llvm::find(linearArgs, addr);
381 if (it == linearArgs.end())
383 size_t index = std::distance(linearArgs.begin(), it);
384 if (linearLoopIVIndex && *linearLoopIVIndex != index)
385 return simdOp.emitError(
386 "Could not determine the linear variable associated with the "
387 "loop nest induction variable");
388 linearLoopIVIndex = index;
395 llvm::Error updateLinearVar(llvm::IRBuilderBase &builder,
396 LLVM::ModuleTranslation &moduleTranslation,
397 llvm::BasicBlock *loopBody,
398 llvm::Value *loopInductionVar) {
399 builder.SetInsertPoint(loopBody->getTerminator());
400 for (
size_t index = 0; index < linearStartVals.size(); index++) {
401 llvm::Type *linearVarType = linearVarTypes[index];
402 llvm::Value *iv = loopInductionVar;
403 llvm::Value *step = linearSteps[index];
404 llvm::Expected<llvm::Value *>
result = getAddress(
405 builder, moduleTranslation, index, linearPrivateVars[index]);
407 return result.takeError();
409 if (!iv->getType()->isIntegerTy())
410 llvm_unreachable(
"OpenMP loop induction variable must be an integer "
413 if (linearVarType->isIntegerTy()) {
415 iv = builder.CreateSExtOrTrunc(iv, linearVarType);
416 step = builder.CreateSExtOrTrunc(step, linearVarType);
418 llvm::LoadInst *linearVarStart =
419 builder.CreateLoad(linearVarType, linearStartVals[index]);
420 llvm::Value *mulInst = builder.CreateMul(iv, step);
421 llvm::Value *addInst = builder.CreateAdd(linearVarStart, mulInst);
422 builder.CreateStore(addInst, *
result);
423 }
else if (linearVarType->isFloatingPointTy()) {
425 step = builder.CreateSExtOrTrunc(step, iv->getType());
426 llvm::Value *mulInst = builder.CreateMul(iv, step);
428 llvm::LoadInst *linearVarStart =
429 builder.CreateLoad(linearVarType, linearStartVals[index]);
430 llvm::Value *mulFp = builder.CreateSIToFP(mulInst, linearVarType);
431 llvm::Value *addInst = builder.CreateFAdd(linearVarStart, mulFp);
432 builder.CreateStore(addInst, *
result);
435 "Linear variable must be of integer or floating-point type");
438 return llvm::Error::success();
442 llvm::Error updateLinearIV(llvm::IRBuilderBase &builder,
443 LLVM::ModuleTranslation &moduleTranslation) {
444 if (!linearLoopIVIndex)
445 return llvm::Error::success();
446 size_t index = *linearLoopIVIndex;
449 llvm::Type *varType = linearVarTypes[index];
450 if (!varType->isIntegerTy())
451 llvm_unreachable(
"Linear iteration variable must be of integer type");
452 llvm::Expected<llvm::Value *> var =
453 getAddress(builder, moduleTranslation, index, linearPrivateVars[index]);
455 return var.takeError();
456 llvm::Value *step = builder.CreateSExtOrTrunc(linearSteps[index], varType);
457 llvm::Value *val = builder.CreateLoad(varType, *var);
458 llvm::Value *addInst = builder.CreateAdd(val, step);
459 builder.CreateStore(addInst, *var);
460 return llvm::Error::success();
465 void splitLinearFiniBB(llvm::IRBuilderBase &builder,
466 llvm::BasicBlock *loopExit) {
467 linearFinalizationBB = loopExit->splitBasicBlock(
468 loopExit->getTerminator(),
"omp_loop.linear_finalization");
469 linearExitBB = linearFinalizationBB->splitBasicBlock(
470 linearFinalizationBB->getTerminator(),
"omp_loop.linear_exit");
471 linearLastIterExitBB = linearFinalizationBB->splitBasicBlock(
472 linearFinalizationBB->getTerminator(),
"omp_loop.linear_lastiter_exit");
476 llvm::OpenMPIRBuilder::InsertPointOrErrorTy
477 finalizeLinearVar(llvm::IRBuilderBase &builder,
478 LLVM::ModuleTranslation &moduleTranslation,
479 llvm::Value *lastIter) {
481 builder.SetInsertPoint(linearFinalizationBB->getTerminator());
482 llvm::Value *loopLastIterLoad = builder.CreateLoad(
483 llvm::Type::getInt32Ty(builder.getContext()), lastIter);
484 llvm::Value *isLast =
485 builder.CreateCmp(llvm::CmpInst::ICMP_NE, loopLastIterLoad,
486 llvm::ConstantInt::get(
487 llvm::Type::getInt32Ty(builder.getContext()), 0));
489 builder.SetInsertPoint(linearLastIterExitBB->getTerminator());
490 if (llvm::Error err = storeLinearVars(builder, moduleTranslation))
491 return std::move(err);
496 builder.SetInsertPoint(linearFinalizationBB->getTerminator());
497 builder.CreateCondBr(isLast, linearLastIterExitBB, linearExitBB);
498 linearFinalizationBB->getTerminator()->eraseFromParent();
500 builder.SetInsertPoint(linearExitBB->getTerminator());
502 ->createBarrier(builder, llvm::omp::OMPD_barrier);
508 emitStoresForLinearVar(llvm::IRBuilderBase &builder,
509 LLVM::ModuleTranslation &moduleTranslation) {
510 return storeLinearVars(builder, moduleTranslation);
518 SymbolRefAttr symbolName) {
519 omp::PrivateClauseOp privatizer =
522 assert(privatizer &&
"privatizer not found in the symbol table");
533 auto todo = [&op](StringRef clauseName) {
534 return op.
emitError() <<
"not yet implemented: Unhandled clause "
535 << clauseName <<
" in " << op.
getName()
539 auto checkAllocate = [&todo](
auto op, LogicalResult &
result) {
540 if (!op.getAllocateVars().empty() || !op.getAllocatorVars().empty())
541 result = todo(
"allocate");
543 auto checkBare = [&todo](
auto op, LogicalResult &
result) {
544 if (op.getKernelType() == omp::TargetExecMode::bare)
545 result = todo(
"ompx_bare");
547 auto checkDepend = [&todo](
auto op, LogicalResult &
result) {
548 if (!op.getDependVars().empty() || op.getDependKinds() ||
549 !op.getDependIterated().empty() || op.getDependIteratedKinds())
552 auto checkHint = [](
auto op, LogicalResult &) {
556 auto checkInReduction = [&todo](
auto op, LogicalResult &
result) {
557 if (isa<omp::TargetOp, omp::TaskOp, omp::TaskloopContextOp>(
558 op.getOperation())) {
559 if (
auto byrefAttr = op.getInReductionByref()) {
560 for (
bool isByRef : *byrefAttr) {
562 result = todo(
"in_reduction with byref modifier");
567 if (isa<omp::TargetOp>(op.getOperation())) {
568 if (
auto inReductionSyms = op.getInReductionSyms()) {
570 (*inReductionSyms).template getAsRange<SymbolRefAttr>()) {
575 "symbol resolution should be guaranteed by the op verifier");
576 if (decl.getInitializerRegion().front().getNumArguments() != 1) {
577 result = todo(
"in_reduction with two-argument initializer");
580 if (!decl.getCleanupRegion().empty()) {
581 result = todo(
"in_reduction with cleanup region");
587 }
else if (!op.getInReductionVars().empty() || op.getInReductionByref() ||
588 op.getInReductionSyms()) {
589 result = todo(
"in_reduction");
592 auto checkNowait = [&todo](
auto op, LogicalResult &
result) {
596 auto checkOrder = [&todo](
auto op, LogicalResult &
result) {
597 if (op.getOrder() || op.getOrderMod())
600 auto checkPrivate = [&todo](
auto op, LogicalResult &
result) {
601 if (!op.getPrivateVars().empty() || op.getPrivateSyms())
602 result = todo(
"privatization");
604 auto checkReduction = [&todo](
auto op, LogicalResult &
result) {
605 if (isa<omp::TeamsOp>(op))
606 if (!op.getReductionVars().empty() || op.getReductionByref() ||
607 op.getReductionSyms())
608 result = todo(
"reduction");
609 for (
unsigned i = 0, e = op.getNumReductionVars(); i != e; ++i) {
610 omp::ReductionModifier mod = op.getReductionModifier(i);
611 if (mod == omp::ReductionModifier::defaultmod)
615 bool taskModifierSupported =
616 mod == omp::ReductionModifier::task &&
617 isa<omp::ParallelOp, omp::WsloopOp, omp::SectionsOp>(op);
618 if (!taskModifierSupported) {
619 result = todo(
"reduction with modifier");
620 }
else if (
auto byref = op.getReductionByref()) {
622 result = todo(
"task reduction modifier with by-ref reduction");
626 auto checkTaskReductionByref = [&todo](
auto op, LogicalResult &
result) {
627 if (
auto byrefAttr = op.getTaskReductionByref())
628 for (
bool isByRef : *byrefAttr)
630 result = todo(
"task_reduction with byref modifier");
634 auto checkReductionByref = [&todo](
auto op, LogicalResult &
result) {
635 if (
auto byrefAttr = op.getReductionByref())
636 for (
bool isByRef : *byrefAttr)
638 result = todo(
"reduction with byref modifier");
642 auto checkNumTeams = [&todo](
auto op, LogicalResult &
result) {
643 if (op.hasNumTeamsMultiDim())
644 result = todo(
"num_teams with multi-dimensional values");
646 auto checkNumThreads = [&todo](
auto op, LogicalResult &
result) {
647 if (op.hasNumThreadsMultiDim())
648 result = todo(
"num_threads with multi-dimensional values");
651 auto checkThreadLimit = [&todo](
auto op, LogicalResult &
result) {
652 if (op.hasThreadLimitMultiDim())
653 result = todo(
"thread_limit with multi-dimensional values");
655 auto checkMap = [&todo](
auto op, LogicalResult &
result) {
656 if (!op.getMapIterated().empty())
657 result = todo(
"map/motion clause with iterator modifier");
660 auto checkDynGroupprivate = [&todo](
auto op, LogicalResult &
result) {
661 if (op.getDynGroupprivateSize())
662 result = todo(
"dyn_groupprivate");
667 .Case([&](omp::DistributeOp op) {
668 checkAllocate(op,
result);
671 .Case([&](omp::SectionsOp op) {
672 checkAllocate(op,
result);
674 checkReduction(op,
result);
676 .Case([&](omp::ScopeOp op) { checkReduction(op,
result); })
677 .Case([&](omp::SingleOp op) {
678 checkAllocate(op,
result);
681 .Case([&](omp::TeamsOp op) {
682 checkAllocate(op,
result);
684 checkNumTeams(op,
result);
685 checkThreadLimit(op,
result);
686 checkDynGroupprivate(op,
result);
688 .Case([&](omp::TaskOp op) {
689 checkAllocate(op,
result);
690 checkInReduction(op,
result);
692 .Case([&](omp::TaskgroupOp op) {
693 checkAllocate(op,
result);
694 checkTaskReductionByref(op,
result);
696 .Case([&](omp::DispatchOp op) {
705 .Case([&](omp::TaskloopContextOp op) {
706 checkAllocate(op,
result);
707 checkInReduction(op,
result);
708 checkReduction(op,
result);
709 checkReductionByref(op,
result);
711 .Case([&](omp::WsloopOp op) {
712 checkAllocate(op,
result);
714 checkReduction(op,
result);
716 .Case([&](omp::ParallelOp op) {
717 checkReduction(op,
result);
718 checkNumThreads(op,
result);
720 .Case([&](omp::SimdOp op) { checkReduction(op,
result); })
721 .Case<omp::AtomicReadOp, omp::AtomicWriteOp, omp::AtomicUpdateOp,
722 omp::AtomicCaptureOp>([&](
auto op) { checkHint(op,
result); })
723 .Case([&](omp::AtomicCompareOp op) {
729 auto structTy = dyn_cast<LLVM::LLVMStructType>(argType);
735 result = todo(
"compare for complex types wider than 128 bits");
737 .Case<omp::TargetEnterDataOp, omp::TargetExitDataOp>([&](
auto op) {
741 .Case([&](omp::TargetUpdateOp op) {
745 .Case([&](omp::TargetOp op) {
746 checkAllocate(op,
result);
748 checkInReduction(op,
result);
750 checkThreadLimit(op,
result);
752 .Case([&](omp::TargetDataOp op) { checkMap(op,
result); })
753 .Case([&](omp::DeclareMapperInfoOp op) { checkMap(op,
result); })
764 llvm::handleAllErrors(
766 [&](
const PreviouslyReportedError &) {
result = failure(); },
767 [&](
const llvm::ErrorInfoBase &err) {
790 llvm::OpenMPIRBuilder::InsertPointTy allocInsertPoint;
793 [&](OpenMPAllocStackFrame &frame) {
794 allocInsertPoint = frame.allocBlock->getFirstInsertionPt();
795 deallocInsertPoints = frame.deallocBlocks;
803 allocInsertPoint.getNodeParent()->getParent() ==
804 builder.GetInsertBlock()->getParent()) {
806 deallocBlocks->insert(deallocBlocks->end(), deallocInsertPoints.begin(),
807 deallocInsertPoints.end());
808 return allocInsertPoint;
818 if (builder.GetInsertBlock() ==
819 &builder.GetInsertBlock()->getParent()->getEntryBlock()) {
820 assert(builder.GetInsertPoint() == builder.GetInsertBlock()->end() &&
821 "Assuming end of basic block");
822 llvm::BasicBlock *entryBB = llvm::BasicBlock::Create(
823 builder.getContext(),
"entry", builder.GetInsertBlock()->getParent(),
824 builder.GetInsertBlock()->getNextNode());
825 builder.CreateBr(entryBB);
826 builder.SetInsertPoint(entryBB);
832 for (llvm::BasicBlock &block : *builder.GetInsertBlock()->getParent()) {
836 llvm::Instruction *terminator = block.getTerminatorOrNull();
837 if (isa_and_present<llvm::ReturnInst>(terminator))
838 deallocBlocks->emplace_back(&block);
842 llvm::BasicBlock &funcEntryBlock =
843 builder.GetInsertBlock()->getParent()->getEntryBlock();
844 return funcEntryBlock.getFirstInsertionPt();
850static llvm::CanonicalLoopInfo *
852 llvm::CanonicalLoopInfo *loopInfo =
nullptr;
853 moduleTranslation.
stackWalk<OpenMPLoopInfoStackFrame>(
854 [&](OpenMPLoopInfoStackFrame &frame) {
855 loopInfo = frame.loopInfo;
867 Region ®ion, StringRef blockName, llvm::IRBuilderBase &builder,
870 bool isLoopWrapper = isa<omp::LoopWrapperInterface>(region.
getParentOp());
872 llvm::BasicBlock *continuationBlock =
873 splitBB(builder,
true,
"omp.region.cont");
874 llvm::BasicBlock *sourceBlock = builder.GetInsertBlock();
876 llvm::LLVMContext &llvmContext = builder.getContext();
877 for (
Block &bb : region) {
878 llvm::BasicBlock *llvmBB = llvm::BasicBlock::Create(
879 llvmContext, blockName, builder.GetInsertBlock()->getParent(),
880 builder.GetInsertBlock()->getNextNode());
881 moduleTranslation.
mapBlock(&bb, llvmBB);
884 llvm::Instruction *sourceTerminator = sourceBlock->getTerminator();
891 unsigned numYields = 0;
893 if (!isLoopWrapper) {
894 bool operandsProcessed =
false;
896 if (omp::YieldOp yield = dyn_cast<omp::YieldOp>(bb.getTerminator())) {
897 if (!operandsProcessed) {
898 for (
unsigned i = 0, e = yield->getNumOperands(); i < e; ++i) {
899 continuationBlockPHITypes.push_back(
900 moduleTranslation.
convertType(yield->getOperand(i).getType()));
902 operandsProcessed =
true;
904 assert(continuationBlockPHITypes.size() == yield->getNumOperands() &&
905 "mismatching number of values yielded from the region");
906 for (
unsigned i = 0, e = yield->getNumOperands(); i < e; ++i) {
907 llvm::Type *operandType =
908 moduleTranslation.
convertType(yield->getOperand(i).getType());
910 assert(continuationBlockPHITypes[i] == operandType &&
911 "values of mismatching types yielded from the region");
921 if (!continuationBlockPHITypes.empty())
923 continuationBlockPHIs &&
924 "expected continuation block PHIs if converted regions yield values");
925 if (continuationBlockPHIs) {
926 llvm::IRBuilderBase::InsertPointGuard guard(builder);
927 continuationBlockPHIs->reserve(continuationBlockPHITypes.size());
928 builder.SetInsertPoint(continuationBlock->begin());
929 for (llvm::Type *ty : continuationBlockPHITypes)
930 continuationBlockPHIs->push_back(builder.CreatePHI(ty, numYields));
936 for (
Block *bb : blocks) {
937 llvm::BasicBlock *llvmBB = moduleTranslation.
lookupBlock(bb);
940 if (bb->isEntryBlock()) {
941 assert(sourceTerminator->getNumSuccessors() == 1 &&
942 "provided entry block has multiple successors");
943 assert(sourceTerminator->getSuccessor(0) == continuationBlock &&
944 "ContinuationBlock is not the successor of the entry block");
945 sourceTerminator->setSuccessor(0, llvmBB);
948 llvm::IRBuilderBase::InsertPointGuard guard(builder);
950 moduleTranslation.
convertBlock(*bb, bb->isEntryBlock(), builder)))
951 return llvm::make_error<PreviouslyReportedError>();
956 builder.CreateBr(continuationBlock);
967 Operation *terminator = bb->getTerminator();
968 if (isa<omp::TerminatorOp, omp::YieldOp>(terminator)) {
969 builder.CreateBr(continuationBlock);
971 for (
unsigned i = 0, e = terminator->
getNumOperands(); i < e; ++i)
972 (*continuationBlockPHIs)[i]->addIncoming(
986 return continuationBlock;
992 case omp::ClauseProcBindKind::Close:
993 return llvm::omp::ProcBindKind::OMP_PROC_BIND_close;
994 case omp::ClauseProcBindKind::Master:
995 return llvm::omp::ProcBindKind::OMP_PROC_BIND_master;
996 case omp::ClauseProcBindKind::Primary:
997 return llvm::omp::ProcBindKind::OMP_PROC_BIND_primary;
998 case omp::ClauseProcBindKind::Spread:
999 return llvm::omp::ProcBindKind::OMP_PROC_BIND_spread;
1001 llvm_unreachable(
"Unknown ClauseProcBindKind kind");
1008 auto dispatchOp = cast<omp::DispatchOp>(opInst);
1013 auto ®ion = dispatchOp.getRegion();
1018 builder.SetInsertPoint(*
result);
1026 auto maskedOp = cast<omp::MaskedOp>(opInst);
1027 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1032 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
1035 auto ®ion = maskedOp.getRegion();
1036 builder.restoreIP(codeGenIP);
1044 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
1046 llvm::Value *filterVal =
nullptr;
1047 if (
auto filterVar = maskedOp.getFilteredThreadId()) {
1048 filterVal = moduleTranslation.
lookupValue(filterVar);
1050 llvm::LLVMContext &llvmContext = builder.getContext();
1052 llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvmContext), 0);
1054 assert(filterVal !=
nullptr);
1055 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
1056 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
1058 ->createMasked(ompLoc, bodyGenCB, finiCB, filterVal);
1063 builder.restoreIP(*afterIP);
1071 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1072 auto masterOp = cast<omp::MasterOp>(opInst);
1077 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
1080 auto ®ion = masterOp.getRegion();
1081 builder.restoreIP(codeGenIP);
1089 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
1091 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
1092 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
1094 ->createMaster(ompLoc, bodyGenCB, finiCB);
1099 builder.restoreIP(*afterIP);
1107 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1108 auto criticalOp = cast<omp::CriticalOp>(opInst);
1113 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
1116 auto ®ion = cast<omp::CriticalOp>(opInst).getRegion();
1117 builder.restoreIP(codeGenIP);
1125 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
1127 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
1128 llvm::LLVMContext &llvmContext = moduleTranslation.
getLLVMContext();
1129 llvm::Constant *hint =
nullptr;
1132 if (criticalOp.getNameAttr()) {
1135 auto symbolRef = cast<SymbolRefAttr>(criticalOp.getNameAttr());
1136 auto criticalDeclareOp =
1140 llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvmContext),
1141 static_cast<int>(criticalDeclareOp.getHint()));
1143 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
1145 ->createCritical(ompLoc, bodyGenCB, finiCB,
1146 criticalOp.getName().value_or(
""), hint);
1151 builder.restoreIP(*afterIP);
1158struct PrivateVarsInfo {
1159 struct AllocatorPrivateInfo {
1160 llvm::Value *allocatedPtr;
1161 llvm::Value *allocator;
1164 template <
typename OP>
1165 PrivateVarsInfo(OP op)
1166 : blockArgs(llvm::to_vector(
1167 cast<omp::BlockArgOpenMPOpInterface>(*op).getPrivateBlockArgs())) {
1168 mlirVars.reserve(blockArgs.size());
1169 llvmVars.reserve(blockArgs.size());
1170 collectPrivatizationDecls<OP>(op);
1172 for (mlir::Value privateVar : op.getPrivateVars())
1173 mlirVars.push_back(privateVar);
1178 template <
typename OP>
1179 void addLinearVars(OP op) {
1180 numPrivateVars = blockArgs.size();
1183 cast<omp::BlockArgOpenMPOpInterface>(*op).getLinearBlockArgs());
1184 llvm::append_range(mlirVars, op.getLinearVars());
1185 if (std::optional<ArrayAttr> attr = op.getLinearSyms())
1186 for (
auto symbolRef : attr->getAsRange<SymbolRefAttr>())
1191 size_t numPrivateVars = 0;
1192 SmallVector<BlockArgument> blockArgs;
1193 SmallVector<mlir::Value> mlirVars;
1194 SmallVector<llvm::Value *> llvmVars;
1195 SmallVector<omp::PrivateClauseOp> privatizers;
1196 llvm::DenseMap<Value, llvm::Value *> convertedAllocators;
1197 SmallVector<AllocatorPrivateInfo> allocatorPrivates;
1203 void collectPrivatizationDecls(OP op) {
1204 std::optional<ArrayAttr> attr = op.getPrivateSyms();
1208 privatizers.reserve(privatizers.size() + attr->size());
1209 for (
auto symbolRef : attr->getAsRange<SymbolRefAttr>()) {
1217template <
typename T>
1221 std::optional<ArrayAttr> attr = op.getReductionSyms();
1225 reductions.reserve(reductions.size() + op.getNumReductionVars());
1226 for (
auto symbolRef : attr->getAsRange<SymbolRefAttr>()) {
1227 reductions.push_back(
1242 Operation *contextOp, std::optional<ArrayAttr> syms, StringRef opName,
1246 out.reserve(out.size() + syms->size());
1247 for (
auto sym : syms->getAsRange<SymbolRefAttr>()) {
1252 <<
"failed to resolve " << clauseName
1253 <<
" declare_reduction symbol " << sym.getRootReference() <<
" in "
1255 if (decl.getInitializerRegion().front().getNumArguments() != 1)
1257 <<
"not yet implemented: " << clauseName
1258 <<
" with two-argument initializer in " << opName;
1259 if (!decl.getCleanupRegion().empty())
1260 return contextOp->
emitError() <<
"not yet implemented: " << clauseName
1261 <<
" with cleanup region in " << opName;
1262 if (decl.getReductionRegion().empty())
1264 << clauseName <<
" declare_reduction is missing a combiner region";
1265 out.push_back(decl);
1276 Region ®ion, StringRef blockName, llvm::IRBuilderBase &builder,
1285 llvm::BasicBlock *insertBlock = builder.GetInsertBlock();
1286 llvm::Instruction *potentialTerminator =
1287 insertBlock->empty() ?
nullptr : &insertBlock->back();
1289 if (potentialTerminator && potentialTerminator->isTerminator()) {
1290 assert(builder.GetInsertPoint() == potentialTerminator->getIterator() &&
1291 "Insertion point should be the terminator");
1292 potentialTerminator->removeFromParent();
1294 builder.SetInsertPoint(insertBlock);
1300 llvm::DebugLoc loc = builder.getCurrentDebugLocation();
1302 region.
front(),
true, builder)))
1304 builder.SetCurrentDebugLocation(loc);
1307 if (continuationBlockArgs)
1309 *continuationBlockArgs,
1316 if (potentialTerminator && potentialTerminator->isTerminator()) {
1317 llvm::BasicBlock *block = builder.GetInsertBlock();
1318 if (block->empty()) {
1324 potentialTerminator->insertInto(block, block->begin());
1326 potentialTerminator->insertAfter(&block->back());
1340 if (continuationBlockArgs)
1341 llvm::append_range(*continuationBlockArgs, phis);
1342 builder.SetInsertPoint((*continuationBlock)->getFirstInsertionPt());
1349using OwningReductionGen =
1350 std::function<llvm::OpenMPIRBuilder::InsertPointOrErrorTy(
1351 llvm::OpenMPIRBuilder::InsertPointTy, llvm::Value *, llvm::Value *,
1353using OwningAtomicReductionGen =
1354 std::function<llvm::OpenMPIRBuilder::InsertPointOrErrorTy(
1355 llvm::OpenMPIRBuilder::InsertPointTy, llvm::Type *, llvm::Value *,
1357using OwningDataPtrPtrReductionGen =
1358 std::function<llvm::OpenMPIRBuilder::InsertPointOrErrorTy(
1359 llvm::OpenMPIRBuilder::InsertPointTy, llvm::Value *, llvm::Value *&)>;
1365static OwningReductionGen
1371 OwningReductionGen gen =
1372 [&, decl](llvm::OpenMPIRBuilder::InsertPointTy insertPoint,
1373 llvm::Value *lhs, llvm::Value *rhs,
1374 llvm::Value *&
result)
mutable
1375 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
1376 moduleTranslation.
mapValue(decl.getReductionLhsArg(), lhs);
1377 moduleTranslation.
mapValue(decl.getReductionRhsArg(), rhs);
1378 builder.restoreIP(insertPoint);
1381 "omp.reduction.nonatomic.body", builder,
1382 moduleTranslation, &phis)))
1383 return llvm::createStringError(
1384 "failed to inline `combiner` region of `omp.declare_reduction`");
1385 result = llvm::getSingleElement(phis);
1386 return builder.saveIP();
1395static OwningAtomicReductionGen
1397 llvm::IRBuilderBase &builder,
1399 if (decl.getAtomicReductionRegion().empty())
1400 return OwningAtomicReductionGen();
1406 [&, decl](llvm::OpenMPIRBuilder::InsertPointTy insertPoint, llvm::Type *,
1407 llvm::Value *lhs, llvm::Value *rhs)
mutable
1408 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
1409 moduleTranslation.
mapValue(decl.getAtomicReductionLhsArg(), lhs);
1410 moduleTranslation.
mapValue(decl.getAtomicReductionRhsArg(), rhs);
1411 builder.restoreIP(insertPoint);
1414 "omp.reduction.atomic.body", builder,
1415 moduleTranslation, &phis)))
1416 return llvm::createStringError(
1417 "failed to inline `atomic` region of `omp.declare_reduction`");
1418 assert(phis.empty());
1419 return builder.saveIP();
1428static OwningDataPtrPtrReductionGen
1431 if (!isByRef || decl.getDataPtrPtrRegion().empty())
1432 return OwningDataPtrPtrReductionGen();
1434 OwningDataPtrPtrReductionGen refDataPtrGen =
1435 [&, decl](llvm::OpenMPIRBuilder::InsertPointTy insertPoint,
1436 llvm::Value *byRefVal, llvm::Value *&
result)
mutable
1437 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
1438 moduleTranslation.
mapValue(decl.getDataPtrPtrRegionArg(), byRefVal);
1439 builder.restoreIP(insertPoint);
1442 "omp.data_ptr_ptr.body", builder,
1443 moduleTranslation, &phis)))
1444 return llvm::createStringError(
1445 "failed to inline `data_ptr_ptr` region of `omp.declare_reduction`");
1446 result = llvm::getSingleElement(phis);
1447 return builder.saveIP();
1450 return refDataPtrGen;
1457 auto orderedOp = cast<omp::OrderedOp>(opInst);
1462 omp::ClauseDepend dependType = *orderedOp.getDoacrossDependType();
1463 bool isDependSource = dependType == omp::ClauseDepend::dependsource;
1464 unsigned numLoops = *orderedOp.getDoacrossNumLoops();
1466 moduleTranslation.
lookupValues(orderedOp.getDoacrossDependVars());
1468 size_t indexVecValues = 0;
1469 while (indexVecValues < vecValues.size()) {
1471 storeValues.reserve(numLoops);
1472 for (
unsigned i = 0; i < numLoops; i++) {
1473 storeValues.push_back(vecValues[indexVecValues]);
1476 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
1478 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
1480 ->createOrderedDepend(ompLoc, allocaIP, numLoops,
1481 storeValues,
".cnt.addr",
1492 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1493 auto orderedRegionOp = cast<omp::OrderedRegionOp>(opInst);
1498 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
1501 auto ®ion = cast<omp::OrderedRegionOp>(opInst).getRegion();
1502 builder.restoreIP(codeGenIP);
1510 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
1512 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
1513 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
1515 ->createOrderedThreadsSimd(ompLoc, bodyGenCB, finiCB,
1516 !orderedRegionOp.getParLevelSimd());
1521 builder.restoreIP(*afterIP);
1527struct DeferredStore {
1528 DeferredStore(llvm::Value *value, llvm::Value *address)
1529 : value(value), address(address) {}
1532 llvm::Value *address;
1539template <
typename T>
1542 llvm::IRBuilderBase &builder,
1544 const llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
1550 llvm::IRBuilderBase::InsertPointGuard guard(builder);
1551 builder.SetInsertPoint(allocaIP.getNodeParent()->getTerminator());
1557 deferredStores.reserve(op.getNumReductionVars());
1559 for (std::size_t i = 0; i < op.getNumReductionVars(); ++i) {
1560 Region &allocRegion = reductionDecls[i].getAllocRegion();
1562 if (allocRegion.
empty())
1567 builder, moduleTranslation, &phis)))
1568 return op.emitError(
1569 "failed to inline `alloc` region of `omp.declare_reduction`");
1571 assert(phis.size() == 1 &&
"expected one allocation to be yielded");
1572 builder.SetInsertPoint(allocaIP.getNodeParent()->getTerminator());
1576 llvm::Type *ptrTy = builder.getPtrTy();
1580 if (useDeviceSharedMem) {
1581 var = ompBuilder->createOMPAllocShared(builder, varTy);
1583 var = builder.CreateAlloca(varTy);
1584 var = builder.CreatePointerBitCastOrAddrSpaceCast(var, ptrTy);
1587 llvm::Value *castPhi =
1588 builder.CreatePointerBitCastOrAddrSpaceCast(phis[0], ptrTy);
1590 deferredStores.emplace_back(castPhi, var);
1592 privateReductionVariables[i] = var;
1593 moduleTranslation.
mapValue(reductionArgs[i], castPhi);
1594 reductionVariableMap.try_emplace(op.getReductionVars()[i], castPhi);
1596 assert(allocRegion.
empty() &&
1597 "allocaction is implicit for by-val reduction");
1599 llvm::Type *ptrTy = builder.getPtrTy();
1603 if (useDeviceSharedMem) {
1604 var = ompBuilder->createOMPAllocShared(builder, varTy);
1606 var = builder.CreateAlloca(varTy);
1607 var = builder.CreatePointerBitCastOrAddrSpaceCast(var, ptrTy);
1610 moduleTranslation.
mapValue(reductionArgs[i], var);
1611 privateReductionVariables[i] = var;
1612 reductionVariableMap.try_emplace(op.getReductionVars()[i], var);
1620template <
typename T>
1623 llvm::IRBuilderBase &builder,
1628 mlir::omp::DeclareReductionOp &reduction = reductionDecls[i];
1629 Region &initializerRegion = reduction.getInitializerRegion();
1632 mlir::Value mlirSource = loop.getReductionVars()[i];
1633 llvm::Value *llvmSource = moduleTranslation.
lookupValue(mlirSource);
1634 llvm::Value *origVal = llvmSource;
1636 if (!isa<LLVM::LLVMPointerType>(
1637 reduction.getInitializerMoldArg().getType()) &&
1638 isa<LLVM::LLVMPointerType>(mlirSource.
getType())) {
1641 reduction.getInitializerMoldArg().getType()),
1642 llvmSource,
"omp_orig");
1644 moduleTranslation.
mapValue(reduction.getInitializerMoldArg(), origVal);
1647 llvm::Value *allocation =
1648 reductionVariableMap.lookup(loop.getReductionVars()[i]);
1649 moduleTranslation.
mapValue(reduction.getInitializerAllocArg(), allocation);
1655 llvm::BasicBlock *block =
nullptr) {
1656 if (block ==
nullptr)
1657 block = builder.GetInsertBlock();
1659 if (!block->hasTerminator())
1660 builder.SetInsertPoint(block);
1662 builder.SetInsertPoint(block->getTerminator());
1670template <
typename OP>
1673 llvm::IRBuilderBase &builder,
1675 llvm::BasicBlock *latestAllocaBlock,
1681 if (op.getNumReductionVars() == 0)
1687 llvm::BasicBlock *initBlock = splitBB(builder,
true,
"omp.reduction.init");
1690 llvm::IRBuilderBase::InsertPointGuard guard(builder);
1691 auto allocaIP = latestAllocaBlock->getTerminator()->getIterator();
1692 builder.restoreIP(allocaIP);
1694 for (
unsigned i = 0; i < op.getNumReductionVars(); ++i) {
1696 if (!reductionDecls[i].getAllocRegion().empty())
1704 if (useDeviceSharedMem)
1705 byRefVars[i] = ompBuilder->createOMPAllocShared(builder, varTy);
1707 byRefVars[i] = builder.CreateAlloca(varTy);
1716 for (
auto [data, addr] : deferredStores)
1717 builder.CreateStore(data, addr);
1722 for (
unsigned i = 0; i < op.getNumReductionVars(); ++i) {
1727 reductionVariableMap, i);
1735 "omp.reduction.neutral", builder,
1736 moduleTranslation, &phis)))
1739 assert(phis.size() == 1 &&
"expected one value to be yielded from the "
1740 "reduction neutral element declaration region");
1745 if (!reductionDecls[i].getAllocRegion().empty())
1754 builder.CreateStore(phis[0], byRefVars[i]);
1756 privateReductionVariables[i] = byRefVars[i];
1757 moduleTranslation.
mapValue(reductionArgs[i], phis[0]);
1758 reductionVariableMap.try_emplace(op.getReductionVars()[i], phis[0]);
1761 builder.CreateStore(phis[0], privateReductionVariables[i]);
1768 moduleTranslation.
forgetMapping(reductionDecls[i].getInitializerRegion());
1775template <
typename T>
1776static void collectReductionInfo(
1777 T loop, llvm::IRBuilderBase &builder,
1786 unsigned numReductions = loop.getNumReductionVars();
1788 for (
unsigned i = 0; i < numReductions; ++i) {
1791 owningAtomicReductionGens.push_back(
1794 reductionDecls[i], builder, moduleTranslation, isByRef[i]));
1798 reductionInfos.reserve(numReductions);
1799 for (
unsigned i = 0; i < numReductions; ++i) {
1800 llvm::OpenMPIRBuilder::ReductionGenAtomicCBTy
atomicGen =
nullptr;
1801 if (owningAtomicReductionGens[i])
1802 atomicGen = owningAtomicReductionGens[i];
1803 llvm::Value *variable =
1804 moduleTranslation.
lookupValue(loop.getReductionVars()[i]);
1807 if (
auto alloca = mlir::dyn_cast<LLVM::AllocaOp>(op)) {
1808 allocatedType = alloca.getElemType();
1815 reductionInfos.push_back(
1817 privateReductionVariables[i],
1818 llvm::OpenMPIRBuilder::EvalKind::Scalar,
1822 allocatedType ? moduleTranslation.
convertType(allocatedType) :
nullptr,
1823 reductionDecls[i].getByrefElementType()
1825 *reductionDecls[i].getByrefElementType())
1835 llvm::IRBuilderBase &builder, StringRef regionName,
1836 bool shouldLoadCleanupRegionArg =
true) {
1837 for (
auto [i, cleanupRegion] : llvm::enumerate(cleanupRegions)) {
1838 if (cleanupRegion->empty())
1844 llvm::Instruction *potentialTerminator =
1845 builder.GetInsertBlock()->empty() ?
nullptr
1846 : &builder.GetInsertBlock()->back();
1847 if (potentialTerminator && potentialTerminator->isTerminator())
1848 builder.SetInsertPoint(potentialTerminator);
1849 llvm::Value *privateVarValue =
1850 shouldLoadCleanupRegionArg
1851 ? builder.CreateLoad(
1853 privateVariables[i])
1854 : privateVariables[i];
1859 moduleTranslation)))
1872 OP op, llvm::IRBuilderBase &builder,
1874 llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
1877 bool isNowait =
false,
bool isTeamsReduction =
false) {
1879 if (op.getNumReductionVars() == 0)
1891 collectReductionInfo(op, builder, moduleTranslation, reductionDecls,
1893 owningReductionGenRefDataPtrGens,
1894 privateReductionVariables, reductionInfos, isByRef);
1899 llvm::UnreachableInst *tempTerminator = builder.CreateUnreachable();
1900 builder.SetInsertPoint(tempTerminator);
1901 llvm::DebugLoc reductionLoc = builder.getCurrentDebugLocation();
1902 llvm::OpenMPIRBuilder::InsertPointOrErrorTy contInsertPoint =
1903 ompBuilder->createReductions(builder, allocaIP, reductionInfos, isByRef,
1904 isNowait, isTeamsReduction);
1909 if (!contInsertPoint->isValid())
1910 return op->emitOpError() <<
"failed to convert reductions";
1912 llvm::OpenMPIRBuilder::InsertPointTy afterIP = *contInsertPoint;
1913 if (!isTeamsReduction && !isNowait) {
1914 llvm::OpenMPIRBuilder::InsertPointOrErrorTy barrierIP =
1915 ompBuilder->createBarrier({*contInsertPoint, reductionLoc},
1916 llvm::omp::OMPD_for);
1920 afterIP = *barrierIP;
1923 tempTerminator->eraseFromParent();
1924 builder.restoreIP(afterIP);
1928 llvm::transform(reductionDecls, std::back_inserter(reductionRegions),
1929 [](omp::DeclareReductionOp reductionDecl) {
1930 return &reductionDecl.getCleanupRegion();
1933 reductionRegions, privateReductionVariables, moduleTranslation, builder,
1934 "omp.reduction.cleanup");
1937 if (useDeviceSharedMem) {
1938 for (
auto [var, reductionDecl] :
1939 llvm::zip_equal(privateReductionVariables, reductionDecls))
1940 ompBuilder->createOMPFreeShared(
1941 builder, var, moduleTranslation.
convertType(reductionDecl.getType()));
1954template <
typename OP>
1958 llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
1963 if (op.getNumReductionVars() == 0)
1969 allocaIP, reductionDecls,
1970 privateReductionVariables, reductionVariableMap,
1971 deferredStores, isByRef)))
1974 return initReductionVars(op, reductionArgs, builder, moduleTranslation,
1975 allocaIP.getNodeParent(), reductionDecls,
1976 privateReductionVariables, reductionVariableMap,
1977 isByRef, deferredStores);
1991 if (mappedPrivateVars ==
nullptr || !mappedPrivateVars->contains(privateVar))
1994 Value blockArg = (*mappedPrivateVars)[privateVar];
1997 assert(isa<LLVM::LLVMPointerType>(blockArgType) &&
1998 "A block argument corresponding to a mapped var should have "
2001 if (privVarType == blockArgType)
2008 if (!isa<LLVM::LLVMPointerType>(privVarType))
2009 return builder.CreateLoad(moduleTranslation.
convertType(privVarType),
2026 llvm::Type *regionArgType =
2028 if (regionArgType->isPointerTy() || !value->getType()->isPointerTy())
2031 return builder.CreateLoad(regionArgType, value);
2038 omp::PrivateClauseOp privatizer, llvm::Value *var) {
2039 Region ®ion = privatizer.getDataAddressRegion();
2048 builder, moduleTranslation, &address)))
2049 return llvm::make_error<PreviouslyReportedError>();
2051 return address.front();
2061 omp::PrivateClauseOp &privDecl, llvm::Value *nonPrivateVar,
2063 llvm::BasicBlock *privInitBlock,
2065 Region &initRegion = privDecl.getInitRegion();
2066 if (initRegion.
empty())
2067 return llvmPrivateVar;
2069 assert(nonPrivateVar);
2070 moduleTranslation.
mapValue(privDecl.getInitMoldArg(), nonPrivateVar);
2071 moduleTranslation.
mapValue(privDecl.getInitPrivateArg(), llvmPrivateVar);
2076 moduleTranslation, &phis)))
2077 return llvm::createStringError(
2078 "failed to inline `init` region of `omp.private`");
2080 assert(phis.size() == 1 &&
"expected one allocation to be yielded");
2097 llvm::Value *llvmPrivateVar, llvm::BasicBlock *privInitBlock,
2100 builder, moduleTranslation, privDecl,
2103 blockArg, llvmPrivateVar, privInitBlock, mappedPrivateVars);
2109 PrivateVarsInfo &privateVarsInfo,
2111 if (privateVarsInfo.blockArgs.empty())
2112 return llvm::Error::success();
2114 llvm::BasicBlock *privInitBlock = splitBB(builder,
true,
"omp.private.init");
2117 for (
auto [idx, zip] : llvm::enumerate(llvm::zip_equal(
2118 privateVarsInfo.privatizers, privateVarsInfo.mlirVars,
2119 privateVarsInfo.blockArgs, privateVarsInfo.llvmVars))) {
2120 auto [privDecl, mlirPrivVar, blockArg, llvmPrivateVar] = zip;
2122 builder, moduleTranslation, privDecl, mlirPrivVar, blockArg,
2123 llvmPrivateVar, privInitBlock, mappedPrivateVars);
2126 return privVarOrErr.takeError();
2128 llvmPrivateVar = privVarOrErr.get();
2129 moduleTranslation.
mapValue(blockArg, llvmPrivateVar);
2134 return llvm::Error::success();
2139 llvm::IRBuilderBase &builder,
2141 PrivateVarsInfo &privateVarsInfo) {
2142 for (
Value allocatorVar : allocatorVars) {
2143 if (privateVarsInfo.convertedAllocators.contains(allocatorVar))
2146 llvm::Value *allocator = moduleTranslation.
lookupValue(allocatorVar);
2148 return op.
emitError(
"failed to translate OpenMP allocator operand");
2149 if (allocator->getType()->isIntegerTy())
2150 allocator = builder.CreateIntToPtr(allocator, builder.getPtrTy());
2151 else if (allocator->getType()->isPointerTy())
2152 allocator = builder.CreatePointerBitCastOrAddrSpaceCast(
2153 allocator, builder.getPtrTy());
2156 "OpenMP allocator operand must have integer or pointer type");
2158 privateVarsInfo.convertedAllocators.try_emplace(allocatorVar, allocator);
2166template <
typename T>
2168 T op, llvm::IRBuilderBase &builder,
2170 PrivateVarsInfo &privateVarsInfo,
2171 llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
2173 std::optional<llvm::OpenMPIRBuilder::InsertPointTy> allocatorIP =
2178 llvm::BasicBlock *allocaBB = allocaIP.getNodeParent();
2179 llvm::Instruction *allocaTerminator = allocaBB->getTerminator();
2180 splitBB(allocaTerminator->getIterator(),
true,
2181 allocaTerminator->getDebugLoc(),
"omp.region.after_alloca");
2183 allocaTerminator = allocaBB->getTerminator();
2185 assert(allocaTerminator->getNumSuccessors() == 1 &&
2186 "This is an unconditional branch created by splitBB");
2187 allocaIP = allocaTerminator->getIterator();
2189 llvm::Instruction *allocatorTerminator =
nullptr;
2190 llvm::BasicBlock *afterAllocatorAllocations =
nullptr;
2192 llvm::BasicBlock *allocatorBB = allocatorIP->getNodeParent();
2193 allocatorTerminator = allocatorBB->getTerminator();
2194 afterAllocatorAllocations = splitBB(
2195 allocatorTerminator->getIterator(),
true,
2196 allocatorTerminator->getDebugLoc(),
"omp.region.after_allocate");
2197 allocatorTerminator = allocatorBB->getTerminator();
2198 assert(allocatorTerminator->getNumSuccessors() == 1 &&
2199 "This is an unconditional branch created by splitBB");
2202 std::optional<llvm::IRBuilderBase::InsertPointGuard> guard;
2204 guard.emplace(builder);
2205 builder.SetInsertPoint(allocaTerminator);
2207 llvm::DataLayout dataLayout = builder.getDataLayout();
2208 llvm::BasicBlock *afterAllocas = allocaTerminator->getSuccessor(0);
2212 unsigned int allocaAS =
2213 moduleTranslation.
getLLVMModule()->getDataLayout().getAllocaAddrSpace();
2216 .getProgramAddressSpace();
2222 if constexpr (std::is_same_v<T, omp::ParallelOp> ||
2223 std::is_same_v<T, omp::ScopeOp>) {
2224 allocatorVars = op.getAllocatorVars();
2225 allocateAlignments = op.getAllocateAlignmentsAttr();
2226 if (
auto privateIndices = op.getAllocatePrivateIndicesAttr())
2227 for (
auto [allocateIndex, privateIndex] :
2228 llvm::enumerate(privateIndices.asArrayRef()))
2229 allocateItemForPrivate[privateIndex] = allocateIndex;
2232 for (
auto [privateIndex, tuple] : llvm::enumerate(llvm::zip_equal(
2233 privateVarsInfo.privatizers, privateVarsInfo.mlirVars,
2234 privateVarsInfo.blockArgs))) {
2235 auto [privDecl, mlirPrivVar, blockArg] = tuple;
2236 llvm::Type *llvmAllocType =
2237 moduleTranslation.
convertType(privDecl.getType());
2238 llvm::Value *llvmPrivateVar =
nullptr;
2239 int64_t allocateIndex = allocateItemForPrivate[privateIndex];
2240 builder.SetInsertPoint(allocateIndex >= 0 && allocatorTerminator
2241 ? allocatorTerminator
2242 : allocaTerminator);
2243 if (allocateIndex >= 0) {
2244 if (ompBuilder->Config.isTargetDevice() ||
2245 op->template getParentOfType<omp::TargetOp>())
2246 return llvm::createStringError(
2247 "allocate clause in an OpenMP device context is not supported");
2248 if (!llvmAllocType->isSized())
2249 return llvm::createStringError(
2250 "allocate clause private type must have a fixed size");
2251 llvm::TypeSize size = dataLayout.getTypeAllocSize(llvmAllocType);
2252 if (size.isScalable())
2253 return llvm::createStringError(
2254 "allocate clause private type must have a fixed size");
2255 llvm::IntegerType *sizeTy =
2256 moduleTranslation.
getLLVMModule()->getDataLayout().getIntPtrType(
2258 if (!llvm::isUIntN(sizeTy->getBitWidth(), size.getFixedValue()))
2259 return llvm::createStringError(
2260 "OpenMP allocation size cannot be represented by the target size "
2262 llvm::Value *sizeValue =
2263 llvm::ConstantInt::get(sizeTy, size.getFixedValue());
2265 Value allocatorVar = allocatorVars[allocateIndex];
2266 auto allocator = privateVarsInfo.convertedAllocators.find(allocatorVar);
2267 if (allocator == privateVarsInfo.convertedAllocators.end())
2268 return llvm::createStringError(
2269 "failed to find converted OpenMP allocator operand");
2270 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2272 allocateAlignments ? allocateAlignments[allocateIndex] : 0;
2273 if (alignment != 0) {
2277 uint64_t alignmentValue = std::max<uint64_t>(
2278 static_cast<uint64_t
>(alignment),
2279 dataLayout.getABITypeAlign(llvmAllocType).value());
2280 if (!llvm::isUIntN(sizeTy->getBitWidth(), alignmentValue))
2281 return llvm::createStringError(
2282 "OpenMP allocation alignment cannot be represented by the "
2283 "target size type");
2284 llvmPrivateVar = ompBuilder->createOMPAlignedAlloc(
2285 ompLoc, llvm::ConstantInt::get(sizeTy, alignmentValue), sizeValue,
2286 allocator->second,
"omp.private.alloc");
2288 llvmPrivateVar = ompBuilder->createOMPAlloc(
2289 ompLoc, sizeValue, allocator->second,
"omp.private.alloc");
2291 if (!llvmPrivateVar)
2292 return llvm::createStringError(
2293 "failed to create OpenMP private allocation");
2294 privateVarsInfo.allocatorPrivates.push_back(
2295 {llvmPrivateVar, allocator->second});
2296 }
else if (mightUseDeviceSharedMem &&
2298 llvmPrivateVar = ompBuilder->createOMPAllocShared(builder, llvmAllocType);
2300 llvmPrivateVar = builder.CreateAlloca(
2301 llvmAllocType,
nullptr,
"omp.private.alloc");
2302 if (allocaAS != defaultAS)
2303 llvmPrivateVar = builder.CreateAddrSpaceCast(
2304 llvmPrivateVar, builder.getPtrTy(defaultAS));
2307 privateVarsInfo.llvmVars.push_back(llvmPrivateVar);
2310 return afterAllocatorAllocations ? afterAllocatorAllocations : afterAllocas;
2321 if (mlir::isa<omp::ParallelOp>(parent))
2324 if (mlir::isa<omp::SingleOp, omp::CriticalOp, omp::MaskedOp, omp::MasterOp,
2325 omp::SectionOp>(parent))
2338 llvm::OpenMPIRBuilder::InsertPointOrErrorTy res =
2339 ompBuilder->createBarrier(builder, llvm::omp::OMPD_barrier);
2352 bool needsFirstprivate =
2353 llvm::any_of(privateDecls, [](omp::PrivateClauseOp &privOp) {
2354 return privOp.getDataSharingType() ==
2355 omp::DataSharingClauseType::FirstPrivate;
2358 if (!needsFirstprivate)
2359 return insertBarrier
2363 llvm::BasicBlock *copyBlock =
2364 splitBB(builder,
true,
"omp.private.copy");
2367 for (
auto [decl, moldVar, llvmVar] :
2368 llvm::zip_equal(privateDecls, moldVars, llvmPrivateVars)) {
2369 if (decl.getDataSharingType() != omp::DataSharingClauseType::FirstPrivate)
2373 Region ©Region = decl.getCopyRegion();
2376 builder, moduleTranslation, decl.getCopyMoldArg(), moldVar);
2378 builder, moduleTranslation, decl.getCopyPrivateArg(), llvmVar);
2380 moduleTranslation.
mapValue(decl.getCopyMoldArg(), copyMoldVar);
2383 moduleTranslation.
mapValue(decl.getCopyPrivateArg(), copyPrivateVar);
2387 moduleTranslation)))
2388 return decl.emitError(
"failed to inline `copy` region of `omp.private`");
2400 return insertBarrier
2414 llvm::transform(mlirPrivateVars, moldVars.begin(), [&](
mlir::Value mlirVar) {
2416 llvm::Value *moldVar = findAssociatedValue(
2417 mlirVar, builder, moduleTranslation, mappedPrivateVars);
2422 llvmPrivateVars, privateDecls, insertBarrier,
2426template <
typename T>
2430 PrivateVarsInfo &privateVarsInfo) {
2433 llvm::transform(privateVarsInfo.privatizers,
2434 std::back_inserter(privateCleanupRegions),
2435 [](omp::PrivateClauseOp privatizer) {
2436 return &privatizer.getDeallocRegion();
2440 privateVarsInfo.llvmVars, moduleTranslation,
2441 builder,
"omp.private.dealloc",
2443 return mlir::emitError(loc,
"failed to inline `dealloc` region of an "
2444 "`omp.private` op in");
2449 for (
auto [privDecl, llvmPrivVar, blockArg] :
2450 llvm::zip_equal(privateVarsInfo.privatizers, privateVarsInfo.llvmVars,
2451 privateVarsInfo.blockArgs)) {
2453 ompBuilder->createOMPFreeShared(
2454 builder, llvmPrivVar,
2455 moduleTranslation.
convertType(privDecl.getType()));
2459 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2460 for (
const PrivateVarsInfo::AllocatorPrivateInfo &allocation :
2461 llvm::reverse(privateVarsInfo.allocatorPrivates))
2462 ompBuilder->createOMPFree(ompLoc, allocation.allocatedPtr,
2463 allocation.allocator);
2475 if (mlir::isa<omp::CancelOp, omp::CancellationPointOp>(child))
2492 llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder::InsertPointTy allocaIP,
2494 bool isWorksharing =
false);
2501template <
typename OpTy>
2505 llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder::InsertPointTy allocaIP,
2509 for (
unsigned i = 0, e = op.getNumReductionVars(); i != e; ++i) {
2510 if (op.getReductionModifier(i) != omp::ReductionModifier::task)
2512 taskDecls.push_back(reductionDecls[i]);
2513 taskVariables.push_back(privateReductionVariables[i]);
2516 taskDecls, taskVariables,
"__omp_taskred_mod_", builder, allocaIP,
2517 moduleTranslation,
true, isWorksharing);
2523 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2524 using StorableBodyGenCallbackTy =
2525 llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
2527 auto sectionsOp = cast<omp::SectionsOp>(opInst);
2533 assert(isByRef.size() == sectionsOp.getNumReductionVars());
2537 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
2541 sectionsOp.getNumReductionVars());
2545 cast<omp::BlockArgOpenMPOpInterface>(opInst).getReductionBlockArgs();
2548 sectionsOp, reductionArgs, builder, moduleTranslation, allocaIP,
2549 reductionDecls, privateReductionVariables, reductionVariableMap,
2553 bool isTaskReductionMod =
2554 sectionsOp.hasReductionModifier(omp::ReductionModifier::task);
2559 auto sectionOp = dyn_cast<omp::SectionOp>(op);
2563 Region ®ion = sectionOp.getRegion();
2564 auto sectionCB = [§ionsOp, ®ion, &builder, &moduleTranslation](
2565 InsertPointTy allocaIP, InsertPointTy codeGenIP,
2567 builder.restoreIP(codeGenIP);
2574 sectionsOp.getRegion().getNumArguments());
2575 for (
auto [sectionsArg, sectionArg] : llvm::zip_equal(
2576 sectionsOp.getRegion().getArguments(), region.
getArguments())) {
2577 llvm::Value *llvmVal = moduleTranslation.
lookupValue(sectionsArg);
2579 moduleTranslation.
mapValue(sectionArg, llvmVal);
2586 sectionCBs.push_back(sectionCB);
2592 if (sectionCBs.empty())
2600 if (isTaskReductionMod &&
2602 sectionsOp, reductionDecls, privateReductionVariables, builder,
2603 allocaIP, moduleTranslation,
true))
2604 return sectionsOp.emitError(
2605 "failed to emit task reduction modifier initialization");
2607 assert(isa<omp::SectionOp>(*sectionsOp.getRegion().op_begin()));
2612 auto privCB = [&](InsertPointTy, InsertPointTy codeGenIP, llvm::Value &,
2613 llvm::Value &vPtr, llvm::Value *&replacementValue)
2614 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
2615 replacementValue = &vPtr;
2621 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
2625 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2626 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2628 ->createSections(ompLoc, allocaIP, sectionCBs, privCB, finiCB,
2629 isCancellable, sectionsOp.getNowait());
2634 builder.restoreIP(*afterIP);
2637 if (isTaskReductionMod)
2643 sectionsOp, builder, moduleTranslation, allocaIP, reductionDecls,
2644 privateReductionVariables, isByRef, sectionsOp.getNowait());
2651 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2658 assert(isByRef.size() == scopeOp.getNumReductionVars());
2660 PrivateVarsInfo privateVarsInfo(scopeOp);
2662 moduleTranslation, privateVarsInfo)))
2667 InsertPointTy privateAllocaIP =
2671 scopeOp.getNumReductionVars());
2675 cast<omp::BlockArgOpenMPOpInterface>(*scopeOp).getReductionBlockArgs();
2677 if (scopeOp.getAllocateVars().empty()) {
2679 scopeOp, builder, moduleTranslation, privateVarsInfo, privateAllocaIP);
2685 scopeOp, reductionArgs, builder, moduleTranslation, privateAllocaIP,
2686 reductionDecls, privateReductionVariables, reductionVariableMap,
2691 [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
2693 if (!scopeOp.getAllocateVars().empty()) {
2697 scopeOp, builder, moduleTranslation, privateVarsInfo, privateAllocaIP,
2698 nullptr, codeGenIP);
2700 return llvm::make_error<PreviouslyReportedError>();
2701 builder.SetInsertPoint(afterAllocas.get()->getTerminator());
2703 builder.restoreIP(codeGenIP);
2710 return llvm::make_error<PreviouslyReportedError>();
2713 scopeOp, builder, moduleTranslation, privateVarsInfo.mlirVars,
2714 privateVarsInfo.llvmVars, privateVarsInfo.privatizers,
2715 scopeOp.getPrivateNeedsBarrier())))
2716 return llvm::make_error<PreviouslyReportedError>();
2723 auto finiCB = [&](InsertPointTy codeGenIP) -> llvm::Error {
2724 InsertPointTy oldIP = builder.saveIP();
2725 builder.restoreIP(codeGenIP);
2727 scopeOp.getLoc(), privateVarsInfo)))
2728 return llvm::make_error<PreviouslyReportedError>();
2729 builder.restoreIP(oldIP);
2730 return llvm::Error::success();
2733 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2734 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2735 ompBuilder->createScope(ompLoc, bodyCB, finiCB, scopeOp.getNowait());
2740 builder.restoreIP(*afterIP);
2744 scopeOp, builder, moduleTranslation, privateAllocaIP, reductionDecls,
2745 privateReductionVariables, isByRef, scopeOp.getNowait(),
2753 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2754 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2759 auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
2761 builder.restoreIP(codegenIP);
2763 builder, moduleTranslation)
2766 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
2770 std::optional<ArrayAttr> cpFuncs = singleOp.getCopyprivateSyms();
2773 for (
size_t i = 0, e = cpVars.size(); i < e; ++i) {
2774 llvmCPVars.push_back(moduleTranslation.
lookupValue(cpVars[i]));
2776 singleOp, cast<SymbolRefAttr>((*cpFuncs)[i]));
2777 llvmCPFuncs.push_back(
2781 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2783 ->createSingle(ompLoc, bodyCB, finiCB, singleOp.getNowait(),
2784 llvmCPVars, llvmCPFuncs);
2789 builder.restoreIP(*afterIP);
2793static omp::DistributeOp
2797 omp::DistributeOp distOp;
2798 WalkResult walk = teamsOp.getRegion().walk([&](omp::DistributeOp op) {
2804 if (walk.wasInterrupted() || !distOp)
2808 llvm::cast<mlir::omp::BlockArgOpenMPOpInterface>(teamsOp.getOperation());
2812 for (
auto ra : iface.getReductionBlockArgs())
2813 for (
auto &use : ra.getUses()) {
2814 auto *useOp = use.getOwner();
2816 if (mlir::isa<LLVM::DbgDeclareOp, LLVM::DbgValueOp>(useOp)) {
2817 debugUses.push_back(useOp);
2820 if (!distOp->isProperAncestor(useOp))
2827 for (
auto *use : debugUses)
2836 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2841 unsigned numReductionVars = op.getNumReductionVars();
2845 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
2851 if (doTeamsReduction) {
2852 isByRef =
getIsByRef(op.getReductionByref());
2854 assert(isByRef.size() == op.getNumReductionVars());
2857 llvm::cast<omp::BlockArgOpenMPOpInterface>(*op).getReductionBlockArgs();
2862 op, reductionArgs, builder, moduleTranslation, allocaIP,
2863 reductionDecls, privateReductionVariables, reductionVariableMap,
2868 auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
2871 moduleTranslation, allocaIP.getNodeParent(), deallocBlocks);
2872 builder.restoreIP(codegenIP);
2878 llvm::Value *numTeamsLower =
nullptr;
2879 if (
Value numTeamsLowerVar = op.getNumTeamsLower())
2880 numTeamsLower = moduleTranslation.
lookupValue(numTeamsLowerVar);
2882 llvm::Value *numTeamsUpper =
nullptr;
2883 if (!op.getNumTeamsUpperVars().empty())
2884 numTeamsUpper = moduleTranslation.
lookupValue(op.getNumTeams(0));
2886 llvm::Value *threadLimit =
nullptr;
2887 if (!op.getThreadLimitVars().empty())
2888 threadLimit = moduleTranslation.
lookupValue(op.getThreadLimit(0));
2890 llvm::Value *ifExpr =
nullptr;
2891 if (
Value ifVar = op.getIfExpr())
2894 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2895 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2897 ->createTeams(ompLoc, bodyCB, numTeamsLower, numTeamsUpper,
2898 threadLimit, ifExpr);
2903 builder.restoreIP(*afterIP);
2904 if (doTeamsReduction) {
2907 op, builder, moduleTranslation, allocaIP, reductionDecls,
2908 privateReductionVariables, isByRef,
2914static llvm::omp::RTLDependenceKindTy
2917 case mlir::omp::ClauseTaskDepend::taskdependin:
2918 return llvm::omp::RTLDependenceKindTy::DepIn;
2922 case mlir::omp::ClauseTaskDepend::taskdependout:
2923 case mlir::omp::ClauseTaskDepend::taskdependinout:
2924 return llvm::omp::RTLDependenceKindTy::DepInOut;
2925 case mlir::omp::ClauseTaskDepend::taskdependmutexinoutset:
2926 return llvm::omp::RTLDependenceKindTy::DepMutexInOutSet;
2927 case mlir::omp::ClauseTaskDepend::taskdependinoutset:
2928 return llvm::omp::RTLDependenceKindTy::DepInOutSet;
2930 llvm_unreachable(
"unhandled depend kind");
2934 std::optional<ArrayAttr> dependKinds,
OperandRange dependVars,
2937 if (dependVars.empty())
2939 for (
auto dep : llvm::zip(dependVars, dependKinds->getValue())) {
2941 cast<mlir::omp::ClauseTaskDependAttr>(std::get<1>(dep)).getValue();
2943 llvm::Value *depVal = moduleTranslation.
lookupValue(std::get<0>(dep));
2944 llvm::OpenMPIRBuilder::DependData dd(type, depVal->getType(), depVal);
2945 dds.emplace_back(dd);
2957 llvm::IRBuilderBase &llvmBuilder, llvm::OpenMPIRBuilder &ompBuilder,
2959 auto finiCB = [&](llvm::OpenMPIRBuilder::InsertPointTy ip) -> llvm::Error {
2960 llvm::IRBuilderBase::InsertPointGuard guard(llvmBuilder);
2964 llvmBuilder.restoreIP(ip);
2970 cancelTerminators.push_back(llvmBuilder.CreateBr(ip.getNodeParent()));
2971 return llvm::Error::success();
2976 ompBuilder.pushFinalizationCB(
2986 llvm::OpenMPIRBuilder &ompBuilder,
2987 llvm::BasicBlock *afterBB) {
2988 ompBuilder.popFinalizationCB();
2989 llvm::BasicBlock *constructFini = afterBB->getSinglePredecessor();
2990 for (llvm::UncondBrInst *cancelBranch : cancelTerminators)
2991 cancelBranch->setSuccessor(constructFini);
2997class TaskContextStructManager {
2999 TaskContextStructManager(llvm::IRBuilderBase &builder,
3000 LLVM::ModuleTranslation &moduleTranslation,
3001 MutableArrayRef<omp::PrivateClauseOp> privateDecls)
3002 : builder{builder}, moduleTranslation{moduleTranslation},
3003 privateDecls{privateDecls} {}
3009 void generateTaskContextStruct();
3015 void createGEPsToPrivateVars();
3021 SmallVector<llvm::Value *>
3022 createGEPsToPrivateVars(llvm::Value *altStructPtr)
const;
3025 void freeStructPtr();
3027 MutableArrayRef<llvm::Value *> getLLVMPrivateVarGEPs() {
3028 return llvmPrivateVarGEPs;
3031 llvm::Value *getStructPtr() {
return structPtr; }
3034 llvm::IRBuilderBase &builder;
3035 LLVM::ModuleTranslation &moduleTranslation;
3036 MutableArrayRef<omp::PrivateClauseOp> privateDecls;
3039 SmallVector<llvm::Type *> privateVarTypes;
3043 SmallVector<llvm::Value *> llvmPrivateVarGEPs;
3046 llvm::Value *structPtr =
nullptr;
3048 llvm::Type *structTy =
nullptr;
3060 llvm::SmallVector<llvm::Value *> lowerBounds;
3061 llvm::SmallVector<llvm::Value *> upperBounds;
3062 llvm::SmallVector<llvm::Value *> steps;
3063 llvm::SmallVector<llvm::Value *> trips;
3065 llvm::Value *totalTrips;
3068 IteratorInfo(mlir::omp::IteratorOp itersOp,
3069 mlir::LLVM::ModuleTranslation &moduleTranslation,
3070 llvm::IRBuilderBase &builder) {
3071 dims = itersOp.getLoopLowerBounds().size();
3072 lowerBounds.resize(dims);
3073 upperBounds.resize(dims);
3077 for (
unsigned d = 0; d < dims; ++d) {
3079 moduleTranslation.
lookupValue(itersOp.getLoopLowerBounds()[d]);
3081 moduleTranslation.
lookupValue(itersOp.getLoopUpperBounds()[d]);
3083 moduleTranslation.
lookupValue(itersOp.getLoopSteps()[d]);
3084 assert(lb && ub && st &&
3085 "Expect lowerBounds, upperBounds, and steps in IteratorOp");
3086 assert(lb->getType() == ub->getType() && lb->getType() == st->getType() &&
3087 "Expect matching iterator range types");
3088 assert((!llvm::isa<llvm::ConstantInt>(st) ||
3089 !llvm::cast<llvm::ConstantInt>(st)->isZero()) &&
3090 "Expect non-zero step in IteratorOp");
3092 lowerBounds[d] = lb;
3093 upperBounds[d] = ub;
3098 llvm::Type *countTy =
3099 builder.getIntNTy(lb->getType()->getIntegerBitWidth() + 1);
3100 llvm::Value *start = builder.CreateSExt(lb, countTy);
3101 llvm::Value *stop = builder.CreateSExt(ub, countTy);
3102 llvm::Value *step = builder.CreateSExt(st, countTy);
3103 llvm::Value *count =
3105 ->calculateCanonicalLoopTripCount(
3106 builder, start, stop, step,
3107 true, itersOp.getLoopInclusive(),
"iterator");
3108 trips[d] = builder.CreateZExtOrTrunc(count, builder.getInt64Ty());
3111 totalTrips = llvm::ConstantInt::get(builder.getInt64Ty(), 1);
3112 for (
unsigned d = 0; d < dims; ++d)
3113 totalTrips = builder.CreateMul(totalTrips, trips[d]);
3116 unsigned getDims()
const {
return dims; }
3117 llvm::ArrayRef<llvm::Value *> getLowerBounds()
const {
return lowerBounds; }
3118 llvm::ArrayRef<llvm::Value *> getUpperBounds()
const {
return upperBounds; }
3119 llvm::ArrayRef<llvm::Value *> getSteps()
const {
return steps; }
3120 llvm::ArrayRef<llvm::Value *> getTrips()
const {
return trips; }
3121 llvm::Value *getTotalTrips()
const {
return totalTrips; }
3125void TaskContextStructManager::generateTaskContextStruct() {
3126 if (privateDecls.empty())
3128 privateVarTypes.reserve(privateDecls.size());
3130 for (omp::PrivateClauseOp &privOp : privateDecls) {
3133 if (!privOp.readsFromMold())
3135 Type mlirType = privOp.getType();
3136 privateVarTypes.push_back(moduleTranslation.
convertType(mlirType));
3139 if (privateVarTypes.empty())
3142 structTy = llvm::StructType::get(moduleTranslation.
getLLVMContext(),
3145 llvm::DataLayout dataLayout = builder.getDataLayout();
3146 llvm::Type *intPtrTy = builder.getIntPtrTy(dataLayout);
3147 llvm::Value *allocSize =
3148 builder.CreateTypeSize(intPtrTy, dataLayout.getTypeAllocSize(structTy));
3151 structPtr = builder.CreateMalloc(intPtrTy, allocSize,
3153 "omp.task.context_ptr");
3156SmallVector<llvm::Value *> TaskContextStructManager::createGEPsToPrivateVars(
3157 llvm::Value *altStructPtr)
const {
3158 SmallVector<llvm::Value *> ret;
3161 ret.reserve(privateDecls.size());
3162 llvm::Value *zero = builder.getInt32(0);
3164 for (
auto privDecl : privateDecls) {
3165 if (!privDecl.readsFromMold()) {
3167 ret.push_back(
nullptr);
3170 llvm::Value *iVal = builder.getInt32(i);
3171 llvm::Value *gep = builder.CreateGEP(structTy, altStructPtr, {zero, iVal});
3178void TaskContextStructManager::createGEPsToPrivateVars() {
3180 assert(privateVarTypes.empty());
3184 llvmPrivateVarGEPs = createGEPsToPrivateVars(structPtr);
3187void TaskContextStructManager::freeStructPtr() {
3191 llvm::IRBuilderBase::InsertPointGuard guard{builder};
3193 builder.SetInsertPoint(builder.GetInsertBlock()->getTerminator());
3194 builder.CreateFree(structPtr);
3198 llvm::OpenMPIRBuilder &ompBuilder,
3199 llvm::Value *affinityList, llvm::Value *
index,
3200 llvm::Value *addr, llvm::Value *len) {
3201 llvm::StructType *kmpTaskAffinityInfoTy =
3202 ompBuilder.getKmpTaskAffinityInfoTy();
3203 llvm::Value *entry = builder.CreateInBoundsGEP(
3204 kmpTaskAffinityInfoTy, affinityList,
index,
"omp.affinity.entry");
3206 addr = builder.CreatePtrToInt(addr, kmpTaskAffinityInfoTy->getElementType(0));
3207 len = builder.CreateIntCast(len, kmpTaskAffinityInfoTy->getElementType(1),
3209 llvm::Value *flags = builder.getInt32(0);
3211 builder.CreateStore(addr,
3212 builder.CreateStructGEP(kmpTaskAffinityInfoTy, entry, 0));
3213 builder.CreateStore(len,
3214 builder.CreateStructGEP(kmpTaskAffinityInfoTy, entry, 1));
3215 builder.CreateStore(flags,
3216 builder.CreateStructGEP(kmpTaskAffinityInfoTy, entry, 2));
3220 llvm::IRBuilderBase &builder,
3222 llvm::Value *affinityList) {
3223 for (
auto [i, affinityVar] : llvm::enumerate(affinityVars)) {
3224 auto entryOp = affinityVar.getDefiningOp<mlir::omp::AffinityEntryOp>();
3225 assert(entryOp &&
"affinity item must be omp.affinity_entry");
3227 llvm::Value *addr = moduleTranslation.
lookupValue(entryOp.getAddr());
3228 llvm::Value *len = moduleTranslation.
lookupValue(entryOp.getLen());
3229 assert(addr && len &&
"expect affinity addr and len to be non-null");
3231 affinityList, builder.getInt64(i), addr, len);
3236 llvm::Value *linearIV, IteratorInfo &iterInfo,
mlir::Region &iteratorRegion,
3239 llvm::Value *tmp = linearIV;
3240 for (
int d = (
int)iterInfo.getDims() - 1; d >= 0; --d) {
3241 llvm::Value *trip = iterInfo.getTrips()[d];
3242 llvm::Value *zero = llvm::ConstantInt::get(trip->getType(), 0);
3243 llvm::Value *one = llvm::ConstantInt::get(trip->getType(), 1);
3246 llvm::Value *divisor =
3247 builder.CreateSelect(builder.CreateICmpEQ(trip, zero), one, trip);
3249 llvm::Value *idx = builder.CreateURem(tmp, divisor);
3251 tmp = builder.CreateUDiv(tmp, divisor);
3255 builder.CreateZExtOrTrunc(idx, iterInfo.getLowerBounds()[d]->getType());
3256 llvm::Value *physIV = builder.CreateAdd(
3257 iterInfo.getLowerBounds()[d],
3258 builder.CreateMul(idx, iterInfo.getSteps()[d]),
"omp.it.phys_iv");
3265 moduleTranslation.
mapBlock(&entryBlock, builder.GetInsertBlock());
3266 return moduleTranslation.
convertBlock(entryBlock,
true,
3274 llvm::BasicBlock *continuation =
3275 splitBB(builder,
true,
"omp.iterator.region.cont");
3276 llvm::Instruction *sourceBranch = builder.GetInsertBlock()->getTerminator();
3280 llvm::BasicBlock::Create(builder.getContext(),
"omp.iterator.region",
3281 continuation->getParent(), continuation));
3282 sourceBranch->setSuccessor(0, moduleTranslation.
lookupBlock(&entryBlock));
3285 llvm::IRBuilderBase::InsertPointGuard guard(builder);
3286 if (failed(moduleTranslation.
convertBlock(*block, block->isEntryBlock(),
3288 return mlir::failure();
3289 if (isa<omp::YieldOp>(block->getTerminator()))
3290 builder.CreateBr(continuation);
3294 builder.SetInsertPoint(continuation);
3295 return mlir::success();
3301static mlir::LogicalResult
3304 IteratorInfo &iterInfo, llvm::StringRef loopName,
3308 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
3310 auto bodyGen = [&](llvm::OpenMPIRBuilder::InsertPointTy bodyIP,
3311 llvm::Value *linearIV) -> llvm::Error {
3312 llvm::IRBuilderBase::InsertPointGuard guard(builder);
3313 builder.restoreIP(bodyIP);
3316 moduleTranslation))) {
3317 return llvm::make_error<llvm::StringError>(
3318 "failed to convert iterator region", llvm::inconvertibleErrorCode());
3321 mlir::omp::YieldOp yield = itersOp.getYieldOp();
3322 assert(yield && yield.getResults().size() == 1 &&
3323 "expect omp.yield in iterator region to have one result");
3325 genStoreEntry(linearIV, yield);
3331 return llvm::Error::success();
3334 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
3336 ->createIteratorLoop(loc, iterInfo.getTotalTrips(), bodyGen,
3341 builder.restoreIP(*afterIP);
3343 return mlir::success();
3346static mlir::LogicalResult
3349 llvm::OpenMPIRBuilder::AffinityData &ad) {
3351 if (taskOp.getAffinityVars().empty() && taskOp.getIterated().empty()) {
3354 return mlir::success();
3358 llvm::StructType *kmpTaskAffinityInfoTy =
3361 auto allocateAffinityList = [&](llvm::Value *count) -> llvm::Value * {
3362 llvm::IRBuilderBase::InsertPointGuard guard(builder);
3363 if (llvm::isa<llvm::Constant>(count) || llvm::isa<llvm::Argument>(count))
3365 return builder.CreateAlloca(kmpTaskAffinityInfoTy, count,
3366 "omp.affinity_list");
3369 auto createAffinity =
3370 [&](llvm::Value *count,
3371 llvm::Value *info) -> llvm::OpenMPIRBuilder::AffinityData {
3372 llvm::OpenMPIRBuilder::AffinityData ad{};
3373 ad.Count = builder.CreateTrunc(count, builder.getInt32Ty());
3375 builder.CreatePointerBitCastOrAddrSpaceCast(info, builder.getPtrTy(0));
3379 if (!taskOp.getAffinityVars().empty()) {
3380 llvm::Value *count = llvm::ConstantInt::get(
3381 builder.getInt64Ty(), taskOp.getAffinityVars().size());
3382 llvm::Value *list = allocateAffinityList(count);
3385 ads.emplace_back(createAffinity(count, list));
3388 if (!taskOp.getIterated().empty()) {
3389 for (
auto [i, iter] : llvm::enumerate(taskOp.getIterated())) {
3390 auto itersOp = iter.getDefiningOp<omp::IteratorOp>();
3391 assert(itersOp &&
"iterated value must be defined by omp.iterator");
3392 IteratorInfo iterInfo(itersOp, moduleTranslation, builder);
3393 llvm::Value *affList = allocateAffinityList(iterInfo.getTotalTrips());
3395 itersOp, builder, moduleTranslation, iterInfo,
"iterator",
3396 [&](llvm::Value *linearIV, mlir::omp::YieldOp yield) {
3397 auto entryOp = yield.getResults()[0]
3398 .getDefiningOp<mlir::omp::AffinityEntryOp>();
3399 assert(entryOp &&
"expect yield produce an affinity entry");
3406 affList, linearIV, addr, len);
3408 return llvm::failure();
3409 ads.emplace_back(createAffinity(iterInfo.getTotalTrips(), affList));
3413 llvm::Value *totalAffinityCount = builder.getInt32(0);
3414 for (
const auto &affinity : ads)
3415 totalAffinityCount = builder.CreateAdd(
3417 builder.CreateIntCast(affinity.Count, builder.getInt32Ty(),
3420 llvm::Value *affinityInfo = ads.front().Info;
3421 if (ads.size() > 1) {
3422 llvm::StructType *kmpTaskAffinityInfoTy =
3424 llvm::Value *affinityInfoElemSize = builder.getInt64(
3425 moduleTranslation.
getLLVMModule()->getDataLayout().getTypeAllocSize(
3426 kmpTaskAffinityInfoTy));
3428 llvm::Value *packedAffinityInfo = allocateAffinityList(totalAffinityCount);
3429 llvm::Value *packedAffinityInfoOffset = builder.getInt32(0);
3430 for (
const auto &affinity : ads) {
3431 llvm::Value *affinityCount = builder.CreateIntCast(
3432 affinity.Count, builder.getInt32Ty(),
false);
3433 llvm::Value *affinityCountInt64 = builder.CreateIntCast(
3434 affinityCount, builder.getInt64Ty(),
false);
3435 llvm::Value *affinityInfoSize =
3436 builder.CreateMul(affinityCountInt64, affinityInfoElemSize);
3438 llvm::Value *packedAffinityInfoIndex = builder.CreateIntCast(
3439 packedAffinityInfoOffset, kmpTaskAffinityInfoTy->getElementType(0),
3441 packedAffinityInfoIndex = builder.CreateInBoundsGEP(
3442 kmpTaskAffinityInfoTy, packedAffinityInfo, packedAffinityInfoIndex);
3444 builder.CreateMemCpy(
3445 packedAffinityInfoIndex, llvm::Align(1),
3446 builder.CreatePointerBitCastOrAddrSpaceCast(
3447 affinity.Info, builder.getPtrTy(packedAffinityInfoIndex->getType()
3448 ->getPointerAddressSpace())),
3449 llvm::Align(1), affinityInfoSize);
3451 packedAffinityInfoOffset =
3452 builder.CreateAdd(packedAffinityInfoOffset, affinityCount);
3455 affinityInfo = packedAffinityInfo;
3458 ad.Count = totalAffinityCount;
3459 ad.Info = affinityInfo;
3461 return mlir::success();
3467static mlir::LogicalResult
3470 std::optional<ArrayAttr> dependIteratedKinds,
3471 llvm::IRBuilderBase &builder,
3473 llvm::OpenMPIRBuilder::DependenciesInfo &taskDeps) {
3474 if (dependIterated.empty()) {
3477 return mlir::success();
3481 llvm::Type *dependInfoTy = ompBuilder.DependInfo;
3482 unsigned numLocator = dependVars.size();
3485 llvm::Value *totalCount =
3486 llvm::ConstantInt::get(builder.getInt64Ty(), numLocator);
3489 for (
auto iter : dependIterated) {
3490 auto itersOp = iter.getDefiningOp<mlir::omp::IteratorOp>();
3491 assert(itersOp &&
"depend_iterated value must be defined by omp.iterator");
3492 iterInfos.emplace_back(itersOp, moduleTranslation, builder);
3494 builder.CreateAdd(totalCount, iterInfos.back().getTotalTrips());
3499 llvm::DataLayout dataLayout = builder.getDataLayout();
3500 llvm::Value *allocSize = builder.CreateTypeSize(
3501 ompBuilder.SizeTy, dataLayout.getTypeAllocSize(dependInfoTy));
3502 llvm::Value *depArray =
3503 builder.CreateMalloc(ompBuilder.SizeTy, allocSize, totalCount,
3504 nullptr,
".dep.arr.addr");
3507 if (numLocator > 0) {
3510 for (
auto [i, dd] : llvm::enumerate(dds)) {
3511 llvm::Value *idx = llvm::ConstantInt::get(builder.getInt64Ty(), i);
3512 llvm::Value *entry =
3513 builder.CreateInBoundsGEP(dependInfoTy, depArray, idx);
3514 ompBuilder.emitTaskDependency(builder, entry, dd);
3519 llvm::Value *offset =
3520 llvm::ConstantInt::get(builder.getInt64Ty(), numLocator);
3521 for (
auto [i, iterInfo] : llvm::enumerate(iterInfos)) {
3522 auto kindAttr = cast<mlir::omp::ClauseTaskDependAttr>(
3523 dependIteratedKinds->getValue()[i]);
3524 llvm::omp::RTLDependenceKindTy rtlKind =
3527 auto itersOp = dependIterated[i].getDefiningOp<mlir::omp::IteratorOp>();
3529 itersOp, builder, moduleTranslation, iterInfo,
"dep_iterator",
3530 [&](llvm::Value *linearIV, mlir::omp::YieldOp yield) {
3532 moduleTranslation.
lookupValue(yield.getResults()[0]);
3533 llvm::Value *idx = builder.CreateAdd(offset, linearIV);
3534 llvm::Value *entry =
3535 builder.CreateInBoundsGEP(dependInfoTy, depArray, idx);
3536 ompBuilder.emitTaskDependency(
3538 llvm::OpenMPIRBuilder::DependData{rtlKind, addr->getType(),
3541 return mlir::failure();
3544 offset = builder.CreateAdd(offset, iterInfo.getTotalTrips());
3547 taskDeps.DepArray = depArray;
3548 taskDeps.NumDeps = builder.CreateTrunc(totalCount, builder.getInt32Ty());
3549 return mlir::success();
3556 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
3560 PrivateVarsInfo privateVarsInfo(taskOp);
3561 TaskContextStructManager taskStructMgr{builder, moduleTranslation,
3562 privateVarsInfo.privatizers};
3573 InsertPointTy allocaIP =
3578 assert(builder.GetInsertPoint() == builder.GetInsertBlock()->end());
3579 llvm::BasicBlock *taskStartBlock = llvm::BasicBlock::Create(
3580 builder.getContext(),
"omp.task.start",
3581 builder.GetInsertBlock()->getParent());
3582 llvm::Instruction *branchToTaskStartBlock = builder.CreateBr(taskStartBlock);
3583 builder.SetInsertPoint(branchToTaskStartBlock);
3586 llvm::BasicBlock *copyBlock =
3587 splitBB(builder,
true,
"omp.private.copy");
3588 llvm::BasicBlock *initBlock =
3589 splitBB(builder,
true,
"omp.private.init");
3605 moduleTranslation, allocaIP.getNodeParent(), deallocBlocks);
3608 builder.SetInsertPoint(initBlock->getTerminator());
3611 taskStructMgr.generateTaskContextStruct();
3618 taskStructMgr.createGEPsToPrivateVars();
3620 for (
auto [privDecl, mlirPrivVar, blockArg, llvmPrivateVarAlloc] :
3621 llvm::zip_equal(privateVarsInfo.privatizers, privateVarsInfo.mlirVars,
3622 privateVarsInfo.blockArgs,
3623 taskStructMgr.getLLVMPrivateVarGEPs())) {
3625 if (!privDecl.readsFromMold())
3627 assert(llvmPrivateVarAlloc &&
3628 "reads from mold so shouldn't have been skipped");
3631 initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar,
3632 blockArg, llvmPrivateVarAlloc, initBlock);
3633 if (!privateVarOrErr)
3634 return handleError(privateVarOrErr, *taskOp.getOperation());
3643 [[maybe_unused]] llvm::Value *llvmPrivateVar = llvmPrivateVarAlloc;
3644 if ((privateVarOrErr.get() != llvmPrivateVarAlloc) &&
3645 !mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
3646 builder.CreateStore(privateVarOrErr.get(), llvmPrivateVarAlloc);
3648 llvmPrivateVar = builder.CreateLoad(privateVarOrErr.get()->getType(),
3649 llvmPrivateVarAlloc);
3651 assert(llvmPrivateVar->getType() ==
3652 moduleTranslation.
convertType(blockArg.getType()));
3662 taskOp, builder, moduleTranslation, privateVarsInfo.mlirVars,
3663 taskStructMgr.getLLVMPrivateVarGEPs(), privateVarsInfo.privatizers,
3664 taskOp.getPrivateNeedsBarrier())))
3665 return llvm::failure();
3667 llvm::OpenMPIRBuilder::AffinityData ad;
3669 return llvm::failure();
3679 taskOp.getOperation(), taskOp.getInReductionSyms(),
"omp.task",
3680 "in_reduction", inRedDecls)))
3683 inRedOrigPtrs.reserve(inRedDecls.size());
3684 for (
Value v : taskOp.getInReductionVars())
3685 inRedOrigPtrs.push_back(moduleTranslation.
lookupValue(v));
3688 builder.SetInsertPoint(taskStartBlock);
3691 [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
3696 moduleTranslation, allocaIP.getNodeParent(), deallocBlocks);
3699 builder.restoreIP(codegenIP);
3701 llvm::BasicBlock *privInitBlock =
nullptr;
3702 privateVarsInfo.llvmVars.resize(privateVarsInfo.blockArgs.size());
3703 for (
auto [i, zip] : llvm::enumerate(llvm::zip_equal(
3704 privateVarsInfo.blockArgs, privateVarsInfo.privatizers,
3705 privateVarsInfo.mlirVars))) {
3706 auto [blockArg, privDecl, mlirPrivVar] = zip;
3708 if (privDecl.readsFromMold())
3711 llvm::IRBuilderBase::InsertPointGuard guard(builder);
3712 llvm::Type *llvmAllocType =
3713 moduleTranslation.
convertType(privDecl.getType());
3714 builder.SetInsertPoint(allocaIP.getNodeParent()->getTerminator());
3715 llvm::Value *llvmPrivateVar = builder.CreateAlloca(
3716 llvmAllocType,
nullptr,
"omp.private.alloc");
3719 initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar,
3720 blockArg, llvmPrivateVar, privInitBlock);
3721 if (!privateVarOrError)
3722 return privateVarOrError.takeError();
3723 moduleTranslation.
mapValue(blockArg, privateVarOrError.get());
3724 privateVarsInfo.llvmVars[i] = privateVarOrError.get();
3727 taskStructMgr.createGEPsToPrivateVars();
3728 for (
auto [i, llvmPrivVar] :
3729 llvm::enumerate(taskStructMgr.getLLVMPrivateVarGEPs())) {
3731 assert(privateVarsInfo.llvmVars[i] &&
3732 "This is added in the loop above");
3735 privateVarsInfo.llvmVars[i] = llvmPrivVar;
3740 for (
auto [blockArg, llvmPrivateVar, privateDecl] :
3741 llvm::zip_equal(privateVarsInfo.blockArgs, privateVarsInfo.llvmVars,
3742 privateVarsInfo.privatizers)) {
3744 if (!privateDecl.readsFromMold())
3747 if (!mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
3748 llvmPrivateVar = builder.CreateLoad(
3749 moduleTranslation.
convertType(blockArg.getType()), llvmPrivateVar);
3751 assert(llvmPrivateVar->getType() ==
3752 moduleTranslation.
convertType(blockArg.getType()));
3753 moduleTranslation.
mapValue(blockArg, llvmPrivateVar);
3764 if (!inRedDecls.empty()) {
3765 auto iface = cast<omp::BlockArgOpenMPOpInterface>(taskOp.getOperation());
3768 llvm::LLVMContext &llvmCtx = m->getContext();
3769 llvm::OpenMPIRBuilder::LocationDescription bodyLoc(builder);
3770 uint32_t srcLocSize;
3771 llvm::Constant *srcLocStr =
3772 ompB.getOrCreateSrcLocStr(bodyLoc, srcLocSize);
3773 llvm::Value *bodyIdent = ompB.getOrCreateIdent(srcLocStr, srcLocSize);
3776 ompB.updateToLocation(bodyLoc);
3777 llvm::Value *bodyGtid = ompB.getOrCreateThreadID(bodyIdent);
3778 llvm::FunctionCallee getThData = ompB.getOrCreateRuntimeFunction(
3779 *m, llvm::omp::OMPRTL___kmpc_task_reduction_get_th_data);
3780 llvm::Type *ptrTy = llvm::PointerType::getUnqual(llvmCtx);
3781 llvm::Value *nullDesc = llvm::ConstantPointerNull::get(ptrTy);
3783 for (
auto [blockArg, origPtr] :
3784 llvm::zip_equal(inRedBlockArgs, inRedOrigPtrs)) {
3791 llvm::Value *lookupPtr = origPtr;
3792 if (
auto *origPtrTy =
3793 llvm::dyn_cast<llvm::PointerType>(lookupPtr->getType());
3794 origPtrTy && origPtrTy->getAddressSpace() != 0)
3795 lookupPtr = builder.CreateAddrSpaceCast(lookupPtr, ptrTy);
3796 llvm::Value *priv = builder.CreateCall(
3797 getThData, {bodyGtid, nullDesc, lookupPtr},
"omp.inred.priv");
3798 if (
auto *argPtrTy = llvm::dyn_cast<llvm::PointerType>(
3799 moduleTranslation.
convertType(blockArg.getType()));
3800 argPtrTy && argPtrTy->getAddressSpace() != 0)
3801 priv = builder.CreateAddrSpaceCast(priv, argPtrTy);
3802 moduleTranslation.
mapValue(blockArg, priv);
3807 taskOp.getRegion(),
"omp.task.region", builder, moduleTranslation);
3808 if (failed(
handleError(continuationBlockOrError, *taskOp)))
3809 return llvm::make_error<PreviouslyReportedError>();
3811 builder.SetInsertPoint(continuationBlockOrError.get()->getTerminator());
3814 taskOp.getLoc(), privateVarsInfo)))
3815 return llvm::make_error<PreviouslyReportedError>();
3818 taskStructMgr.freeStructPtr();
3820 return llvm::Error::success();
3829 llvm::omp::Directive::OMPD_taskgroup);
3831 llvm::OpenMPIRBuilder::DependenciesInfo dependencies;
3832 if (failed(
buildDependData(taskOp.getDependVars(), taskOp.getDependKinds(),
3833 taskOp.getDependIterated(),
3834 taskOp.getDependIteratedKinds(), builder,
3835 moduleTranslation, dependencies)))
3838 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
3839 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
3841 ->createTask(ompLoc, allocaIP, deallocBlocks, bodyCB,
3842 !taskOp.getUntied(),
3844 moduleTranslation.
lookupValue(taskOp.getIfExpr()),
3845 dependencies, ad, taskOp.getMergeable(),
3846 moduleTranslation.
lookupValue(taskOp.getEventHandle()),
3847 moduleTranslation.
lookupValue(taskOp.getPriority()),
3848 taskOp.getThreadset() == omp::ThreadsetPolicy::omp_pool);
3855 afterIP->getNodeParent());
3857 builder.restoreIP(*afterIP);
3859 if (dependencies.DepArray)
3860 builder.CreateFree(dependencies.DepArray);
3869 llvm::IRBuilderBase &builder,
3877 loopWrapperOp.getRegion(),
"omp.taskloop.wrapper.region", builder,
3880 if (failed(
handleError(continuationBlockOrError, opInst)))
3883 builder.SetInsertPoint(continuationBlockOrError.get());
3891static llvm::Expected<llvm::Value *>
3894 llvm::IRBuilderBase &builder) {
3895 if (llvm::Value *mapped = moduleTranslation.
lookupValue(value))
3900 return llvm::make_error<llvm::StringError>(
3901 "value is a block argument and is not mapped",
3902 llvm::inconvertibleErrorCode());
3904 return llvm::make_error<llvm::StringError>(
3905 "unsupported op defining taskloop loop bound",
3906 llvm::inconvertibleErrorCode());
3916 if (!operandOrError)
3917 return operandOrError.takeError();
3918 moduleTranslation.
mapValue(operand, *operandOrError);
3919 mappingsToRemove.push_back(operand);
3923 return llvm::make_error<llvm::StringError>(
3924 "failed to convert op defining taskloop loop bound",
3925 llvm::inconvertibleErrorCode());
3928 assert(
result &&
"expected conversion of loop bound op to produce a value");
3932 mappingsToRemove.push_back(resultValue);
3934 for (
Value mappedValue : mappingsToRemove)
3943 llvm::Value *&lbVal, llvm::Value *&ubVal,
3944 llvm::Value *&stepVal) {
3952 return firstLbOrErr.takeError();
3954 llvm::Type *boundType = (*firstLbOrErr)->getType();
3955 ubVal = builder.getIntN(boundType->getIntegerBitWidth(), 1);
3956 if (loopOp.getCollapseNumLoops() > 1) {
3974 for (uint64_t i = 0; i < loopOp.getCollapseNumLoops(); i++) {
3976 i == 0 ? std::move(firstLbOrErr)
3980 return lbOrErr.takeError();
3982 upperBounds[i], moduleTranslation, builder);
3984 return ubOrErr.takeError();
3988 return stepOrErr.takeError();
3990 llvm::Value *loopLb = *lbOrErr;
3991 llvm::Value *loopUb = *ubOrErr;
3992 llvm::Value *loopStep = *stepOrErr;
3998 llvm::Value *loopLbMinusOne = builder.CreateSub(
3999 loopLb, builder.getIntN(boundType->getIntegerBitWidth(), 1));
4000 llvm::Value *loopUbMinusOne = builder.CreateSub(
4001 loopUb, builder.getIntN(boundType->getIntegerBitWidth(), 1));
4002 llvm::Value *boundsCmp = builder.CreateICmpSLT(loopLb, loopUb);
4003 llvm::Value *ubMinusLb = builder.CreateSub(loopUb, loopLbMinusOne);
4004 llvm::Value *lbMinusUb = builder.CreateSub(loopLb, loopUbMinusOne);
4005 llvm::Value *loopTripCount =
4006 builder.CreateSelect(boundsCmp, ubMinusLb, lbMinusUb);
4007 loopTripCount = builder.CreateBinaryIntrinsic(
4008 llvm::Intrinsic::abs, loopTripCount, builder.getFalse());
4012 llvm::Value *loopTripCountDivStep =
4013 builder.CreateSDiv(loopTripCount, loopStep);
4014 loopTripCountDivStep = builder.CreateBinaryIntrinsic(
4015 llvm::Intrinsic::abs, loopTripCountDivStep, builder.getFalse());
4016 llvm::Value *loopTripCountRem =
4017 builder.CreateSRem(loopTripCount, loopStep);
4018 loopTripCountRem = builder.CreateBinaryIntrinsic(
4019 llvm::Intrinsic::abs, loopTripCountRem, builder.getFalse());
4020 llvm::Value *needsRoundUp = builder.CreateICmpNE(
4022 builder.getIntN(loopTripCountRem->getType()->getIntegerBitWidth(),
4025 builder.CreateAdd(loopTripCountDivStep,
4026 builder.CreateZExtOrTrunc(
4027 needsRoundUp, loopTripCountDivStep->getType()));
4028 ubVal = builder.CreateMul(ubVal, loopTripCount);
4030 lbVal = builder.getIntN(boundType->getIntegerBitWidth(), 1);
4031 stepVal = builder.getIntN(boundType->getIntegerBitWidth(), 1);
4036 return ubOrErr.takeError();
4040 return stepOrErr.takeError();
4041 lbVal = *firstLbOrErr;
4043 stepVal = *stepOrErr;
4046 assert(lbVal !=
nullptr &&
"Expected value for lbVal");
4047 assert(ubVal !=
nullptr &&
"Expected value for ubVal");
4048 assert(stepVal !=
nullptr &&
"Expected value for stepVal");
4049 return llvm::Error::success();
4055 llvm::IRBuilderBase &builder,
4057 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4059 omp::TaskloopWrapperOp loopWrapperOp = contextOp.getLoopOp();
4066 PrivateVarsInfo privateVarsInfo(contextOp);
4067 TaskContextStructManager taskStructMgr{builder, moduleTranslation,
4068 privateVarsInfo.privatizers};
4071 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
4074 assert(builder.GetInsertPoint() == builder.GetInsertBlock()->end());
4075 llvm::BasicBlock *taskloopStartBlock = llvm::BasicBlock::Create(
4076 builder.getContext(),
"omp.taskloop.wrapper.start",
4077 builder.GetInsertBlock()->getParent());
4078 llvm::Instruction *branchToTaskloopStartBlock =
4079 builder.CreateBr(taskloopStartBlock);
4080 builder.SetInsertPoint(branchToTaskloopStartBlock);
4082 llvm::BasicBlock *copyBlock =
4083 splitBB(builder,
true,
"omp.private.copy");
4084 llvm::BasicBlock *initBlock =
4085 splitBB(builder,
true,
"omp.private.init");
4088 moduleTranslation, allocaIP.getNodeParent(), deallocBlocks);
4091 builder.SetInsertPoint(initBlock->getTerminator());
4094 taskStructMgr.generateTaskContextStruct();
4095 taskStructMgr.createGEPsToPrivateVars();
4097 llvmFirstPrivateVars.resize(privateVarsInfo.blockArgs.size());
4099 for (
auto [i, zip] : llvm::enumerate(llvm::zip_equal(
4100 privateVarsInfo.privatizers, privateVarsInfo.mlirVars,
4101 privateVarsInfo.blockArgs, taskStructMgr.getLLVMPrivateVarGEPs()))) {
4102 auto [privDecl, mlirPrivVar, blockArg, llvmPrivateVarAlloc] = zip;
4104 if (!privDecl.readsFromMold())
4106 assert(llvmPrivateVarAlloc &&
4107 "reads from mold so shouldn't have been skipped");
4110 initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar,
4111 blockArg, llvmPrivateVarAlloc, initBlock);
4112 if (!privateVarOrErr)
4113 return handleError(privateVarOrErr, *contextOp.getOperation());
4115 llvmFirstPrivateVars[i] = privateVarOrErr.get();
4117 llvm::IRBuilderBase::InsertPointGuard guard(builder);
4118 builder.SetInsertPoint(builder.GetInsertBlock()->getTerminator());
4120 [[maybe_unused]] llvm::Value *llvmPrivateVar = llvmPrivateVarAlloc;
4121 if ((privateVarOrErr.get() != llvmPrivateVarAlloc) &&
4122 !mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
4123 builder.CreateStore(privateVarOrErr.get(), llvmPrivateVarAlloc);
4125 llvmPrivateVar = builder.CreateLoad(privateVarOrErr.get()->getType(),
4126 llvmPrivateVarAlloc);
4128 assert(llvmPrivateVar->getType() ==
4129 moduleTranslation.
convertType(blockArg.getType()));
4135 contextOp, builder, moduleTranslation, privateVarsInfo.mlirVars,
4136 taskStructMgr.getLLVMPrivateVarGEPs(), privateVarsInfo.privatizers,
4137 contextOp.getPrivateNeedsBarrier())))
4138 return llvm::failure();
4148 contextOp.getOperation(), contextOp.getReductionSyms(),
4149 "omp.taskloop.context",
"reduction", redDecls)))
4153 contextOp.getOperation(), contextOp.getInReductionSyms(),
4154 "omp.taskloop.context",
"in_reduction", inRedDecls)))
4160 redOrigPtrs.reserve(redDecls.size());
4161 for (
Value v : contextOp.getReductionVars())
4162 redOrigPtrs.push_back(moduleTranslation.
lookupValue(v));
4164 inRedOrigPtrs.reserve(inRedDecls.size());
4165 for (
Value v : contextOp.getInReductionVars())
4166 inRedOrigPtrs.push_back(moduleTranslation.
lookupValue(v));
4170 builder.SetInsertPoint(taskloopStartBlock);
4172 llvm::OpenMPIRBuilder &ompBuilderRef = *
getOpenMPBuilder(moduleTranslation);
4179 bool implicitTaskgroup = !redDecls.empty();
4180 llvm::Value *redDesc =
nullptr;
4181 if (implicitTaskgroup) {
4182 llvm::OpenMPIRBuilder::LocationDescription redLoc(builder);
4183 uint32_t srcLocSize;
4184 llvm::Constant *srcLocStr =
4185 ompBuilderRef.getOrCreateSrcLocStr(redLoc, srcLocSize);
4186 llvm::Value *ident = ompBuilderRef.getOrCreateIdent(srcLocStr, srcLocSize);
4189 ompBuilderRef.updateToLocation(redLoc);
4190 llvm::Value *outerGtid = ompBuilderRef.getOrCreateThreadID(ident);
4191 llvm::FunctionCallee taskgroupFn = ompBuilderRef.getOrCreateRuntimeFunction(
4192 *module, llvm::omp::OMPRTL___kmpc_taskgroup);
4193 builder.CreateCall(taskgroupFn, {ident, outerGtid});
4196 "__omp_taskloop_taskred_", builder,
4197 allocaIP, moduleTranslation);
4202 auto loopOp = cast<omp::LoopNestOp>(loopWrapperOp.getWrappedLoop());
4203 llvm::Value *lbVal =
nullptr;
4204 llvm::Value *ubVal =
nullptr;
4205 llvm::Value *stepVal =
nullptr;
4207 loopOp, builder, moduleTranslation, lbVal, ubVal, stepVal))
4211 [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
4216 moduleTranslation, allocaIP.getNodeParent(), deallocBlocks);
4219 builder.restoreIP(codegenIP);
4221 llvm::BasicBlock *privInitBlock =
nullptr;
4222 privateVarsInfo.llvmVars.resize(privateVarsInfo.blockArgs.size());
4223 for (
auto [i, zip] : llvm::enumerate(llvm::zip_equal(
4224 privateVarsInfo.blockArgs, privateVarsInfo.privatizers,
4225 privateVarsInfo.mlirVars))) {
4226 auto [blockArg, privDecl, mlirPrivVar] = zip;
4228 if (privDecl.readsFromMold())
4231 llvm::IRBuilderBase::InsertPointGuard guard(builder);
4232 llvm::Type *llvmAllocType =
4233 moduleTranslation.
convertType(privDecl.getType());
4234 builder.SetInsertPoint(allocaIP.getNodeParent()->getTerminator());
4235 llvm::Value *llvmPrivateVar = builder.CreateAlloca(
4236 llvmAllocType,
nullptr,
"omp.private.alloc");
4239 initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar,
4240 blockArg, llvmPrivateVar, privInitBlock);
4241 if (!privateVarOrError)
4242 return privateVarOrError.takeError();
4243 moduleTranslation.
mapValue(blockArg, privateVarOrError.get());
4244 privateVarsInfo.llvmVars[i] = privateVarOrError.get();
4247 taskStructMgr.createGEPsToPrivateVars();
4248 for (
auto [i, llvmPrivVar] :
4249 llvm::enumerate(taskStructMgr.getLLVMPrivateVarGEPs())) {
4251 assert(privateVarsInfo.llvmVars[i] &&
4252 "This is added in the loop above");
4255 privateVarsInfo.llvmVars[i] = llvmPrivVar;
4260 for (
auto [blockArg, llvmPrivateVar, privateDecl] :
4261 llvm::zip_equal(privateVarsInfo.blockArgs, privateVarsInfo.llvmVars,
4262 privateVarsInfo.privatizers)) {
4264 if (!privateDecl.readsFromMold())
4267 if (!mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
4268 llvmPrivateVar = builder.CreateLoad(
4269 moduleTranslation.
convertType(blockArg.getType()), llvmPrivateVar);
4271 assert(llvmPrivateVar->getType() ==
4272 moduleTranslation.
convertType(blockArg.getType()));
4273 moduleTranslation.
mapValue(blockArg, llvmPrivateVar);
4285 if (!redDecls.empty() || !inRedDecls.empty()) {
4287 cast<omp::BlockArgOpenMPOpInterface>(contextOp.getOperation());
4290 llvm::LLVMContext &llvmCtx = m->getContext();
4291 llvm::OpenMPIRBuilder::LocationDescription bodyLoc(builder);
4292 uint32_t srcLocSize;
4293 llvm::Constant *srcLocStr =
4294 ompB.getOrCreateSrcLocStr(bodyLoc, srcLocSize);
4295 llvm::Value *bodyIdent = ompB.getOrCreateIdent(srcLocStr, srcLocSize);
4298 ompB.updateToLocation(bodyLoc);
4299 llvm::Value *bodyGtid = ompB.getOrCreateThreadID(bodyIdent);
4300 llvm::FunctionCallee getThData = ompB.getOrCreateRuntimeFunction(
4301 *m, llvm::omp::OMPRTL___kmpc_task_reduction_get_th_data);
4302 llvm::Type *ptrTy = llvm::PointerType::getUnqual(llvmCtx);
4312 auto remapReductionArg = [&](
BlockArgument blockArg, llvm::Value *desc,
4313 llvm::Value *origPtr,
4314 const llvm::Twine &name) {
4315 if (
auto *origPtrTy =
4316 llvm::dyn_cast<llvm::PointerType>(origPtr->getType());
4317 origPtrTy && origPtrTy->getAddressSpace() != 0)
4318 origPtr = builder.CreateAddrSpaceCast(origPtr, ptrTy);
4320 builder.CreateCall(getThData, {bodyGtid, desc, origPtr}, name);
4321 if (
auto *argPtrTy = llvm::dyn_cast<llvm::PointerType>(
4323 argPtrTy && argPtrTy->getAddressSpace() != 0)
4324 priv = builder.CreateAddrSpaceCast(priv, argPtrTy);
4325 moduleTranslation.
mapValue(blockArg, priv);
4329 for (
auto [blockArg, origPtr] :
4330 llvm::zip_equal(redBlockArgs, redOrigPtrs))
4331 remapReductionArg(blockArg, redDesc, origPtr,
"omp.taskred.priv");
4333 llvm::Value *nullDesc = llvm::ConstantPointerNull::get(ptrTy);
4334 for (
auto [blockArg, origPtr] :
4335 llvm::zip_equal(inRedBlockArgs, inRedOrigPtrs))
4336 remapReductionArg(blockArg, nullDesc, origPtr,
"omp.inred.priv");
4342 contextOp.getRegion(),
"omp.taskloop.context.region", builder,
4345 if (failed(
handleError(continuationBlockOrError, opInst)))
4346 return llvm::make_error<PreviouslyReportedError>();
4348 builder.SetInsertPoint(continuationBlockOrError.get()->getTerminator());
4356 contextOp.getLoc(), privateVarsInfo)))
4357 return llvm::make_error<PreviouslyReportedError>();
4360 taskStructMgr.freeStructPtr();
4362 return llvm::Error::success();
4368 auto taskDupCB = [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
4369 llvm::Value *destPtr, llvm::Value *srcPtr)
4371 llvm::IRBuilderBase::InsertPointGuard guard(builder);
4372 builder.restoreIP(codegenIP);
4375 builder.getPtrTy(srcPtr->getType()->getPointerAddressSpace());
4377 builder.CreateLoad(ptrTy, srcPtr,
"omp.taskloop.context.src");
4379 TaskContextStructManager &srcStructMgr = taskStructMgr;
4380 TaskContextStructManager destStructMgr(builder, moduleTranslation,
4381 privateVarsInfo.privatizers);
4382 destStructMgr.generateTaskContextStruct();
4383 llvm::Value *dest = destStructMgr.getStructPtr();
4384 dest->setName(
"omp.taskloop.context.dest");
4385 builder.CreateStore(dest, destPtr);
4388 srcStructMgr.createGEPsToPrivateVars(src);
4390 destStructMgr.createGEPsToPrivateVars(dest);
4393 for (
auto [privDecl, mold, blockArg, llvmPrivateVarAlloc] :
4394 llvm::zip_equal(privateVarsInfo.privatizers, srcGEPs,
4395 privateVarsInfo.blockArgs, destGEPs)) {
4397 if (!privDecl.readsFromMold())
4399 assert(llvmPrivateVarAlloc &&
4400 "reads from mold so shouldn't have been skipped");
4403 builder, moduleTranslation, privDecl.getInitMoldArg(), mold);
4405 builder, moduleTranslation, privDecl, moldArg, blockArg,
4406 llvmPrivateVarAlloc, builder.GetInsertBlock());
4407 if (!privateVarOrErr)
4408 return privateVarOrErr.takeError();
4417 [[maybe_unused]] llvm::Value *llvmPrivateVar = llvmPrivateVarAlloc;
4418 if ((privateVarOrErr.get() != llvmPrivateVarAlloc) &&
4419 !mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
4420 builder.CreateStore(privateVarOrErr.get(), llvmPrivateVarAlloc);
4422 llvmPrivateVar = builder.CreateLoad(privateVarOrErr.get()->getType(),
4423 llvmPrivateVarAlloc);
4425 assert(llvmPrivateVar->getType() ==
4426 moduleTranslation.
convertType(blockArg.getType()));
4434 moduleTranslation, srcGEPs, destGEPs,
4435 privateVarsInfo.privatizers,
4436 contextOp.getPrivateNeedsBarrier())))
4437 return llvm::make_error<PreviouslyReportedError>();
4439 return builder.saveIP();
4447 llvm::Value *ifCond =
nullptr;
4448 llvm::Value *grainsize =
nullptr;
4450 mlir::Value grainsizeVal = contextOp.getGrainsize();
4451 mlir::Value numTasksVal = contextOp.getNumTasks();
4452 if (
Value ifVar = contextOp.getIfExpr())
4455 grainsize = moduleTranslation.
lookupValue(grainsizeVal);
4457 }
else if (numTasksVal) {
4458 grainsize = moduleTranslation.
lookupValue(numTasksVal);
4462 llvm::OpenMPIRBuilder::TaskDupCallbackTy taskDupOrNull =
nullptr;
4463 if (taskStructMgr.getStructPtr())
4464 taskDupOrNull = taskDupCB;
4474 llvm::omp::Directive::OMPD_taskgroup);
4476 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4477 bool effectiveNoGroup = contextOp.getNogroup() || implicitTaskgroup;
4478 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
4481 ompLoc, allocaIP, deallocBlocks, bodyCB, loopInfo, lbVal, ubVal,
4482 stepVal, contextOp.getUntied(), ifCond, grainsize,
4483 effectiveNoGroup, sched,
4484 moduleTranslation.
lookupValue(contextOp.getFinal()),
4485 contextOp.getMergeable(),
4486 moduleTranslation.
lookupValue(contextOp.getPriority()),
4487 loopOp.getCollapseNumLoops(), taskDupOrNull,
4488 taskStructMgr.getStructPtr(),
4489 contextOp.getThreadset() == omp::ThreadsetPolicy::omp_pool);
4495 afterIP->getNodeParent());
4497 builder.restoreIP(*afterIP);
4501 if (implicitTaskgroup) {
4502 llvm::OpenMPIRBuilder::LocationDescription endLoc(builder);
4503 uint32_t srcLocSize;
4504 llvm::Constant *srcLocStr =
4505 ompBuilder.getOrCreateSrcLocStr(endLoc, srcLocSize);
4506 llvm::Value *ident = ompBuilder.getOrCreateIdent(srcLocStr, srcLocSize);
4509 ompBuilder.updateToLocation(endLoc);
4510 llvm::Value *outerGtid = ompBuilder.getOrCreateThreadID(ident);
4511 llvm::FunctionCallee endTgFn = ompBuilder.getOrCreateRuntimeFunction(
4513 llvm::omp::OMPRTL___kmpc_end_taskgroup);
4514 builder.CreateCall(endTgFn, {ident, outerGtid});
4525static llvm::Function *
4528 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
4529 llvm::LLVMContext &ctx = llvmModule->getContext();
4530 llvm::Type *voidTy = llvm::Type::getVoidTy(ctx);
4531 llvm::Type *ptrTy = llvm::PointerType::getUnqual(ctx);
4532 llvm::FunctionType *fty =
4533 llvm::FunctionType::get(voidTy, {ptrTy, ptrTy},
false);
4534 llvm::Function *fn =
4535 llvm::Function::Create(fty, llvm::GlobalValue::InternalLinkage,
4536 baseName +
".red.init", llvmModule);
4537 fn->setDoesNotRecurse();
4538 fn->getArg(0)->setName(
"priv");
4539 fn->getArg(1)->setName(
"orig");
4541 llvm::BasicBlock *entry = llvm::BasicBlock::Create(ctx,
"entry", fn);
4542 llvm::IRBuilder<>
b(entry);
4549 Value moldArg = decl.getInitializerMoldArg();
4550 llvm::Value *origVal = fn->getArg(1);
4551 if (!isa<LLVM::LLVMPointerType>(moldArg.
getType()))
4553 fn->getArg(1),
"omp.orig");
4554 moduleTranslation.
mapValue(moldArg, origVal);
4557 "omp.taskred.init",
b, moduleTranslation,
4559 fn->eraseFromParent();
4562 assert(phis.size() == 1 &&
4563 "expected one value yielded from reduction initializer");
4564 b.CreateStore(phis[0], fn->getArg(0));
4567 moduleTranslation.
forgetMapping(decl.getInitializerRegion());
4575static llvm::Function *
4578 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
4579 llvm::LLVMContext &ctx = llvmModule->getContext();
4580 llvm::Type *voidTy = llvm::Type::getVoidTy(ctx);
4581 llvm::Type *ptrTy = llvm::PointerType::getUnqual(ctx);
4582 llvm::FunctionType *fty =
4583 llvm::FunctionType::get(voidTy, {ptrTy, ptrTy},
false);
4584 llvm::Function *fn =
4585 llvm::Function::Create(fty, llvm::GlobalValue::InternalLinkage,
4586 baseName +
".red.comb", llvmModule);
4587 fn->setDoesNotRecurse();
4588 fn->getArg(0)->setName(
"lhs");
4589 fn->getArg(1)->setName(
"rhs");
4591 llvm::BasicBlock *entry = llvm::BasicBlock::Create(ctx,
"entry", fn);
4592 llvm::IRBuilder<>
b(entry);
4594 llvm::Type *elemTy = moduleTranslation.
convertType(decl.getType());
4595 Block &combBlock = decl.getReductionRegion().
front();
4597 "expected two arguments in declare_reduction combiner");
4598 llvm::Value *lhsVal =
b.CreateLoad(elemTy, fn->getArg(0),
"omp.lhs");
4599 llvm::Value *rhsVal =
b.CreateLoad(elemTy, fn->getArg(1),
"omp.rhs");
4605 "omp.taskred.comb",
b, moduleTranslation,
4607 fn->eraseFromParent();
4610 assert(phis.size() == 1 &&
4611 "expected one value yielded from reduction combiner");
4612 b.CreateStore(phis[0], fn->getArg(0));
4638 llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder::InsertPointTy allocaIP,
4640 bool isWorksharing) {
4641 assert(redDecls.size() == origPtrs.size() &&
4642 "expected one orig pointer per reduction decl");
4644 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
4645 llvm::LLVMContext &ctx = llvmModule->getContext();
4646 const llvm::DataLayout &dl = llvmModule->getDataLayout();
4648 llvm::Type *ptrTy = llvm::PointerType::getUnqual(ctx);
4649 llvm::Type *i32Ty = llvm::Type::getInt32Ty(ctx);
4650 llvm::Type *sizeTy =
4651 llvm::Type::getIntNTy(ctx, dl.getPointerSizeInBits(0));
4655 llvm::StructType *redInputTy =
4656 llvm::StructType::getTypeByName(ctx,
"kmp_taskred_input_t");
4658 redInputTy = llvm::StructType::create(
4659 ctx, {ptrTy, ptrTy, sizeTy, ptrTy, ptrTy, ptrTy, i32Ty},
4660 "kmp_taskred_input_t");
4662 unsigned n = redDecls.size();
4663 llvm::ArrayType *arrTy = llvm::ArrayType::get(redInputTy, n);
4666 llvm::AllocaInst *arrAlloca;
4668 llvm::IRBuilderBase::InsertPointGuard guard(builder);
4669 builder.restoreIP(allocaIP);
4671 builder.CreateAlloca(arrTy,
nullptr,
".taskred.input");
4675 llvm::Value *zero = builder.getInt32(0);
4676 for (
unsigned i = 0; i < n; ++i) {
4677 omp::DeclareReductionOp decl = redDecls[i];
4678 llvm::Value *orig = origPtrs[i];
4679 if (
auto *origPtrTy = llvm::dyn_cast<llvm::PointerType>(orig->getType());
4680 origPtrTy && origPtrTy->getAddressSpace() != 0)
4681 orig = builder.CreateAddrSpaceCast(orig, ptrTy);
4682 llvm::Type *elemTy = moduleTranslation.
convertType(decl.getType());
4683 uint64_t size = dl.getTypeAllocSize(elemTy).getFixedValue();
4685 std::string baseName =
4686 (llvm::Twine(helperNamePrefix) + decl.getSymName()).str();
4687 llvm::Function *initFn =
4689 llvm::Function *combFn =
4691 if (!initFn || !combFn)
4693 llvm::Value *elemPtr = builder.CreateInBoundsGEP(
4694 arrTy, arrAlloca, {zero, builder.getInt32(i)},
".taskred.elem");
4695 auto storeField = [&](
unsigned fieldIdx, llvm::Value *val) {
4696 llvm::Value *fieldPtr =
4697 builder.CreateStructGEP(redInputTy, elemPtr, fieldIdx);
4698 builder.CreateStore(val, fieldPtr);
4700 storeField(0, orig);
4701 storeField(1, orig);
4702 storeField(2, llvm::ConstantInt::get(sizeTy, size));
4703 storeField(3, initFn);
4704 storeField(4, llvm::ConstantPointerNull::get(ptrTy));
4705 storeField(5, combFn);
4706 storeField(6, llvm::ConstantInt::get(i32Ty, 0));
4710 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4711 uint32_t srcLocSize;
4712 llvm::Constant *srcLocStr =
4713 ompBuilder->getOrCreateSrcLocStr(ompLoc, srcLocSize);
4714 llvm::Value *ident = ompBuilder->getOrCreateIdent(srcLocStr, srcLocSize);
4715 ompBuilder->updateToLocation(ompLoc);
4716 llvm::Value *gtid = ompBuilder->getOrCreateThreadID(ident);
4720 llvm::FunctionCallee modInit = ompBuilder->getOrCreateRuntimeFunction(
4721 *llvmModule, llvm::omp::OMPRTL___kmpc_taskred_modifier_init);
4722 return builder.CreateCall(modInit,
4724 builder.getInt32(isWorksharing ? 1 : 0),
4725 builder.getInt32(n), arrAlloca},
4729 llvm::FunctionCallee taskredInit = ompBuilder->getOrCreateRuntimeFunction(
4730 *llvmModule, llvm::omp::OMPRTL___kmpc_taskred_init);
4731 return builder.CreateCall(taskredInit, {gtid, builder.getInt32(n), arrAlloca},
4742 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
4743 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4744 uint32_t srcLocSize;
4745 llvm::Constant *srcLocStr =
4746 ompBuilder->getOrCreateSrcLocStr(ompLoc, srcLocSize);
4747 llvm::Value *ident = ompBuilder->getOrCreateIdent(srcLocStr, srcLocSize);
4748 ompBuilder->updateToLocation(ompLoc);
4749 llvm::Value *gtid = ompBuilder->getOrCreateThreadID(ident);
4750 llvm::FunctionCallee fini = ompBuilder->getOrCreateRuntimeFunction(
4751 *llvmModule, llvm::omp::OMPRTL___kmpc_task_reduction_modifier_fini);
4752 builder.CreateCall(fini,
4753 {ident, gtid, builder.getInt32(isWorksharing ? 1 : 0)});
4760 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4769 if (
auto syms = tgOp.getTaskReductionSyms()) {
4770 redDecls.reserve(syms->size());
4771 for (
auto sym : syms->getAsRange<SymbolRefAttr>()) {
4775 return tgOp.emitError()
4776 <<
"failed to resolve task_reduction declare_reduction symbol "
4777 << sym.getRootReference() <<
" in omp.taskgroup";
4778 if (decl.getInitializerRegion().front().getNumArguments() != 1)
4779 return tgOp.emitError(
"not yet implemented: task_reduction with "
4780 "two-argument initializer in omp.taskgroup");
4781 if (!decl.getCleanupRegion().empty())
4782 return tgOp.emitError(
"not yet implemented: task_reduction with "
4783 "cleanup region in omp.taskgroup");
4784 if (decl.getReductionRegion().empty())
4785 return tgOp.emitError(
"task_reduction declare_reduction is missing a "
4787 redDecls.push_back(decl);
4792 [&](InsertPointTy allocaIP, InsertPointTy codegenIP,
4794 builder.restoreIP(codegenIP);
4796 if (!redDecls.empty()) {
4798 origPtrs.reserve(redDecls.size());
4799 for (
Value v : tgOp.getTaskReductionVars())
4800 origPtrs.push_back(moduleTranslation.
lookupValue(v));
4802 builder, allocaIP, moduleTranslation))
4803 return llvm::createStringError(
4804 llvm::inconvertibleErrorCode(),
4805 "failed to emit task_reduction initialization for omp.taskgroup");
4813 for (
auto [i, blockArg] :
4814 llvm::enumerate(tgOp.getRegion().getArguments())) {
4816 moduleTranslation.
lookupValue(tgOp.getTaskReductionVars()[i]);
4817 moduleTranslation.
mapValue(blockArg, orig);
4821 builder, moduleTranslation)
4826 InsertPointTy allocaIP =
4828 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4829 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
4831 ->createTaskgroup(ompLoc, allocaIP, deallocBlocks, bodyCB);
4836 builder.restoreIP(*afterIP);
4843 if (!initOp.getDependVars().empty() || initOp.getDependKinds() ||
4844 !initOp.getDependIterated().empty() || initOp.getDependIteratedKinds())
4845 return initOp.emitError()
4846 <<
"not yet implemented: Unhandled clause depend in "
4847 << omp::InteropInitOp::getOperationName() <<
" operation";
4850 llvm::Value *interopVar =
4851 moduleTranslation.
lookupValue(initOp.getInteropVar());
4852 llvm::Value *device = initOp.getDevice()
4853 ? moduleTranslation.
lookupValue(initOp.getDevice())
4857 llvm::Value *numDeps = llvm::ConstantInt::get(builder.getInt32Ty(), 0);
4858 llvm::Value *depArray = llvm::ConstantPointerNull::get(builder.getPtrTy());
4859 bool hasNowait = initOp.getNowait();
4866 bool hasTarget =
false, hasTargetSync =
false;
4868 switch (cast<omp::InteropTypeAttr>(typeAttr).getValue()) {
4869 case omp::InteropType::target:
4872 case omp::InteropType::targetsync:
4873 hasTargetSync =
true;
4877 llvm::omp::OMPInteropType interopType =
4878 (!hasTarget && hasTargetSync) ? llvm::omp::OMPInteropType::TargetSync
4879 : llvm::omp::OMPInteropType::Target;
4880 ompBuilder->createOMPInteropInit(builder, interopVar, interopType, device,
4881 numDeps, depArray, hasNowait);
4887 llvm::IRBuilderBase &builder,
4889 if (!destroyOp.getDependVars().empty() || destroyOp.getDependKinds() ||
4890 !destroyOp.getDependIterated().empty() ||
4891 destroyOp.getDependIteratedKinds())
4892 return destroyOp.emitError()
4893 <<
"not yet implemented: Unhandled clause depend in "
4894 << omp::InteropDestroyOp::getOperationName() <<
" operation";
4897 llvm::Value *interopVar =
4898 moduleTranslation.
lookupValue(destroyOp.getInteropVar());
4899 llvm::Value *device =
4900 destroyOp.getDevice()
4901 ? moduleTranslation.
lookupValue(destroyOp.getDevice())
4904 llvm::Value *numDeps = llvm::ConstantInt::get(builder.getInt32Ty(), 0);
4905 llvm::Value *depArray = llvm::ConstantPointerNull::get(builder.getPtrTy());
4906 bool hasNowait = destroyOp.getNowait();
4908 ompBuilder->createOMPInteropDestroy(builder, interopVar, device, numDeps,
4909 depArray, hasNowait);
4916 if (!useOp.getDependVars().empty() || useOp.getDependKinds() ||
4917 !useOp.getDependIterated().empty() || useOp.getDependIteratedKinds())
4918 return useOp.emitError()
4919 <<
"not yet implemented: Unhandled clause depend in "
4920 << omp::InteropUseOp::getOperationName() <<
" operation";
4923 llvm::Value *interopVar =
4924 moduleTranslation.
lookupValue(useOp.getInteropVar());
4925 llvm::Value *device = useOp.getDevice()
4926 ? moduleTranslation.
lookupValue(useOp.getDevice())
4929 llvm::Value *numDeps = llvm::ConstantInt::get(builder.getInt32Ty(), 0);
4930 llvm::Value *depArray = llvm::ConstantPointerNull::get(builder.getPtrTy());
4931 bool hasNowait = useOp.getNowait();
4933 ompBuilder->createOMPInteropUse(builder, interopVar, device, numDeps,
4934 depArray, hasNowait);
4944 llvm::OpenMPIRBuilder::DependenciesInfo dds;
4946 twOp.getDependVars(), twOp.getDependKinds(), twOp.getDependIterated(),
4947 twOp.getDependIteratedKinds(), builder, moduleTranslation, dds))) {
4952 ->createTaskwait(builder, dds, twOp.getNowait());
4954 builder.CreateFree(dds.DepArray);
4965 auto wsloopOp = cast<omp::WsloopOp>(opInst);
4969 auto loopOp = cast<omp::LoopNestOp>(wsloopOp.getWrappedLoop());
4971 assert(isByRef.size() == wsloopOp.getNumReductionVars());
4975 wsloopOp.getScheduleKind().value_or(omp::ClauseScheduleKind::Static);
4978 llvm::Value *step = moduleTranslation.
lookupValue(loopOp.getLoopSteps()[0]);
4979 llvm::Type *ivType = step->getType();
4980 llvm::Value *chunk =
nullptr;
4981 if (wsloopOp.getScheduleChunk()) {
4982 llvm::Value *chunkVar =
4983 moduleTranslation.
lookupValue(wsloopOp.getScheduleChunk());
4984 chunk = builder.CreateSExtOrTrunc(chunkVar, ivType);
4987 omp::DistributeOp distributeOp =
nullptr;
4988 llvm::Value *distScheduleChunk =
nullptr;
4989 bool hasDistSchedule =
false;
4990 if (llvm::isa_and_present<omp::DistributeOp>(opInst.
getParentOp())) {
4991 distributeOp = cast<omp::DistributeOp>(opInst.
getParentOp());
4992 hasDistSchedule = distributeOp.getDistScheduleStatic();
4993 if (distributeOp.getDistScheduleChunkSize()) {
4994 llvm::Value *chunkVar = moduleTranslation.
lookupValue(
4995 distributeOp.getDistScheduleChunkSize());
4996 distScheduleChunk = builder.CreateSExtOrTrunc(chunkVar, ivType);
5000 PrivateVarsInfo privateVarsInfo(wsloopOp);
5001 privateVarsInfo.addLinearVars(wsloopOp);
5006 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
5009 llvm::BasicBlock *allocaBlock = allocaIP.getNodeParent();
5011 wsloopOp.getNumReductionVars());
5014 wsloopOp, builder, moduleTranslation, privateVarsInfo, allocaIP);
5021 cast<omp::BlockArgOpenMPOpInterface>(opInst).getReductionBlockArgs();
5026 moduleTranslation, allocaIP, reductionDecls,
5027 privateReductionVariables, reductionVariableMap,
5028 deferredStores, isByRef)))
5037 wsloopOp, builder, moduleTranslation, privateVarsInfo.mlirVars,
5038 privateVarsInfo.llvmVars, privateVarsInfo.privatizers,
5039 wsloopOp.getPrivateNeedsBarrier())))
5042 assert(afterAllocas.get()->getSinglePredecessor());
5043 if (failed(initReductionVars(wsloopOp, reductionArgs, builder,
5045 afterAllocas.get()->getSinglePredecessor(),
5046 reductionDecls, privateReductionVariables,
5047 reductionVariableMap, isByRef, deferredStores)))
5053 bool isTaskReductionMod =
5054 wsloopOp.hasReductionModifier(omp::ReductionModifier::task);
5055 if (isTaskReductionMod &&
5057 wsloopOp, reductionDecls, privateReductionVariables, builder,
5058 allocaIP, moduleTranslation,
true))
5059 return wsloopOp.emitError(
5060 "failed to emit task reduction modifier initialization");
5063 bool isOrdered = wsloopOp.getOrdered().has_value();
5064 std::optional<omp::ScheduleModifier> scheduleMod = wsloopOp.getScheduleMod();
5065 bool isSimd = wsloopOp.getScheduleSimd();
5066 bool loopNeedsBarrier = !wsloopOp.getNowait();
5071 llvm::omp::WorksharingLoopType workshareLoopType =
5072 llvm::isa_and_present<omp::DistributeOp>(opInst.
getParentOp())
5073 ? llvm::omp::WorksharingLoopType::DistributeForStaticLoop
5074 : llvm::omp::WorksharingLoopType::ForStaticLoop;
5078 llvm::omp::Directive::OMPD_for);
5080 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5083 LinearClauseProcessor linearClauseProcessor;
5085 if (!wsloopOp.getLinearVars().empty()) {
5086 auto linearVarTypes = wsloopOp.getLinearVarTypes().value();
5088 linearClauseProcessor.registerType(moduleTranslation, linearVarType);
5090 for (
auto [idx, linearVar] : llvm::enumerate(wsloopOp.getLinearVars())) {
5091 size_t privIdx = privateVarsInfo.numPrivateVars + idx;
5092 linearClauseProcessor.createLinearVar(
5093 builder, allocaIP, privateVarsInfo.privatizers[privIdx],
5095 privateVarsInfo.llvmVars[privIdx], idx);
5097 for (
mlir::Value linearStep : wsloopOp.getLinearStepVars())
5098 linearClauseProcessor.initLinearStep(moduleTranslation, linearStep);
5102 wsloopOp.getRegion(),
"omp.wsloop.region", builder, moduleTranslation);
5110 if (!wsloopOp.getLinearVars().empty()) {
5112 linearClauseProcessor.initLinearVar(builder, moduleTranslation,
5113 loopInfo->getPreheader()),
5116 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterBarrierIP =
5118 ->createBarrier(builder, llvm::omp::OMPD_barrier);
5121 builder.restoreIP(*afterBarrierIP);
5122 if (failed(
handleError(linearClauseProcessor.updateLinearVar(
5123 builder, moduleTranslation, loopInfo->getBody(),
5124 loopInfo->getIndVar()),
5127 linearClauseProcessor.splitLinearFiniBB(builder, loopInfo->getExit());
5130 builder.SetInsertPoint((*regionBlock)->begin());
5133 bool noLoopMode =
false;
5134 omp::TargetOp targetOp = wsloopOp->getParentOfType<mlir::omp::TargetOp>();
5136 targetOp.getKernelType() == omp::TargetExecMode::spmd_no_loop) {
5138 cast<omp::ComposableOpInterface>(*targetOp).findCapturedOp();
5142 if (loopOp == targetCapturedOp)
5147 allocaIP = allocaBlock->getFirstInsertionPt();
5148 llvm::OpenMPIRBuilder::InsertPointOrErrorTy wsloopIP =
5149 ompBuilder->applyWorkshareLoop(
5150 ompLoc.DL, loopInfo, allocaIP, loopNeedsBarrier,
5151 convertToScheduleKind(schedule), chunk, isSimd,
5152 scheduleMod == omp::ScheduleModifier::monotonic,
5153 scheduleMod == omp::ScheduleModifier::nonmonotonic, isOrdered,
5154 workshareLoopType, noLoopMode, hasDistSchedule, distScheduleChunk,
5155 !wsloopOp.getLinearVars().empty());
5162 llvm::BasicBlock *wsloopContinuationBB = wsloopIP->getNodeParent();
5165 if (!wsloopOp.getLinearVars().empty()) {
5166 llvm::OpenMPIRBuilder::InsertPointTy oldIP = builder.saveIP();
5167 assert(loopInfo->getLastIter() &&
5168 "`lastiter` in CanonicalLoopInfo is nullptr");
5169 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterBarrierIP =
5170 linearClauseProcessor.finalizeLinearVar(builder, moduleTranslation,
5171 loopInfo->getLastIter());
5175 builder.restoreIP(oldIP);
5182 if (isTaskReductionMod)
5188 wsloopOp, builder, moduleTranslation, allocaIP, reductionDecls,
5189 privateReductionVariables, isByRef, wsloopOp.getNowait(),
5194 wsloopOp.getLoc(), privateVarsInfo);
5201 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5203 assert(isByRef.size() == opInst.getNumReductionVars());
5210 PrivateVarsInfo privateVarsInfo(opInst);
5212 moduleTranslation, privateVarsInfo)))
5219 opInst.getNumReductionVars());
5225 bool isTaskReductionMod =
5226 opInst.hasReductionModifier(omp::ReductionModifier::task);
5229 [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
5232 opInst, builder, moduleTranslation, privateVarsInfo, allocaIP);
5234 return llvm::make_error<PreviouslyReportedError>();
5240 cast<omp::BlockArgOpenMPOpInterface>(*opInst).getReductionBlockArgs();
5242 allocaIP = allocaIP.getNodeParent()->getTerminator()->getIterator();
5245 opInst, reductionArgs, builder, moduleTranslation, allocaIP,
5246 reductionDecls, privateReductionVariables, reductionVariableMap,
5247 deferredStores, isByRef)))
5248 return llvm::make_error<PreviouslyReportedError>();
5250 assert(afterAllocas.get()->getSinglePredecessor());
5251 builder.restoreIP(codeGenIP);
5257 return llvm::make_error<PreviouslyReportedError>();
5260 opInst, builder, moduleTranslation, privateVarsInfo.mlirVars,
5261 privateVarsInfo.llvmVars, privateVarsInfo.privatizers,
5262 opInst.getPrivateNeedsBarrier())))
5263 return llvm::make_error<PreviouslyReportedError>();
5266 initReductionVars(opInst, reductionArgs, builder, moduleTranslation,
5267 afterAllocas.get()->getSinglePredecessor(),
5268 reductionDecls, privateReductionVariables,
5269 reductionVariableMap, isByRef, deferredStores)))
5270 return llvm::make_error<PreviouslyReportedError>();
5275 if (isTaskReductionMod &&
5277 opInst, reductionDecls, privateReductionVariables, builder,
5278 allocaIP, moduleTranslation,
false))
5279 return llvm::createStringError(
5280 "failed to emit task reduction modifier initialization");
5285 moduleTranslation, allocaIP.getNodeParent(), deallocBlocks);
5289 opInst.getRegion(),
"omp.par.region", builder, moduleTranslation);
5291 return regionBlock.takeError();
5294 if (opInst.getNumReductionVars() > 0) {
5299 owningReductionGenRefDataPtrGens;
5301 collectReductionInfo(opInst, builder, moduleTranslation, reductionDecls,
5303 owningReductionGenRefDataPtrGens,
5304 privateReductionVariables, reductionInfos, isByRef);
5307 builder.SetInsertPoint((*regionBlock)->getTerminator());
5311 if (isTaskReductionMod)
5316 llvm::UnreachableInst *tempTerminator = builder.CreateUnreachable();
5317 builder.SetInsertPoint(tempTerminator);
5319 llvm::OpenMPIRBuilder::InsertPointOrErrorTy contInsertPoint =
5320 ompBuilder->createReductions(builder, allocaIP, reductionInfos,
5324 if (!contInsertPoint)
5325 return contInsertPoint.takeError();
5327 if (!contInsertPoint->isValid())
5328 return llvm::make_error<PreviouslyReportedError>();
5330 tempTerminator->eraseFromParent();
5331 builder.restoreIP(*contInsertPoint);
5334 return llvm::Error::success();
5337 auto privCB = [](InsertPointTy allocaIP, InsertPointTy codeGenIP,
5338 llvm::Value &, llvm::Value &val, llvm::Value *&replVal) {
5347 auto finiCB = [&](InsertPointTy codeGenIP) -> llvm::Error {
5348 InsertPointTy oldIP = builder.saveIP();
5349 builder.restoreIP(codeGenIP);
5354 llvm::transform(reductionDecls, std::back_inserter(reductionCleanupRegions),
5355 [](omp::DeclareReductionOp reductionDecl) {
5356 return &reductionDecl.getCleanupRegion();
5359 reductionCleanupRegions, privateReductionVariables,
5360 moduleTranslation, builder,
"omp.reduction.cleanup")))
5361 return llvm::createStringError(
5362 "failed to inline `cleanup` region of `omp.declare_reduction`");
5365 opInst.getLoc(), privateVarsInfo)))
5366 return llvm::make_error<PreviouslyReportedError>();
5370 if (isCancellable) {
5371 auto IPOrErr = ompBuilder->createBarrier(
5372 llvm::OpenMPIRBuilder::LocationDescription(builder),
5373 llvm::omp::Directive::OMPD_unknown,
5377 return IPOrErr.takeError();
5380 builder.restoreIP(oldIP);
5381 return llvm::Error::success();
5384 llvm::Value *ifCond =
nullptr;
5385 if (
auto ifVar = opInst.getIfExpr())
5387 llvm::Value *numThreads =
nullptr;
5388 if (!opInst.getNumThreadsVars().empty())
5389 numThreads = moduleTranslation.
lookupValue(opInst.getNumThreads(0));
5390 auto pbKind = llvm::omp::OMP_PROC_BIND_default;
5391 if (
auto bind = opInst.getProcBindKind())
5395 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
5397 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5399 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
5400 ompBuilder->createParallel(ompLoc, allocaIP, deallocBlocks, bodyGenCB,
5401 privCB, finiCB, ifCond, numThreads, pbKind,
5407 builder.restoreIP(*afterIP);
5412static llvm::omp::OrderKind
5415 return llvm::omp::OrderKind::OMP_ORDER_unknown;
5417 case omp::ClauseOrderKind::Concurrent:
5418 return llvm::omp::OrderKind::OMP_ORDER_concurrent;
5420 llvm_unreachable(
"Unknown ClauseOrderKind kind");
5428 auto simdOp = cast<omp::SimdOp>(opInst);
5433 PrivateVarsInfo privateVarsInfo(simdOp);
5434 privateVarsInfo.addLinearVars(simdOp);
5437 cast<omp::BlockArgOpenMPOpInterface>(opInst).getReductionBlockArgs();
5440 simdOp.getNumReductionVars());
5445 assert(isByRef.size() == simdOp.getNumReductionVars());
5447 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
5451 simdOp, builder, moduleTranslation, privateVarsInfo, allocaIP);
5456 moduleTranslation, allocaIP, reductionDecls,
5457 privateReductionVariables, reductionVariableMap,
5458 deferredStores, isByRef)))
5471 LinearClauseProcessor linearClauseProcessor;
5472 if (linearClauseProcessor.initLinearIV(simdOp).failed())
5475 if (!simdOp.getLinearVars().empty()) {
5476 auto linearVarTypes = simdOp.getLinearVarTypes().value();
5478 linearClauseProcessor.registerType(moduleTranslation, linearVarType);
5479 for (
auto [idx, linearVar] : llvm::enumerate(simdOp.getLinearVars())) {
5480 size_t privIdx = privateVarsInfo.numPrivateVars + idx;
5481 linearClauseProcessor.createLinearVar(
5482 builder, allocaIP, privateVarsInfo.privatizers[privIdx],
5484 privateVarsInfo.llvmVars[privIdx], idx);
5486 for (
mlir::Value linearStep : simdOp.getLinearStepVars())
5487 linearClauseProcessor.initLinearStep(moduleTranslation, linearStep);
5490 assert(afterAllocas.get()->getSinglePredecessor());
5491 if (failed(initReductionVars(simdOp, reductionArgs, builder,
5493 afterAllocas.get()->getSinglePredecessor(),
5494 reductionDecls, privateReductionVariables,
5495 reductionVariableMap, isByRef, deferredStores)))
5498 llvm::ConstantInt *simdlen =
nullptr;
5499 if (std::optional<uint64_t> simdlenVar = simdOp.getSimdlen())
5500 simdlen = builder.getInt64(simdlenVar.value());
5502 llvm::ConstantInt *safelen =
nullptr;
5503 if (std::optional<uint64_t> safelenVar = simdOp.getSafelen())
5504 safelen = builder.getInt64(safelenVar.value());
5509 llvm::BasicBlock *sourceBlock = builder.GetInsertBlock();
5510 std::optional<ArrayAttr> alignmentValues = simdOp.getAlignments();
5512 for (
size_t i = 0; i < operands.size(); ++i) {
5513 llvm::Value *alignment =
nullptr;
5514 llvm::Value *llvmVal = moduleTranslation.
lookupValue(operands[i]);
5515 llvm::Type *ty = llvmVal->getType();
5517 auto intAttr = cast<IntegerAttr>((*alignmentValues)[i]);
5518 alignment = builder.getInt64(intAttr.getInt());
5519 assert(ty->isPointerTy() &&
"Invalid type for aligned variable");
5520 assert(alignment &&
"Invalid alignment value");
5524 if (!intAttr.getValue().isPowerOf2())
5527 auto curInsert = builder.saveIP();
5528 builder.SetInsertPoint(sourceBlock);
5529 llvmVal = builder.CreateLoad(ty, llvmVal);
5530 builder.restoreIP(curInsert);
5531 alignedVars[llvmVal] = alignment;
5535 simdOp.getRegion(),
"omp.simd.region", builder, moduleTranslation);
5542 if (simdOp.getLinearVars().size()) {
5544 linearClauseProcessor.initLinearVar(builder, moduleTranslation,
5545 loopInfo->getPreheader()),
5549 if (failed(
handleError(linearClauseProcessor.updateLinearVar(
5550 builder, moduleTranslation, loopInfo->getBody(),
5551 loopInfo->getIndVar()),
5555 builder.SetInsertPoint((*regionBlock)->begin());
5557 ompBuilder->applySimd(loopInfo, alignedVars,
5559 ? moduleTranslation.
lookupValue(simdOp.getIfExpr())
5561 order, simdlen, safelen);
5564 linearClauseProcessor.updateLinearIV(builder, moduleTranslation),
5567 if (failed(
handleError(linearClauseProcessor.emitStoresForLinearVar(
5568 builder, moduleTranslation),
5576 for (
auto [i, tuple] : llvm::enumerate(
5577 llvm::zip(reductionDecls, isByRef, simdOp.getReductionVars(),
5578 privateReductionVariables))) {
5579 auto [decl, byRef, reductionVar, privateReductionVar] = tuple;
5581 OwningReductionGen gen =
makeReductionGen(decl, builder, moduleTranslation);
5582 llvm::Value *originalVariable = moduleTranslation.
lookupValue(reductionVar);
5583 llvm::Type *reductionType = moduleTranslation.
convertType(decl.getType());
5587 llvm::Value *redValue = originalVariable;
5590 builder.CreateLoad(reductionType, redValue,
"red.value." + Twine(i));
5591 llvm::Value *privateRedValue = builder.CreateLoad(
5592 reductionType, privateReductionVar,
"red.private.value." + Twine(i));
5593 llvm::Value *reduced;
5595 auto res = gen(builder.saveIP(), redValue, privateRedValue, reduced);
5598 builder.restoreIP(res.get());
5602 builder.CreateStore(reduced, originalVariable);
5607 llvm::transform(reductionDecls, std::back_inserter(reductionRegions),
5608 [](omp::DeclareReductionOp reductionDecl) {
5609 return &reductionDecl.getCleanupRegion();
5612 moduleTranslation, builder,
5613 "omp.reduction.cleanup")))
5621static llvm::OpenMPIRBuilder::CollapseIVMapping
5624 using Mapping = llvm::OpenMPIRBuilder::CollapseIVMapping;
5625 if (isTargetDevice || loopOp.getCollapseNumLoops() != 2 ||
5626 disableVirtualCollapse)
5627 return Mapping::DivMod;
5628 auto wsloop = dyn_cast<omp::WsloopOp>(loopOp->getParentOp());
5629 if (!wsloop || isa<omp::LoopWrapperInterface>(wsloop->getParentOp()) ||
5630 wsloop.getScheduleKind().value_or(omp::ClauseScheduleKind::Static) !=
5631 omp::ClauseScheduleKind::Static ||
5632 wsloop.getScheduleChunk() || wsloop.getOrdered().has_value() ||
5633 !wsloop.getLinearVars().empty())
5634 return Mapping::DivMod;
5637 if (llvm::any_of(loops, [](llvm::CanonicalLoopInfo *loop) {
5638 auto *count = llvm::dyn_cast<llvm::ConstantInt>(loop->getTripCount());
5641 return Mapping::DivMod;
5642 return Mapping::Virtual;
5650 auto loopOp = cast<omp::LoopNestOp>(opInst);
5656 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
5661 auto bodyGen = [&](llvm::OpenMPIRBuilder::InsertPointTy ip,
5662 llvm::Value *iv) -> llvm::Error {
5665 loopOp.getRegion().front().getArgument(loopInfos.size()), iv);
5670 bodyInsertPoints.push_back(ip);
5672 if (loopInfos.size() != loopOp.getNumLoops() - 1)
5673 return llvm::Error::success();
5676 builder.restoreIP(ip);
5678 loopOp.getRegion(),
"omp.loop_nest.region", builder, moduleTranslation);
5680 return regionBlock.takeError();
5682 builder.SetInsertPoint((*regionBlock)->begin());
5683 return llvm::Error::success();
5691 for (
unsigned i = 0, e = loopOp.getNumLoops(); i < e; ++i) {
5692 llvm::Value *lowerBound =
5693 moduleTranslation.
lookupValue(loopOp.getLoopLowerBounds()[i]);
5694 llvm::Value *upperBound =
5695 moduleTranslation.
lookupValue(loopOp.getLoopUpperBounds()[i]);
5696 llvm::Value *step = moduleTranslation.
lookupValue(loopOp.getLoopSteps()[i]);
5701 llvm::OpenMPIRBuilder::LocationDescription loc = ompLoc;
5702 llvm::OpenMPIRBuilder::InsertPointTy computeIP = ompLoc.IP;
5704 loc = llvm::OpenMPIRBuilder::LocationDescription(bodyInsertPoints.back(),
5706 computeIP = loopInfos.front()->getPreheaderIP();
5710 ompBuilder->createCanonicalLoop(
5711 loc, bodyGen, lowerBound, upperBound, step,
5712 true, loopOp.getLoopInclusive(), computeIP);
5717 loopInfos.push_back(*loopResult);
5720 llvm::OpenMPIRBuilder::InsertPointTy afterIP =
5721 loopInfos.front()->getAfterIP();
5724 if (
const auto &tiles = loopOp.getTileSizes()) {
5725 llvm::Type *ivType = loopInfos.front()->getIndVarType();
5728 for (
auto tile : tiles.value()) {
5729 llvm::Value *tileVal = llvm::ConstantInt::get(ivType,
tile);
5730 tileSizes.push_back(tileVal);
5733 std::vector<llvm::CanonicalLoopInfo *> newLoops =
5734 ompBuilder->tileLoops(ompLoc.DL, loopInfos, tileSizes);
5738 llvm::BasicBlock *afterBB = newLoops.front()->getAfter();
5739 llvm::BasicBlock *afterAfterBB = afterBB->getSingleSuccessor();
5740 afterIP = afterAfterBB->begin();
5744 for (
const auto &newLoop : newLoops)
5745 loopInfos.push_back(newLoop);
5749 const auto &numCollapse = loopOp.getCollapseNumLoops();
5751 loopInfos.begin(), loopInfos.begin() + (numCollapse));
5753 llvm::SaveAndRestore<llvm::OpenMPIRBuilder::CollapseIVMapping> mappingGuard(
5754 ompBuilder->Config.CollapseMapping,
5756 collapseLoopInfos));
5757 auto newTopLoopInfo =
5758 ompBuilder->collapseLoops(ompLoc.DL, collapseLoopInfos, {});
5760 assert(newTopLoopInfo &&
"New top loop information is missing");
5761 moduleTranslation.
stackWalk<OpenMPLoopInfoStackFrame>(
5762 [&](OpenMPLoopInfoStackFrame &frame) {
5763 frame.loopInfo = newTopLoopInfo;
5771 builder.restoreIP(afterIP);
5781 llvm::OpenMPIRBuilder::LocationDescription loopLoc(builder);
5782 Value loopIV = op.getInductionVar();
5783 Value loopTC = op.getTripCount();
5785 llvm::Value *llvmTC = moduleTranslation.
lookupValue(loopTC);
5788 ompBuilder->createCanonicalLoop(
5790 [&](llvm::OpenMPIRBuilder::InsertPointTy ip, llvm::Value *llvmIV) {
5793 moduleTranslation.
mapValue(loopIV, llvmIV);
5795 builder.restoreIP(ip);
5800 return bodyGenStatus.takeError();
5802 llvmTC,
"omp.loop");
5804 return op.emitError(llvm::toString(llvmOrError.takeError()));
5806 llvm::CanonicalLoopInfo *llvmCLI = *llvmOrError;
5807 llvm::IRBuilderBase::InsertPoint afterIP = llvmCLI->getAfterIP();
5808 builder.restoreIP(afterIP);
5811 if (
Value cli = op.getCli())
5824 Value applyee = op.getApplyee();
5825 assert(applyee &&
"Loop to apply unrolling on required");
5827 llvm::CanonicalLoopInfo *consBuilderCLI =
5829 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
5830 ompBuilder->unrollLoopHeuristic(loc.DL, consBuilderCLI);
5843 Value applyee = op.getApplyee();
5844 assert(applyee &&
"Loop to apply unrolling on required");
5846 llvm::CanonicalLoopInfo *consBuilderCLI =
5848 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
5849 ompBuilder->unrollLoopFull(loc.DL, consBuilderCLI);
5862 Value applyee = op.getApplyee();
5863 assert(applyee &&
"Loop to apply unrolling on required");
5865 llvm::CanonicalLoopInfo *consBuilderCLI =
5867 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
5871 int32_t factor =
static_cast<int32_t
>(op.getUnrollFactor());
5872 ompBuilder->unrollLoopPartial(loc.DL, consBuilderCLI, factor,
5881static LogicalResult
applyTile(omp::TileOp op, llvm::IRBuilderBase &builder,
5884 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
5889 for (
Value size : op.getSizes()) {
5890 llvm::Value *translatedSize = moduleTranslation.
lookupValue(size);
5891 assert(translatedSize &&
5892 "sizes clause arguments must already be translated");
5893 translatedSizes.push_back(translatedSize);
5896 for (
Value applyee : op.getApplyees()) {
5897 llvm::CanonicalLoopInfo *consBuilderCLI =
5899 assert(applyee &&
"Canonical loop must already been translated");
5900 translatedLoops.push_back(consBuilderCLI);
5903 auto generatedLoops =
5904 ompBuilder->tileLoops(loc.DL, translatedLoops, translatedSizes);
5905 if (!op.getGeneratees().empty()) {
5906 for (
auto [mlirLoop,
genLoop] :
5907 zip_equal(op.getGeneratees(), generatedLoops))
5912 for (
Value applyee : op.getApplyees())
5920static LogicalResult
applyFuse(omp::FuseOp op, llvm::IRBuilderBase &builder,
5923 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
5927 for (
size_t i = 0; i < op.getApplyees().size(); i++) {
5928 Value applyee = op.getApplyees()[i];
5929 llvm::CanonicalLoopInfo *consBuilderCLI =
5931 assert(applyee &&
"Canonical loop must already been translated");
5932 if (op.getFirst().has_value() && i < op.getFirst().value() - 1)
5933 beforeFuse.push_back(consBuilderCLI);
5934 else if (op.getCount().has_value() &&
5935 i >= op.getFirst().value() + op.getCount().value() - 1)
5936 afterFuse.push_back(consBuilderCLI);
5938 toFuse.push_back(consBuilderCLI);
5941 (op.getGeneratees().empty() ||
5942 beforeFuse.size() + afterFuse.size() + 1 == op.getGeneratees().size()) &&
5943 "Wrong number of generatees");
5946 auto generatedLoop = ompBuilder->fuseLoops(loc.DL, toFuse);
5947 if (!op.getGeneratees().empty()) {
5949 for (; i < beforeFuse.size(); i++)
5950 mapOmpLoop(moduleTranslation, op.getGeneratees()[i], beforeFuse[i]);
5951 mapOmpLoop(moduleTranslation, op.getGeneratees()[i++], generatedLoop);
5952 for (; i < afterFuse.size(); i++)
5953 mapOmpLoop(moduleTranslation, op.getGeneratees()[i], afterFuse[i]);
5957 for (
Value applyee : op.getApplyees())
5964static llvm::AtomicOrdering
5967 return llvm::AtomicOrdering::Monotonic;
5970 case omp::ClauseMemoryOrderKind::Seq_cst:
5971 return llvm::AtomicOrdering::SequentiallyConsistent;
5972 case omp::ClauseMemoryOrderKind::Acq_rel:
5973 return llvm::AtomicOrdering::AcquireRelease;
5974 case omp::ClauseMemoryOrderKind::Acquire:
5975 return llvm::AtomicOrdering::Acquire;
5976 case omp::ClauseMemoryOrderKind::Release:
5977 return llvm::AtomicOrdering::Release;
5978 case omp::ClauseMemoryOrderKind::Relaxed:
5979 return llvm::AtomicOrdering::Monotonic;
5981 llvm_unreachable(
"Unknown ClauseMemoryOrderKind kind");
5988static llvm::AtomicOrdering
5990 llvm::AtomicOrdering atomicOrdering) {
5991 if (atomicCompareOp.getFailMemoryOrder())
5993 return llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(atomicOrdering);
6000 auto readOp = cast<omp::AtomicReadOp>(opInst);
6005 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
6008 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6011 llvm::Value *x = moduleTranslation.
lookupValue(readOp.getX());
6012 llvm::Value *v = moduleTranslation.
lookupValue(readOp.getV());
6014 llvm::Type *elementType =
6015 moduleTranslation.
convertType(readOp.getElementType());
6017 llvm::OpenMPIRBuilder::AtomicOpValue V = {v, elementType,
false,
false};
6018 llvm::OpenMPIRBuilder::AtomicOpValue X = {x, elementType,
false,
false};
6019 builder.restoreIP(ompBuilder->createAtomicRead(ompLoc, X, V, AO, allocaIP));
6027 auto writeOp = cast<omp::AtomicWriteOp>(opInst);
6032 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
6035 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6037 llvm::Value *expr = moduleTranslation.
lookupValue(writeOp.getExpr());
6038 llvm::Value *dest = moduleTranslation.
lookupValue(writeOp.getX());
6039 llvm::Type *ty = moduleTranslation.
convertType(writeOp.getExpr().getType());
6040 llvm::OpenMPIRBuilder::AtomicOpValue x = {dest, ty,
false,
6043 ompBuilder->createAtomicWrite(ompLoc, x, expr, ao, allocaIP));
6051 .Case([&](LLVM::AddOp) {
return llvm::AtomicRMWInst::BinOp::Add; })
6052 .Case([&](LLVM::SubOp) {
return llvm::AtomicRMWInst::BinOp::Sub; })
6053 .Case([&](LLVM::AndOp) {
return llvm::AtomicRMWInst::BinOp::And; })
6054 .Case([&](LLVM::OrOp) {
return llvm::AtomicRMWInst::BinOp::Or; })
6055 .Case([&](LLVM::XOrOp) {
return llvm::AtomicRMWInst::BinOp::Xor; })
6056 .Case([&](LLVM::SMaxOp) {
return llvm::AtomicRMWInst::BinOp::Max; })
6057 .Case([&](LLVM::SMinOp) {
return llvm::AtomicRMWInst::BinOp::Min; })
6058 .Case([&](LLVM::UMaxOp) {
return llvm::AtomicRMWInst::BinOp::UMax; })
6059 .Case([&](LLVM::UMinOp) {
return llvm::AtomicRMWInst::BinOp::UMin; })
6060 .Case([&](LLVM::FAddOp) {
return llvm::AtomicRMWInst::BinOp::FAdd; })
6061 .Case([&](LLVM::FSubOp) {
return llvm::AtomicRMWInst::BinOp::FSub; })
6062 .Case([&](LLVM::MaxNumOp) {
return llvm::AtomicRMWInst::BinOp::FMax; })
6063 .Case([&](LLVM::MinNumOp) {
return llvm::AtomicRMWInst::BinOp::FMin; })
6065 [&](LLVM::MaximumOp) {
return llvm::AtomicRMWInst::BinOp::FMaximum; })
6067 [&](LLVM::MinimumOp) {
return llvm::AtomicRMWInst::BinOp::FMinimum; })
6068 .Default(llvm::AtomicRMWInst::BinOp::BAD_BINOP);
6072 bool &isIgnoreDenormalMode,
6073 bool &isFineGrainedMemory,
6074 bool &isRemoteMemory) {
6075 isIgnoreDenormalMode =
false;
6076 isFineGrainedMemory =
false;
6077 isRemoteMemory =
false;
6078 if (atomicUpdateOp && atomicUpdateOp.getAtomicControlAttr()) {
6079 mlir::omp::AtomicControlAttr atomicControlAttr =
6080 atomicUpdateOp.getAtomicControlAttr();
6081 isIgnoreDenormalMode = atomicControlAttr.getIgnoreDenormalMode();
6082 isFineGrainedMemory = atomicControlAttr.getFineGrainedMemory();
6083 isRemoteMemory = atomicControlAttr.getRemoteMemory();
6090 llvm::IRBuilderBase &builder,
6097 auto &innerOpList = opInst.getRegion().front().getOperations();
6098 bool isXBinopExpr{
false};
6099 llvm::AtomicRMWInst::BinOp binop;
6101 llvm::Value *llvmExpr =
nullptr;
6102 llvm::Value *llvmX =
nullptr;
6103 llvm::Type *llvmXElementType =
nullptr;
6104 if (innerOpList.size() == 2) {
6110 opInst.getRegion().getArgument(0))) {
6111 return opInst.emitError(
"no atomic update operation with region argument"
6112 " as operand found inside atomic.update region");
6115 isXBinopExpr = innerOp.
getOperand(0) == opInst.getRegion().getArgument(0);
6117 llvmExpr = moduleTranslation.
lookupValue(mlirExpr);
6121 binop = llvm::AtomicRMWInst::BinOp::BAD_BINOP;
6123 llvmX = moduleTranslation.
lookupValue(opInst.getX());
6125 opInst.getRegion().getArgument(0).getType());
6126 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {llvmX, llvmXElementType,
6130 llvm::AtomicOrdering atomicOrdering =
6135 [&opInst, &moduleTranslation](
6136 llvm::Value *atomicx,
6139 moduleTranslation.
mapValue(*opInst.getRegion().args_begin(), atomicx);
6140 moduleTranslation.
mapBlock(&bb, builder.GetInsertBlock());
6141 if (failed(moduleTranslation.
convertBlock(bb,
true, builder)))
6142 return llvm::make_error<PreviouslyReportedError>();
6144 omp::YieldOp yieldop = dyn_cast<omp::YieldOp>(bb.
getTerminator());
6145 assert(yieldop && yieldop.getResults().size() == 1 &&
6146 "terminator must be omp.yield op and it must have exactly one "
6148 return moduleTranslation.
lookupValue(yieldop.getResults()[0]);
6151 bool isIgnoreDenormalMode;
6152 bool isFineGrainedMemory;
6153 bool isRemoteMemory;
6158 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6159 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
6160 ompBuilder->createAtomicUpdate(ompLoc, allocaIP, llvmAtomicX, llvmExpr,
6161 atomicOrdering, binop, updateFn,
6162 isXBinopExpr, isIgnoreDenormalMode,
6163 isFineGrainedMemory, isRemoteMemory);
6168 builder.restoreIP(*afterIP);
6174static std::optional<llvm::omp::OMPAtomicCompareOp>
6176 switch (predicate) {
6177 case LLVM::ICmpPredicate::eq:
6178 return llvm::omp::OMPAtomicCompareOp::EQ;
6179 case LLVM::ICmpPredicate::slt:
6180 case LLVM::ICmpPredicate::ult:
6181 return llvm::omp::OMPAtomicCompareOp::MIN;
6182 case LLVM::ICmpPredicate::sgt:
6183 case LLVM::ICmpPredicate::ugt:
6184 return llvm::omp::OMPAtomicCompareOp::MAX;
6186 return std::nullopt;
6192static std::optional<llvm::omp::OMPAtomicCompareOp>
6194 switch (predicate) {
6195 case LLVM::FCmpPredicate::oeq:
6196 case LLVM::FCmpPredicate::ueq:
6197 return llvm::omp::OMPAtomicCompareOp::EQ;
6198 case LLVM::FCmpPredicate::olt:
6199 case LLVM::FCmpPredicate::ult:
6200 return llvm::omp::OMPAtomicCompareOp::MIN;
6201 case LLVM::FCmpPredicate::ogt:
6202 case LLVM::FCmpPredicate::ugt:
6203 return llvm::omp::OMPAtomicCompareOp::MAX;
6205 return std::nullopt;
6232 if (
auto extractOp = v.getDefiningOp<LLVM::ExtractValueOp>())
6233 return extractOp.getContainer();
6237 if (!isa<LLVM::AndOp, LLVM::OrOp>(op))
6241 if (!lhsFcmp || !rhsFcmp)
6243 mlir::Value lhsAgg0 = traceToAggregate(lhsFcmp.getOperand(0));
6244 mlir::Value lhsAgg1 = traceToAggregate(lhsFcmp.getOperand(1));
6245 bool lhsXIsOp0 = (lhsAgg0 == block.
getArgument(0));
6246 bool lhsXIsOp1 = (lhsAgg1 == block.
getArgument(0));
6247 if (!lhsXIsOp0 && !lhsXIsOp1)
6249 mlir::Value eAggregate = lhsXIsOp0 ? lhsAgg1 : lhsAgg0;
6253 result.isNE = isa<LLVM::OrOp>(op);
6254 result.eAggregate = eAggregate;
6255 result.isXBinopExpr = lhsXIsOp0;
6267 llvm::Value *llvmX, llvm::Type *complexTy,
6268 llvm::Value *eVal, llvm::Value *dVal,
6269 llvm::AtomicOrdering atomicOrdering,
6270 llvm::AtomicOrdering failOrdering,
6271 bool isWeak, llvm::Value *&oldComplex,
6272 llvm::Value *&cmpOk) {
6273 const llvm::DataLayout &DL = builder.getDataLayout();
6274 unsigned totalBits = DL.getTypeStoreSizeInBits(complexTy).getFixedValue();
6275 llvm::IntegerType *intTy =
6276 llvm::IntegerType::get(builder.getContext(), totalBits);
6277 llvm::Align complexAlign = DL.getABITypeAlign(complexTy);
6278 llvm::Align intAlign = DL.getABITypeAlign(intTy);
6279 llvm::Align maxAlign = std::max(complexAlign, intAlign);
6282 llvm::AllocaInst *dAlloca =
6283 builder.CreateAlloca(complexTy,
nullptr,
"cmplx.d");
6284 dAlloca->setAlignment(maxAlign);
6285 builder.CreateAlignedStore(dVal, dAlloca, maxAlign);
6287 builder.CreateAlignedLoad(intTy, dAlloca, maxAlign,
"cmplx.d.int");
6292 llvm::LoadInst *xCurr =
6293 builder.CreateAlignedLoad(intTy, llvmX, maxAlign,
"cmplx.x.load");
6294 xCurr->setAtomic(failOrdering);
6295 llvm::AllocaInst *xAlloca =
6296 builder.CreateAlloca(complexTy,
nullptr,
"cmplx.x");
6297 xAlloca->setAlignment(maxAlign);
6298 builder.CreateAlignedStore(xCurr, xAlloca, maxAlign);
6299 llvm::Value *xStruct =
6300 builder.CreateAlignedLoad(complexTy, xAlloca, maxAlign,
"cmplx.x.val");
6305 llvm::Value *reX = builder.CreateExtractValue(xStruct, 0);
6306 llvm::Value *imX = builder.CreateExtractValue(xStruct, 1);
6307 llvm::Value *reE = builder.CreateExtractValue(eVal, 0);
6308 llvm::Value *imE = builder.CreateExtractValue(eVal, 1);
6309 llvm::Value *reEq = builder.CreateFCmpOEQ(reX, reE,
"cmplx.re.eq");
6310 llvm::Value *imEq = builder.CreateFCmpOEQ(imX, imE,
"cmplx.im.eq");
6311 llvm::Value *fpEqual = builder.CreateAnd(reEq, imEq,
"cmplx.eq");
6316 llvm::BasicBlock *curBB = builder.GetInsertBlock();
6317 llvm::Function *fn = curBB->getParent();
6318 llvm::BasicBlock *swapBB =
6319 llvm::BasicBlock::Create(builder.getContext(),
"cmplx.atomic.swap", fn);
6320 llvm::BasicBlock *exitBB =
6321 llvm::BasicBlock::Create(builder.getContext(),
"cmplx.atomic.exit", fn);
6322 builder.CreateCondBr(fpEqual, swapBB, exitBB);
6324 builder.SetInsertPoint(swapBB);
6325 llvm::AtomicCmpXchgInst *cmpXchg = builder.CreateAtomicCmpXchg(
6326 llvmX, xCurr, dInt, maxAlign, atomicOrdering, failOrdering);
6327 cmpXchg->setWeak(isWeak);
6328 llvm::Value *oldSwap = builder.CreateExtractValue(cmpXchg, 0);
6329 llvm::Value *okSwap = builder.CreateExtractValue(cmpXchg, 1);
6330 builder.CreateBr(exitBB);
6333 builder.SetInsertPoint(exitBB);
6334 llvm::PHINode *oldIntPHI = builder.CreatePHI(intTy, 2,
"cmplx.old.int");
6335 oldIntPHI->addIncoming(oldSwap, swapBB);
6336 oldIntPHI->addIncoming(xCurr, curBB);
6337 llvm::PHINode *okPHI = builder.CreatePHI(builder.getInt1Ty(), 2,
"cmplx.ok");
6338 okPHI->addIncoming(okSwap, swapBB);
6339 okPHI->addIncoming(builder.getFalse(), curBB);
6342 llvm::AllocaInst *oldAlloca =
6343 builder.CreateAlloca(complexTy,
nullptr,
"cmplx.old");
6344 oldAlloca->setAlignment(maxAlign);
6345 builder.CreateAlignedStore(oldIntPHI, oldAlloca, maxAlign);
6346 oldComplex = builder.CreateAlignedLoad(complexTy, oldAlloca, maxAlign,
6354 llvm::omp::OMPAtomicCompareOp
compareOp = llvm::omp::OMPAtomicCompareOp::EQ;
6374 return atomicCompareOp.emitError(
6375 "unsupported comparison predicate (NE) for complex atomic compare");
6376 info.
compareOp = llvm::omp::OMPAtomicCompareOp::EQ;
6378 info.
eVal = materializeValue(cplx.eAggregate);
6380 if (
auto selectOp = dyn_cast<LLVM::SelectOp>(op)) {
6381 info.
dVal = materializeValue(selectOp.getTrueValue());
6391 if (
auto icmpOp = dyn_cast<LLVM::ICmpOp>(op);
6392 icmpOp && icmpOp.getOperand(0) != block.
getArgument(0) &&
6398 .Case<LLVM::ICmpOp>([&](LLVM::ICmpOp icmpOp) -> LogicalResult {
6402 return atomicCompareOp.emitError(
6403 "unsupported comparison predicate in atomic compare");
6405 LLVM::ICmpPredicate pred = icmpOp.getPredicate();
6406 info.
isSigned = (pred == LLVM::ICmpPredicate::slt ||
6407 pred == LLVM::ICmpPredicate::sgt ||
6408 pred == LLVM::ICmpPredicate::sle ||
6409 pred == LLVM::ICmpPredicate::sge);
6413 : icmpOp.getOperand(0);
6414 info.
eVal = materializeValue(eOperand);
6417 .Case<LLVM::FCmpOp>([&](LLVM::FCmpOp fcmpOp) -> LogicalResult {
6421 return atomicCompareOp.emitError(
6422 "unsupported comparison predicate in atomic compare");
6427 : fcmpOp.getOperand(0);
6428 info.
eVal = materializeValue(eOperand);
6431 .Case<LLVM::SelectOp>([&](LLVM::SelectOp selectOp) {
6433 info.
dVal = materializeValue(selectOp.getTrueValue());
6436 .Case<mlir::arith::MaxSIOp, mlir::arith::MinSIOp,
6437 mlir::arith::MaxUIOp, mlir::arith::MinUIOp,
6438 mlir::arith::MaximumFOp, mlir::arith::MinimumFOp,
6439 LLVM::SMaxOp, LLVM::SMinOp, LLVM::UMaxOp, LLVM::UMinOp,
6440 LLVM::MaxNumOp, LLVM::MinNumOp>([&](
Operation *) {
6445 bool isMax = isa<mlir::arith::MaxSIOp, mlir::arith::MaxUIOp,
6446 mlir::arith::MaximumFOp, LLVM::SMaxOp,
6447 LLVM::UMaxOp, LLVM::MaxNumOp>(op);
6448 info.
compareOp = isMax ? llvm::omp::OMPAtomicCompareOp::MIN
6449 : llvm::omp::OMPAtomicCompareOp::MAX;
6450 info.
isSigned = isa<mlir::arith::MaxSIOp, mlir::arith::MinSIOp,
6451 LLVM::SMaxOp, LLVM::SMinOp>(op);
6455 info.
eVal = materializeValue(eOperand);
6469 llvm::IRBuilderBase &builder,
6475 omp::AtomicUpdateOp atomicUpdateOp = atomicCaptureOp.getAtomicUpdateOp();
6476 omp::AtomicWriteOp atomicWriteOp = atomicCaptureOp.getAtomicWriteOp();
6477 omp::AtomicCompareOp atomicCompareOp = atomicCaptureOp.getAtomicCompareOp();
6481 if (atomicCompareOp) {
6482 omp::AtomicReadOp atomicReadOp = atomicCaptureOp.getAtomicReadOp();
6483 assert(atomicReadOp &&
"expected atomic.read in capture+compare");
6485 Region ®ion = atomicCompareOp.getRegion();
6488 llvm::Type *llvmXElementType =
6490 llvm::Value *llvmX = moduleTranslation.
lookupValue(atomicCompareOp.getX());
6491 llvm::Value *llvmV = moduleTranslation.
lookupValue(atomicReadOp.getV());
6493 bool isSigned =
false;
6494 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {
6495 llvmX, llvmXElementType, isSigned,
false};
6496 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicV = {
6497 llvmV, llvmXElementType,
false,
false};
6498 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicR = {
nullptr,
nullptr,
false,
6501 llvm::AtomicOrdering atomicOrdering =
6505 auto isAtomicComparePatternOp = [](
Operation &op) {
6506 return llvm::isa<LLVM::ICmpOp, LLVM::FCmpOp, LLVM::SelectOp, LLVM::AndOp,
6507 LLVM::OrOp, LLVM::SMaxOp, LLVM::SMinOp, LLVM::UMaxOp,
6508 LLVM::UMinOp, LLVM::MaxNumOp, LLVM::MinNumOp,
6509 mlir::arith::MaxSIOp, mlir::arith::MinSIOp,
6510 mlir::arith::MaxUIOp, mlir::arith::MinUIOp,
6511 mlir::arith::MaximumFOp, mlir::arith::MinimumFOp>(op);
6514 if (isAtomicComparePatternOp(op))
6516 bool allOperandsMapped =
6518 return moduleTranslation.lookupValue(v) != nullptr;
6520 if (!allOperandsMapped)
6523 return atomicCompareOp.emitError(
6524 "failed to translate operation inside atomic compare region");
6527 auto materializeValue = [&](
mlir::Value val) -> llvm::Value * {
6528 if (llvm::Value *existing = moduleTranslation.
lookupValue(val))
6530 if (
auto loadOp = val.getDefiningOp<LLVM::LoadOp>()) {
6531 if (loadOp->getParentRegion() == ®ion) {
6532 llvm::Value *loadAddr =
6536 llvm::Type *loadType =
6537 moduleTranslation.
convertType(loadOp.getResult().getType());
6538 return builder.CreateLoad(loadType, loadAddr);
6547 atomicCompareOp, patternInfo)))
6550 llvm::omp::OMPAtomicCompareOp compareOp = patternInfo.
compareOp;
6551 llvm::Value *eVal = patternInfo.
eVal;
6552 llvm::Value *dVal = patternInfo.
dVal;
6557 return atomicCompareOp.emitError(
6558 "failed to extract expected value (e) from atomic compare region");
6561 if (yieldOp.getResults().empty())
6562 return atomicCompareOp.emitError(
6563 "failed to extract desired value (d) from atomic compare region");
6564 dVal = materializeValue(yieldOp.getResults()[0]);
6567 llvmAtomicX.IsSigned = isSigned;
6569 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6570 bool isReadFirst = isa<omp::AtomicReadOp>(atomicCaptureOp.getFirstOp());
6571 bool isPostfixCapture = !isReadFirst;
6572 bool isFailOnly = atomicCaptureOp.getFailOnly();
6580 if (llvmXElementType->isStructTy()) {
6581 llvm::Value *oldComplex =
nullptr;
6582 llvm::Value *cmpOk =
nullptr;
6583 llvm::AtomicOrdering failOrdering =
6586 atomicOrdering, failOrdering,
6587 atomicCompareOp.getWeak(), oldComplex, cmpOk);
6591 llvm::Value *cmpFailed = builder.CreateNot(cmpOk);
6592 llvm::BasicBlock *curBB = builder.GetInsertBlock();
6593 llvm::Function *fn = curBB->getParent();
6594 llvm::BasicBlock *contBB = llvm::BasicBlock::Create(
6595 builder.getContext(),
"omp.atomic.cont", fn);
6596 llvm::BasicBlock *exitBB = llvm::BasicBlock::Create(
6597 builder.getContext(),
"omp.atomic.exit", fn);
6598 builder.CreateCondBr(cmpFailed, contBB, exitBB);
6599 builder.SetInsertPoint(contBB);
6600 builder.CreateStore(oldComplex, llvmAtomicV.Var,
6601 llvmAtomicV.IsVolatile);
6602 builder.CreateBr(exitBB);
6603 builder.SetInsertPoint(exitBB);
6604 }
else if (isPostfixCapture) {
6606 llvm::Value *newComplex = builder.CreateSelect(cmpOk, dVal, oldComplex);
6607 builder.CreateStore(newComplex, llvmAtomicV.Var,
6608 llvmAtomicV.IsVolatile);
6611 builder.CreateStore(oldComplex, llvmAtomicV.Var,
6612 llvmAtomicV.IsVolatile);
6616 if (atomicOrdering == llvm::AtomicOrdering::Release ||
6617 atomicOrdering == llvm::AtomicOrdering::AcquireRelease ||
6618 atomicOrdering == llvm::AtomicOrdering::SequentiallyConsistent) {
6619 llvm::OpenMPIRBuilder::LocationDescription flushLoc(builder);
6620 ompBuilder->createFlush(flushLoc);
6631 bool isMinMax = compareOp != llvm::omp::OMPAtomicCompareOp::EQ;
6633 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicVForCall = llvmAtomicV;
6640 bool minMaxManualCapture = isMinMax && (isPostfixCapture || isFailOnly);
6641 bool eqPostfixManualCapture = !isMinMax && isPostfixCapture && !isFailOnly;
6642 if (minMaxManualCapture || eqPostfixManualCapture)
6643 llvmAtomicVForCall = {
nullptr,
nullptr,
false,
false};
6647 bool builderFailOnly = isFailOnly && !isMinMax;
6654 bool isPostfixUpdate = !builderFailOnly;
6656 bool isWeak = atomicCompareOp.getWeak();
6657 bool savedHandleFPNegZero = ompBuilder->setHandleFPNegZero(
true);
6658 llvm::AtomicOrdering failureOrdering =
6660 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
6661 ompBuilder->createAtomicCompare(
6662 ompLoc, llvmAtomicX, llvmAtomicVForCall, llvmAtomicR, eVal, dVal,
6663 atomicOrdering, compareOp, isXBinopExpr, isPostfixUpdate,
6664 builderFailOnly, failureOrdering, isWeak);
6665 ompBuilder->setHandleFPNegZero(savedHandleFPNegZero);
6667 if (failed(
handleError(afterIP, *atomicCaptureOp)))
6670 builder.restoreIP(*afterIP);
6679 if (isMinMax && (isPostfixCapture || isFailOnly)) {
6680 llvm::BasicBlock *curBB = builder.GetInsertBlock();
6681 llvm::AtomicRMWInst *rmw =
nullptr;
6682 for (
auto &inst : llvm::reverse(*curBB)) {
6683 if (
auto *r = dyn_cast<llvm::AtomicRMWInst>(&inst)) {
6688 assert(rmw &&
"expected atomicrmw for min/max compare capture");
6689 llvm::Value *oldVal = rmw;
6690 llvm::Value *rhs = rmw->getValOperand();
6696 llvm::CmpInst::Predicate updatePred;
6697 switch (rmw->getOperation()) {
6698 case llvm::AtomicRMWInst::Min:
6699 updatePred = llvm::CmpInst::ICMP_SGT;
6701 case llvm::AtomicRMWInst::Max:
6702 updatePred = llvm::CmpInst::ICMP_SLT;
6704 case llvm::AtomicRMWInst::UMin:
6705 updatePred = llvm::CmpInst::ICMP_UGT;
6707 case llvm::AtomicRMWInst::UMax:
6708 updatePred = llvm::CmpInst::ICMP_ULT;
6710 case llvm::AtomicRMWInst::FMin:
6711 updatePred = llvm::CmpInst::FCMP_OGT;
6713 case llvm::AtomicRMWInst::FMax:
6714 updatePred = llvm::CmpInst::FCMP_OLT;
6718 "unexpected atomicrmw op for min/max compare capture");
6720 llvm::Value *updated = builder.CreateCmp(updatePred, oldVal, rhs);
6721 llvm::Value *failed = builder.CreateNot(updated);
6722 llvm::Function *fn = curBB->getParent();
6723 llvm::BasicBlock *contBB = llvm::BasicBlock::Create(
6724 builder.getContext(),
"omp.atomic.cont", fn);
6725 llvm::BasicBlock *exitBB = llvm::BasicBlock::Create(
6726 builder.getContext(),
"omp.atomic.exit", fn);
6727 builder.CreateCondBr(failed, contBB, exitBB);
6728 builder.SetInsertPoint(contBB);
6729 builder.CreateStore(oldVal, llvmAtomicV.Var, llvmAtomicV.IsVolatile);
6730 builder.CreateBr(exitBB);
6731 builder.SetInsertPoint(exitBB);
6733 llvm::Intrinsic::ID id;
6734 switch (rmw->getOperation()) {
6735 case llvm::AtomicRMWInst::Min:
6736 id = llvm::Intrinsic::smin;
6738 case llvm::AtomicRMWInst::Max:
6739 id = llvm::Intrinsic::smax;
6741 case llvm::AtomicRMWInst::UMin:
6742 id = llvm::Intrinsic::umin;
6744 case llvm::AtomicRMWInst::UMax:
6745 id = llvm::Intrinsic::umax;
6747 case llvm::AtomicRMWInst::FMin:
6748 id = llvm::Intrinsic::minnum;
6750 case llvm::AtomicRMWInst::FMax:
6751 id = llvm::Intrinsic::maxnum;
6755 "unexpected atomicrmw op for min/max compare capture");
6757 llvm::Value *newVal = builder.CreateBinaryIntrinsic(
id, oldVal, rhs);
6758 builder.CreateStore(newVal, llvmAtomicV.Var, llvmAtomicV.IsVolatile);
6764 if (!isMinMax && isPostfixCapture && !isFailOnly) {
6765 llvm::BasicBlock *curBB = builder.GetInsertBlock();
6766 llvm::Value *oldVal =
nullptr;
6767 llvm::Value *successVal =
nullptr;
6771 for (
auto &inst : llvm::reverse(*curBB)) {
6772 if (isa<llvm::AtomicCmpXchgInst>(&inst)) {
6773 oldVal = builder.CreateExtractValue(&inst, 0);
6774 successVal = builder.CreateExtractValue(&inst, 1);
6785 for (
auto &inst : *curBB) {
6786 auto *phi = dyn_cast<llvm::PHINode>(&inst);
6789 if (phi->getType()->isIntegerTy(1))
6792 for (
auto &inst : *curBB) {
6793 if (
auto *bc = dyn_cast<llvm::BitCastInst>(&inst)) {
6800 assert(oldVal &&
"expected cmpxchg or PHI+bitcast for compare capture");
6801 assert(successVal &&
"expected success flag for compare capture");
6802 llvm::Value *newVal = builder.CreateSelect(successVal, dVal, oldVal);
6803 builder.CreateStore(newVal, llvmAtomicV.Var, llvmAtomicV.IsVolatile);
6810 bool isXBinopExpr =
false, isPostfixUpdate =
false;
6811 llvm::AtomicRMWInst::BinOp binop = llvm::AtomicRMWInst::BinOp::BAD_BINOP;
6813 assert((atomicUpdateOp || atomicWriteOp) &&
6814 "internal op must be an atomic.update or atomic.write op");
6816 if (atomicWriteOp) {
6817 isPostfixUpdate =
true;
6818 mlirExpr = atomicWriteOp.getExpr();
6820 isPostfixUpdate = atomicCaptureOp.getSecondOp() ==
6821 atomicCaptureOp.getAtomicUpdateOp().getOperation();
6822 auto &innerOpList = atomicUpdateOp.getRegion().front().getOperations();
6825 if (innerOpList.size() == 2) {
6828 atomicUpdateOp.getRegion().getArgument(0))) {
6829 return atomicUpdateOp.emitError(
6830 "no atomic update operation with region argument"
6831 " as operand found inside atomic.update region");
6835 innerOp.
getOperand(0) == atomicUpdateOp.getRegion().getArgument(0);
6838 binop = llvm::AtomicRMWInst::BinOp::BAD_BINOP;
6842 llvm::Value *llvmExpr = moduleTranslation.
lookupValue(mlirExpr);
6843 llvm::Value *llvmX =
6844 moduleTranslation.
lookupValue(atomicCaptureOp.getAtomicReadOp().getX());
6845 llvm::Value *llvmV =
6846 moduleTranslation.
lookupValue(atomicCaptureOp.getAtomicReadOp().getV());
6847 llvm::Type *llvmXElementType = moduleTranslation.
convertType(
6848 atomicCaptureOp.getAtomicReadOp().getElementType());
6849 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {llvmX, llvmXElementType,
6852 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicV = {llvmV, llvmXElementType,
6856 llvm::AtomicOrdering atomicOrdering =
6860 [&](llvm::Value *atomicx,
6863 return moduleTranslation.
lookupValue(atomicWriteOp.getExpr());
6864 Block &bb = *atomicUpdateOp.getRegion().
begin();
6865 moduleTranslation.
mapValue(*atomicUpdateOp.getRegion().args_begin(),
6867 moduleTranslation.
mapBlock(&bb, builder.GetInsertBlock());
6868 if (failed(moduleTranslation.
convertBlock(bb,
true, builder)))
6869 return llvm::make_error<PreviouslyReportedError>();
6871 omp::YieldOp yieldop = dyn_cast<omp::YieldOp>(bb.
getTerminator());
6872 assert(yieldop && yieldop.getResults().size() == 1 &&
6873 "terminator must be omp.yield op and it must have exactly one "
6875 return moduleTranslation.
lookupValue(yieldop.getResults()[0]);
6878 bool isIgnoreDenormalMode;
6879 bool isFineGrainedMemory;
6880 bool isRemoteMemory;
6882 isFineGrainedMemory, isRemoteMemory);
6885 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
6886 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
6887 ompBuilder->createAtomicCapture(
6888 ompLoc, allocaIP, llvmAtomicX, llvmAtomicV, llvmExpr, atomicOrdering,
6889 binop, updateFn, atomicUpdateOp, isPostfixUpdate, isXBinopExpr,
6890 isIgnoreDenormalMode, isFineGrainedMemory, isRemoteMemory);
6892 if (failed(
handleError(afterIP, *atomicCaptureOp)))
6895 builder.restoreIP(*afterIP);
6917 llvm::IRBuilderBase &builder,
6923 Region ®ion = atomicCompareOp.getRegion();
6927 llvm::Type *llvmXElementType =
6929 if (!llvmXElementType)
6930 return atomicCompareOp.emitError(
6931 "unable to determine element type for atomic compare");
6933 llvm::Value *llvmX = moduleTranslation.
lookupValue(atomicCompareOp.getX());
6938 bool isSigned =
false;
6939 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {llvmX, llvmXElementType,
6943 llvm::AtomicOrdering atomicOrdering =
6946 auto isAtomicComparePatternOp = [](
Operation &op) {
6947 return llvm::isa<LLVM::ICmpOp, LLVM::FCmpOp, LLVM::SelectOp, LLVM::AndOp,
6948 LLVM::OrOp, LLVM::SMaxOp, LLVM::SMinOp, LLVM::UMaxOp,
6949 LLVM::UMinOp, LLVM::MaxNumOp, LLVM::MinNumOp,
6950 mlir::arith::MaxSIOp, mlir::arith::MinSIOp,
6951 mlir::arith::MaxUIOp, mlir::arith::MinUIOp,
6952 mlir::arith::MaximumFOp, mlir::arith::MinimumFOp>(op);
6972 if (isAtomicComparePatternOp(op))
6977 return moduleTranslation.lookupValue(v) != nullptr;
6979 if (!allOperandsMapped)
6983 return atomicCompareOp.emitError(
6984 "failed to translate operation inside atomic compare region");
6989 auto materializeValue = [&](
mlir::Value val) -> llvm::Value * {
6991 if (llvm::Value *existing = moduleTranslation.
lookupValue(val))
6995 if (
auto loadOp = val.getDefiningOp<LLVM::LoadOp>()) {
6996 if (loadOp->getParentRegion() == ®ion) {
6997 llvm::Value *loadAddr = moduleTranslation.
lookupValue(loadOp.getAddr());
7000 llvm::Type *loadType =
7001 moduleTranslation.
convertType(loadOp.getResult().getType());
7002 return builder.CreateLoad(loadType, loadAddr);
7010 llvm::omp::OMPAtomicCompareOp compareOp = llvm::omp::OMPAtomicCompareOp::EQ;
7011 llvm::Value *eVal =
nullptr;
7012 llvm::Value *dVal =
nullptr;
7013 bool isXBinopExpr =
false;
7019 if (isComplexPattern) {
7022 return atomicCompareOp.emitError(
7023 "unsupported comparison predicate (NE) for complex atomic compare");
7024 compareOp = llvm::omp::OMPAtomicCompareOp::EQ;
7029 if (isComplexPattern) {
7032 if (
auto selectOp = dyn_cast<LLVM::SelectOp>(op)) {
7033 dVal = materializeValue(selectOp.getTrueValue());
7039 if (yieldOp.getResults().empty())
7040 return atomicCompareOp.emitError(
7041 "failed to extract desired value (d) from atomic compare region");
7042 dVal = materializeValue(yieldOp.getResults()[0]);
7045 llvm::Value *oldComplex =
nullptr;
7046 llvm::Value *cmpOk =
nullptr;
7047 llvm::AtomicOrdering failOrdering =
7050 atomicOrdering, failOrdering,
7051 atomicCompareOp.getWeak(), oldComplex, cmpOk);
7057 if (atomicOrdering == llvm::AtomicOrdering::Release ||
7058 atomicOrdering == llvm::AtomicOrdering::AcquireRelease ||
7059 atomicOrdering == llvm::AtomicOrdering::SequentiallyConsistent) {
7060 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
7061 ompBuilder->createFlush(ompLoc);
7067 atomicCompareOp, patternInfo)))
7070 eVal = patternInfo.
eVal;
7071 dVal = patternInfo.
dVal;
7077 return atomicCompareOp.emitError(
7078 "failed to extract expected value (e) from atomic compare region");
7082 if (yieldOp.getResults().empty())
7083 return atomicCompareOp.emitError(
7084 "failed to extract desired value (d) from atomic compare region");
7085 dVal = materializeValue(yieldOp.getResults()[0]);
7088 llvmAtomicX.IsSigned = isSigned;
7090 llvm::OpenMPIRBuilder::AtomicOpValue vOpVal = {
nullptr,
nullptr,
false,
7092 llvm::OpenMPIRBuilder::AtomicOpValue rOpVal = {
nullptr,
nullptr,
false,
7094 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
7096 bool isWeak = atomicCompareOp.getWeak();
7098 bool savedHandleFPNegZero = ompBuilder->setHandleFPNegZero(
true);
7099 llvm::AtomicOrdering failureOrdering =
7101 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
7102 ompBuilder->createAtomicCompare(
7103 ompLoc, llvmAtomicX, vOpVal, rOpVal, eVal, dVal, atomicOrdering,
7104 compareOp, isXBinopExpr,
false,
7105 false, failureOrdering, isWeak);
7106 ompBuilder->setHandleFPNegZero(savedHandleFPNegZero);
7108 if (failed(
handleError(afterIP, *atomicCompareOp)))
7111 builder.restoreIP(*afterIP);
7116 omp::ClauseCancellationConstructType directive) {
7117 switch (directive) {
7118 case omp::ClauseCancellationConstructType::Loop:
7119 return llvm::omp::Directive::OMPD_for;
7120 case omp::ClauseCancellationConstructType::Parallel:
7121 return llvm::omp::Directive::OMPD_parallel;
7122 case omp::ClauseCancellationConstructType::Sections:
7123 return llvm::omp::Directive::OMPD_sections;
7124 case omp::ClauseCancellationConstructType::Taskgroup:
7125 return llvm::omp::Directive::OMPD_taskgroup;
7127 llvm_unreachable(
"Unhandled cancellation construct type");
7136 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
7139 llvm::Value *ifCond =
nullptr;
7140 if (
Value ifVar = op.getIfExpr())
7143 llvm::omp::Directive cancelledDirective =
7146 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
7147 ompBuilder->createCancel(ompLoc, ifCond, cancelledDirective);
7149 if (failed(
handleError(afterIP, *op.getOperation())))
7152 builder.restoreIP(afterIP.get());
7159 llvm::IRBuilderBase &builder,
7164 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
7167 llvm::omp::Directive cancelledDirective =
7170 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
7171 ompBuilder->createCancellationPoint(ompLoc, cancelledDirective);
7173 if (failed(
handleError(afterIP, *op.getOperation())))
7176 builder.restoreIP(afterIP.get());
7186 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
7188 auto threadprivateOp = cast<omp::ThreadprivateOp>(opInst);
7193 Value symAddr = threadprivateOp.getSymAddr();
7196 if (
auto asCast = dyn_cast<LLVM::AddrSpaceCastOp>(symOp))
7199 if (!isa<LLVM::AddressOfOp>(symOp))
7200 return opInst.
emitError(
"Addressing symbol not found");
7201 LLVM::AddressOfOp addressOfOp = dyn_cast<LLVM::AddressOfOp>(symOp);
7203 LLVM::GlobalOp global =
7204 addressOfOp.getGlobal(moduleTranslation.
symbolTable());
7205 llvm::GlobalValue *globalValue = moduleTranslation.
lookupGlobal(global);
7206 llvm::Type *type = globalValue->getValueType();
7207 llvm::TypeSize typeSize = builder.getDataLayout().getTypeStoreSize(type);
7208 llvm::ConstantInt *size = builder.getInt64(typeSize.getFixedValue());
7209 llvm::Value *callInst = ompBuilder->createCachedThreadPrivate(
7210 ompLoc, globalValue, size, global.getSymName() +
".cache");
7216static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind
7218 switch (deviceClause) {
7219 case mlir::omp::DeclareTargetDeviceType::host:
7220 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseHost;
7222 case mlir::omp::DeclareTargetDeviceType::nohost:
7223 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNoHost;
7225 case mlir::omp::DeclareTargetDeviceType::any:
7226 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny;
7229 llvm_unreachable(
"unhandled device clause");
7232static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind
7234 mlir::omp::DeclareTargetCaptureClause captureClause) {
7235 switch (captureClause) {
7236 case mlir::omp::DeclareTargetCaptureClause::to:
7237 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo;
7238 case mlir::omp::DeclareTargetCaptureClause::link:
7239 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink;
7240 case mlir::omp::DeclareTargetCaptureClause::enter:
7241 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter;
7242 case mlir::omp::DeclareTargetCaptureClause::none:
7243 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
7245 llvm_unreachable(
"unhandled capture clause");
7250 if (
auto addrCast = dyn_cast_if_present<LLVM::AddrSpaceCastOp>(op))
7252 if (
auto addressOfOp = dyn_cast_if_present<LLVM::AddressOfOp>(op)) {
7253 auto modOp = addressOfOp->getParentOfType<mlir::ModuleOp>();
7254 return modOp.lookupSymbol(addressOfOp.getGlobalName());
7261 if (
auto addrCast = dyn_cast_if_present<LLVM::AddrSpaceCastOp>(op))
7262 value = addrCast.getOperand();
7286 if (!llvmVarTy->isPointerTy())
7290 if (
auto gop = dyn_cast<LLVM::GlobalOp>(globalOp))
7291 return moduleTranslation.
convertType(gop.getGlobalType());
7294 dyn_cast_if_present<LLVM::AllocaOp>(baseVar.
getDefiningOp()))
7295 return moduleTranslation.
convertType(allocaOp.getElemType());
7297 if (llvm::Value *baseLlvm = moduleTranslation.
lookupValue(baseVar))
7298 if (
auto *allocaInst = dyn_cast<llvm::AllocaInst>(baseLlvm))
7299 return allocaInst->getAllocatedType();
7308 llvm::IRBuilderBase &builder,
const llvm::DataLayout &dataLayout) {
7310 dyn_cast_if_present<LLVM::AllocaOp>(baseVar.
getDefiningOp())) {
7311 if (
Value arraySize = allocaOp.getArraySize()) {
7312 llvm::Type *elemTy =
7313 moduleTranslation.
convertType(allocaOp.getElemType());
7314 llvm::Value *numElems = moduleTranslation.
lookupValue(arraySize);
7315 if (!numElems->getType()->isIntegerTy(64))
7316 numElems = builder.CreateZExt(numElems, builder.getInt64Ty());
7317 uint64_t elemSize = dataLayout.getTypeAllocSize(elemTy).getFixedValue();
7318 return builder.CreateMul(numElems, builder.getInt64(elemSize));
7321 if (llvm::Value *baseLlvm = moduleTranslation.
lookupValue(baseVar)) {
7322 if (
auto *allocaInst = dyn_cast<llvm::AllocaInst>(baseLlvm)) {
7323 if (allocaInst->isArrayAllocation() &&
7324 !llvm::isa<llvm::ArrayType>(allocaInst->getAllocatedType())) {
7326 dataLayout.getTypeAllocSize(allocaInst->getAllocatedType())
7328 return builder.CreateMul(allocaInst->getArraySize(),
7329 builder.getInt64(elemSize));
7333 return std::nullopt;
7336static llvm::SmallString<64>
7338 llvm::OpenMPIRBuilder &ompBuilder,
7339 llvm::vfs::FileSystem &vfs) {
7341 llvm::raw_svector_ostream os(suffix);
7344 auto fileInfoCallBack = [&loc]() {
7345 return std::pair<std::string, uint64_t>(
7346 llvm::StringRef(loc.getFilename()), loc.getLine());
7351 ompBuilder.getTargetEntryUniqueInfo(fileInfoCallBack, vfs).FileID);
7353 os <<
"_decl_tgt_ref_ptr";
7359 if (
auto declareTargetGlobal =
7360 dyn_cast_if_present<omp::DeclareTargetInterface>(
7362 omp::DeclareTargetAttr declareTargetAttr =
7363 declareTargetGlobal.getDeclareTarget();
7364 if (declareTargetAttr && declareTargetAttr.getCaptureClause() ==
7365 omp::DeclareTargetCaptureClause::link)
7372 if (
auto declareTargetGlobal =
7373 dyn_cast_if_present<omp::DeclareTargetInterface>(
7375 omp::DeclareTargetAttr declareTargetAttr =
7376 declareTargetGlobal.getDeclareTarget();
7377 if (declareTargetAttr && (declareTargetAttr.getCaptureClause() ==
7378 omp::DeclareTargetCaptureClause::to ||
7379 declareTargetAttr.getCaptureClause() ==
7380 omp::DeclareTargetCaptureClause::enter))
7399 ompBuilder->Config.hasRequiresUnifiedSharedMemory())) {
7403 if (gOp.getSymName().contains(suffix))
7408 (gOp.getSymName().str() + suffix.str()).str());
7416struct MapInfosTy : llvm::OpenMPIRBuilder::MapInfosTy {
7417 SmallVector<Operation *, 4> Mappers;
7420 void append(MapInfosTy &curInfo) {
7421 Mappers.append(curInfo.Mappers.begin(), curInfo.Mappers.end());
7422 llvm::OpenMPIRBuilder::MapInfosTy::append(curInfo);
7431struct MapInfoData : MapInfosTy {
7432 llvm::SmallVector<bool, 4> IsDeclareTarget;
7433 llvm::SmallVector<bool, 4> IsAMember;
7435 llvm::SmallVector<bool, 4> IsAMapping;
7436 llvm::SmallVector<mlir::Operation *, 4> MapClause;
7437 llvm::SmallVector<llvm::Value *, 4> OriginalValue;
7440 llvm::SmallVector<llvm::Type *, 4> BaseType;
7443 void append(MapInfoData &CurInfo) {
7444 IsDeclareTarget.append(CurInfo.IsDeclareTarget.begin(),
7445 CurInfo.IsDeclareTarget.end());
7446 MapClause.append(CurInfo.MapClause.begin(), CurInfo.MapClause.end());
7447 OriginalValue.append(CurInfo.OriginalValue.begin(),
7448 CurInfo.OriginalValue.end());
7449 BaseType.append(CurInfo.BaseType.begin(), CurInfo.BaseType.end());
7450 MapInfosTy::append(CurInfo);
7454enum class TargetDirectiveEnumTy : uint32_t {
7458 TargetEnterData = 3,
7463static TargetDirectiveEnumTy getTargetDirectiveEnumTyFromOp(Operation *op) {
7464 return llvm::TypeSwitch<Operation *, TargetDirectiveEnumTy>(op)
7465 .Case([](omp::TargetDataOp) {
return TargetDirectiveEnumTy::TargetData; })
7466 .Case([](omp::TargetEnterDataOp) {
7467 return TargetDirectiveEnumTy::TargetEnterData;
7469 .Case([&](omp::TargetExitDataOp) {
7470 return TargetDirectiveEnumTy::TargetExitData;
7472 .Case([&](omp::TargetUpdateOp) {
7473 return TargetDirectiveEnumTy::TargetUpdate;
7475 .Case([&](omp::TargetOp) {
return TargetDirectiveEnumTy::Target; })
7476 .Default([&](Operation *op) {
return TargetDirectiveEnumTy::None; });
7482 if (
auto nestedArrTy = llvm::dyn_cast_if_present<LLVM::LLVMArrayType>(
7483 arrTy.getElementType()))
7497 if (mapOp.getVarPtrPtr())
7514 return bitEnumContainsAll(mapType, omp::ClauseMapFlags::priv |
7515 omp::ClauseMapFlags::target_param |
7516 omp::ClauseMapFlags::attach);
7531 llvm::Value *basePointer,
7532 llvm::Type *baseType,
7533 llvm::IRBuilderBase &builder,
7535 if (
auto memberClause =
7536 mlir::dyn_cast_if_present<mlir::omp::MapInfoOp>(clauseOp)) {
7541 if (!memberClause.getBounds().empty()) {
7542 llvm::Value *elementCount = builder.getInt64(1);
7543 for (
auto bounds : memberClause.getBounds()) {
7544 if (
auto boundOp = mlir::dyn_cast_if_present<mlir::omp::MapBoundsOp>(
7545 bounds.getDefiningOp())) {
7550 elementCount = builder.CreateMul(
7554 moduleTranslation.
lookupValue(boundOp.getUpperBound()),
7555 moduleTranslation.
lookupValue(boundOp.getLowerBound())),
7556 builder.getInt64(1)));
7563 if (
auto arrTy = llvm::dyn_cast_if_present<LLVM::LLVMArrayType>(type))
7571 llvm::Value *sizeCalc = builder.CreateMul(
7572 elementCount, builder.getInt64(underlyingTypeSzInBits / 8),
7610 return builder.CreateSelect(
7611 builder.CreateICmpEQ(sizeCalc, builder.getInt64(0)),
7612 builder.getInt64(1), sizeCalc);
7626static llvm::omp::OpenMPOffloadMappingFlags
7628 const bool hasExplicitMap =
7629 (mlirFlags &
~omp::ClauseMapFlags::is_device_ptr) !=
7630 omp::ClauseMapFlags::none;
7632 llvm::omp::OpenMPOffloadMappingFlags mapType =
7633 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7635 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::to))
7636 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
7638 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::from))
7639 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7641 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::always))
7642 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
7644 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::del))
7645 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
7647 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::return_param))
7648 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
7650 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::priv))
7651 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRIVATE;
7653 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::literal))
7654 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL;
7656 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::implicit))
7657 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
7659 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::close))
7660 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
7662 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::present))
7663 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
7665 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::ompx_hold))
7666 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
7668 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::attach))
7669 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH;
7671 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::target_param))
7672 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7674 if (bitEnumContainsAll(mlirFlags, omp::ClauseMapFlags::is_device_ptr)) {
7675 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7676 if (!hasExplicitMap)
7677 mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL;
7684 if (StringAttr name = mapOp.getNameAttr())
7685 return name.getValue();
7693 ArrayRef<Value> useDevAddrOperands = {},
7694 ArrayRef<Value> hasDevAddrOperands = {}) {
7696 auto checkRefPtrOrPteeMapWithAttach = [](omp::ClauseMapFlags mapType) {
7698 bitEnumContainsAll(mapType, omp::ClauseMapFlags::ref_ptr) ||
7699 bitEnumContainsAll(mapType, omp::ClauseMapFlags::ref_ptee);
7700 return hasRefType &&
7701 bitEnumContainsAll(mapType, omp::ClauseMapFlags::attach);
7704 auto checkIsAMember = [](
const auto &mapVars,
auto mapOp) {
7712 for (Value mapValue : mapVars) {
7713 auto map = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
7714 for (
auto member : map.getMembers())
7715 if (member == mapOp)
7722 for (Value mapValue : mapVars) {
7723 auto mapOp = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
7724 bool isAttachStyleMap =
7725 checkRefPtrOrPteeMapWithAttach(mapOp.getMapType()) ||
7727 Value offloadPtr = (mapOp.getVarPtrPtr() && !isAttachStyleMap)
7728 ? mapOp.getVarPtrPtr()
7729 : mapOp.getVarPtr();
7730 mapData.OriginalValue.push_back(moduleTranslation.
lookupValue(offloadPtr));
7731 mapData.Pointers.push_back(
7732 isAttachStyleMap ? moduleTranslation.
lookupValue(mapOp.getVarPtrPtr())
7733 : mapData.OriginalValue.back());
7735 if (llvm::Value *refPtr =
7737 mapData.IsDeclareTarget.push_back(
true);
7738 mapData.BasePointers.push_back(refPtr);
7740 mapData.IsDeclareTarget.push_back(
true);
7741 mapData.BasePointers.push_back(mapData.OriginalValue.back());
7743 mapData.IsDeclareTarget.push_back(
false);
7744 mapData.BasePointers.push_back(mapData.OriginalValue.back());
7750 mapData.BaseType.push_back(moduleTranslation.
convertType(
7751 mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtrType().value()
7752 : mapOp.getVarPtrType()));
7759 mlir::Type sizeType = (isAttachStyleMap || !mapOp.getVarPtrPtr())
7760 ? mapOp.getVarPtrType()
7761 : mapOp.getVarPtrPtrType().value();
7763 dl, sizeType, isAttachStyleMap ?
nullptr : mapOp,
7764 mapData.Pointers.back(), moduleTranslation.
convertType(sizeType),
7765 builder, moduleTranslation));
7766 mapData.MapClause.push_back(mapOp.getOperation());
7769 mapData.HasAttachPtr.push_back(
false);
7770 mapData.Names.push_back(LLVM::createMappingInformation(
7773 mapData.DevicePointers.push_back(llvm::OpenMPIRBuilder::DeviceInfoTy::None);
7774 if (mapOp.getMapperId())
7775 mapData.Mappers.push_back(
7777 mapOp, mapOp.getMapperIdAttr()));
7779 mapData.Mappers.push_back(
nullptr);
7780 mapData.IsAMapping.push_back(
true);
7781 mapData.IsAMember.push_back(checkIsAMember(mapVars, mapOp));
7784 auto findMapInfo = [&mapData](llvm::Value *val,
7785 llvm::OpenMPIRBuilder::DeviceInfoTy devInfoTy,
7786 size_t memberCount) {
7789 for (llvm::Value *basePtr : mapData.OriginalValue) {
7790 auto mapOp = cast<omp::MapInfoOp>(mapData.MapClause[index]);
7801 (mapData.Types[index] &
7802 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH) ==
7803 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH;
7804 if (!isAttachMap && basePtr == val && mapData.IsAMapping[index] &&
7805 memberCount == mapOp.getMembers().size()) {
7807 mapData.Types[index] |=
7808 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
7809 mapData.DevicePointers[index] = devInfoTy;
7817 auto addDevInfos = [&](
const llvm::ArrayRef<Value> &useDevOperands,
7818 llvm::OpenMPIRBuilder::DeviceInfoTy devInfoTy) {
7819 for (Value mapValue : useDevOperands) {
7820 auto mapOp = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
7822 mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtr() : mapOp.getVarPtr();
7823 llvm::Value *origValue = moduleTranslation.
lookupValue(offloadPtr);
7826 if (!findMapInfo(origValue, devInfoTy, mapOp.getMembers().size())) {
7827 mapData.OriginalValue.push_back(origValue);
7828 mapData.Pointers.push_back(mapData.OriginalValue.back());
7829 mapData.IsDeclareTarget.push_back(
false);
7830 mapData.BasePointers.push_back(mapData.OriginalValue.back());
7831 mlir::Type baseTy = mapOp.getVarPtrPtr()
7832 ? mapOp.getVarPtrPtrType().value()
7833 : mapOp.getVarPtrType();
7834 mapData.BaseType.push_back(moduleTranslation.
convertType(baseTy));
7835 mapData.Sizes.push_back(builder.getInt64(0));
7836 mapData.MapClause.push_back(mapOp.getOperation());
7837 mapData.Types.push_back(
7838 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM);
7840 mapData.HasAttachPtr.push_back(
false);
7841 mapData.Names.push_back(LLVM::createMappingInformation(
7844 mapData.DevicePointers.push_back(devInfoTy);
7845 mapData.Mappers.push_back(
nullptr);
7846 mapData.IsAMapping.push_back(
false);
7847 mapData.IsAMember.push_back(checkIsAMember(useDevOperands, mapOp));
7852 addDevInfos(useDevAddrOperands, llvm::OpenMPIRBuilder::DeviceInfoTy::Address);
7853 addDevInfos(useDevPtrOperands, llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer);
7855 for (Value mapValue : hasDevAddrOperands) {
7856 auto mapOp = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
7858 mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtr() : mapOp.getVarPtr();
7859 llvm::Value *origValue = moduleTranslation.
lookupValue(offloadPtr);
7861 auto mapTypeAlways = llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
7863 (mapOp.getMapType() & omp::ClauseMapFlags::is_device_ptr) !=
7864 omp::ClauseMapFlags::none;
7866 mapData.OriginalValue.push_back(origValue);
7867 mapData.BasePointers.push_back(origValue);
7868 mapData.Pointers.push_back(origValue);
7869 mapData.IsDeclareTarget.push_back(
false);
7871 mlir::Type baseTy = mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtrType().value()
7872 : mapOp.getVarPtrType();
7873 mapData.BaseType.push_back(moduleTranslation.
convertType(baseTy));
7874 mapData.Sizes.push_back(builder.getInt64(dl.
getTypeSize(baseTy)));
7876 mapData.MapClause.push_back(mapOp.getOperation());
7877 if (llvm::to_underlying(mapType & mapTypeAlways)) {
7881 mapData.Types.push_back(mapType);
7883 mapData.HasAttachPtr.push_back(
false);
7887 if (mapOp.getMapperId()) {
7888 mapData.Mappers.push_back(
7890 mapOp, mapOp.getMapperIdAttr()));
7892 mapData.Mappers.push_back(
nullptr);
7897 mapData.Types.push_back(
7898 isDevicePtr ? mapType
7899 : llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
7901 mapData.HasAttachPtr.push_back(
false);
7902 mapData.Mappers.push_back(
nullptr);
7904 mapData.Names.push_back(LLVM::createMappingInformation(
7907 mapData.DevicePointers.push_back(
7908 isDevicePtr ? llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer
7909 : llvm::OpenMPIRBuilder::DeviceInfoTy::Address);
7910 mapData.IsAMapping.push_back(
false);
7911 mapData.IsAMember.push_back(checkIsAMember(hasDevAddrOperands, mapOp));
7916 auto *res = llvm::find(mapData.MapClause, memberOp);
7917 assert(res != mapData.MapClause.end() &&
7918 "MapInfoOp for member not found in MapData, cannot return index");
7919 return std::distance(mapData.MapClause.begin(), res);
7923 omp::MapInfoOp mapInfo,
bool first =
true) {
7924 ArrayAttr indexAttr = mapInfo.getMembersIndexAttr();
7934 auto memberIndicesA = cast<ArrayAttr>(indexAttr[a]);
7935 auto memberIndicesB = cast<ArrayAttr>(indexAttr[b]);
7937 for (auto it : llvm::zip(memberIndicesA, memberIndicesB)) {
7938 int64_t aIndex = mlir::cast<IntegerAttr>(std::get<0>(it)).getInt();
7939 int64_t bIndex = mlir::cast<IntegerAttr>(std::get<1>(it)).getInt();
7941 if (aIndex == bIndex)
7944 if (aIndex < bIndex)
7947 if (aIndex > bIndex)
7954 bool memberAParent = memberIndicesA.size() < memberIndicesB.size();
7956 occludedChildren.push_back(
b);
7958 occludedChildren.push_back(a);
7959 return memberAParent;
7962 for (
auto v : occludedChildren)
7969 ArrayAttr indexAttr = mapInfo.getMembersIndexAttr();
7971 if (indexAttr.size() == 1)
7972 return cast<omp::MapInfoOp>(mapInfo.getMembers()[0].getDefiningOp());
7976 return llvm::cast<omp::MapInfoOp>(
7977 mapInfo.getMembers()[
indices.front()].getDefiningOp());
8000static std::vector<llvm::Value *>
8002 llvm::IRBuilderBase &builder,
bool isArrayTy,
8004 std::vector<llvm::Value *> idx;
8005 isByteOffset =
false;
8016 idx.push_back(builder.getInt64(0));
8017 for (
int i = bounds.size() - 1; i >= 0; --i) {
8018 if (
auto boundOp = dyn_cast_if_present<omp::MapBoundsOp>(
8019 bounds[i].getDefiningOp())) {
8020 idx.push_back(moduleTranslation.
lookupValue(boundOp.getLowerBound()));
8025 llvm::Value *offset = builder.getInt64(0);
8026 for (
Value bound : bounds) {
8028 dyn_cast_if_present<omp::MapBoundsOp>(bound.getDefiningOp());
8029 if (!boundOp || !boundOp.getStride())
8034 isByteOffset = boundOp.getStrideInBytes();
8037 for (
Value bound : bounds) {
8039 dyn_cast_if_present<omp::MapBoundsOp>(bound.getDefiningOp());
8040 if (!boundOp || !boundOp.getStride())
8055 moduleTranslation.
lookupValue(boundOp.getLowerBound());
8056 llvm::Value *stride =
8057 moduleTranslation.
lookupValue(boundOp.getStride());
8058 offset = builder.CreateAdd(offset, builder.CreateMul(lb, stride));
8060 idx.push_back(offset);
8062 for (
int i = bounds.size() - 1; i >= 0; --i) {
8063 if (
auto boundOp = dyn_cast_if_present<omp::MapBoundsOp>(
8064 bounds[i].getDefiningOp())) {
8077 if (i == ((
int)bounds.size() - 1))
8079 moduleTranslation.
lookupValue(boundOp.getLowerBound()));
8081 idx.back() = builder.CreateAdd(
8082 builder.CreateMul(idx.back(), moduleTranslation.
lookupValue(
8083 boundOp.getExtent())),
8084 moduleTranslation.
lookupValue(boundOp.getLowerBound()));
8094 llvm::transform(values, std::back_inserter(ints), [](
Attribute value) {
8095 return cast<IntegerAttr>(value).getInt();
8103 omp::MapInfoOp parentOp) {
8105 if (parentOp.getMembers().empty())
8109 if (parentOp.getMembers().size() == 1) {
8110 overlapMapDataIdxs.push_back(0);
8114 ArrayAttr indexAttr = parentOp.getMembersIndexAttr();
8115 size_t numMembers = indexAttr.size();
8119 for (
auto [i, indicesAttr] : llvm::enumerate(indexAttr))
8120 getAsIntegers(cast<ArrayAttr>(indicesAttr), memberIndices[i]);
8126 llvm::SmallDenseSet<size_t> skipIndices;
8127 for (
size_t i = 0; i < numMembers; ++i) {
8128 const auto &iIndices = memberIndices[i];
8129 for (
size_t j = 0;
j < numMembers; ++
j) {
8132 const auto &jIndices = memberIndices[
j];
8134 if (jIndices.size() < iIndices.size() &&
8135 std::equal(jIndices.begin(), jIndices.end(), iIndices.begin())) {
8136 skipIndices.insert(i);
8143 for (
size_t i = 0; i < numMembers; ++i)
8144 if (!skipIndices.contains(i))
8145 overlapMapDataIdxs.push_back(i);
8156 llvm::IRBuilderBase &builder,
8157 MapInfoData &mapData,
size_t mapDataIdx,
8158 MapInfosTy &combinedInfo) {
8159 auto mapOp = cast<omp::MapInfoOp>(mapData.MapClause[mapDataIdx]);
8160 if (mapOp.getBounds().empty() || mapOp.getMapperId() ||
8161 mapOp->getParentOfType<omp::DeclareMapperOp>() ||
8162 bitEnumContainsAll(mapOp.getMapType(), omp::ClauseMapFlags::attach))
8165 llvm::Type *elementType = mapData.BaseType[mapDataIdx];
8170 while (
auto *arrayType = dyn_cast<llvm::ArrayType>(elementType)) {
8171 arrayExtents.push_back(arrayType->getNumElements());
8172 elementType = arrayType->getElementType();
8174 llvm::Value *elementSize = builder.getInt64(
8175 builder.GetInsertBlock()->getModule()->getDataLayout().getTypeAllocSize(
8180 llvm::OpenMPIRBuilder::MapValuesArrayTy offsets{builder.getInt64(0)};
8181 llvm::OpenMPIRBuilder::MapValuesArrayTy counts{elementSize};
8182 llvm::OpenMPIRBuilder::MapValuesArrayTy strides{builder.getInt64(1)};
8183 llvm::Value *sourceStride = elementSize;
8184 llvm::Value *contiguousSize = elementSize;
8187 bool isContiguous =
true;
8188 for (
auto [dim, bound] : llvm::enumerate(mapOp.getBounds())) {
8189 auto bounds = cast<omp::MapBoundsOp>(bound.getDefiningOp());
8190 auto getInt64 = [&](
Value value) {
8191 return builder.CreateSExtOrTrunc(moduleTranslation.
lookupValue(value),
8192 builder.getInt64Ty());
8194 llvm::Value *lower = bounds.getLowerBound()
8195 ? getInt64(bounds.getLowerBound())
8196 : builder.getInt64(0);
8197 llvm::Value *count = builder.CreateAdd(
8198 builder.CreateSub(getInt64(bounds.getUpperBound()), lower),
8199 builder.getInt64(1));
8201 builder.CreateSelect(builder.CreateICmpSGT(count, builder.getInt64(0)),
8202 count, builder.getInt64(0));
8203 llvm::Value *stride = sourceStride;
8204 if (bounds.getStrideInBytes() && bounds.getStride())
8205 stride = getInt64(bounds.getStride());
8206 else if (arrayExtents.empty() && bounds.getStride())
8207 stride = builder.CreateMul(getInt64(bounds.getStride()), elementSize);
8208 offsets.push_back(builder.CreateMul(lower, stride));
8209 counts.push_back(count);
8210 strides.push_back(stride);
8211 isContiguous &= stride == contiguousSize;
8212 contiguousSize = builder.CreateMul(contiguousSize, count);
8217 if (dim < arrayExtents.size())
8218 sourceStride = builder.CreateMul(
8220 builder.getInt64(arrayExtents[arrayExtents.size() - dim - 1]));
8221 else if (bounds.getExtent())
8223 builder.CreateMul(sourceStride, getInt64(bounds.getExtent()));
8228 llvm::Value *base = mapData.OriginalValue[mapDataIdx];
8229 if (mapOp.getVarPtrPtr())
8230 base = builder.CreateLoad(builder.getPtrTy(), base);
8233 counts[1] = builder.CreateSelect(builder.CreateIsNull(base),
8234 builder.getInt64(0), counts[1]);
8237 combinedInfo.BasePointers.back() = base;
8238 combinedInfo.Types.back() |=
8239 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG;
8240 auto &nonContig = combinedInfo.NonContigInfo;
8241 nonContig.IsNonContiguous =
true;
8242 nonContig.Dims.resize(combinedInfo.Types.size(), 1);
8243 nonContig.Dims.back() = counts.size();
8244 nonContig.Offsets.push_back(std::move(offsets));
8245 nonContig.Counts.push_back(std::move(counts));
8246 nonContig.Strides.push_back(std::move(strides));
8260 llvm::OpenMPIRBuilder &ompBuilder, MapInfoData &mapData,
size_t mapDataIdx,
8261 MapInfosTy &combinedInfo, TargetDirectiveEnumTy targetDirective,
8262 llvm::omp::OpenMPOffloadMappingFlags memberOfFlag =
8263 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE,
8264 bool isTargetParam =
true,
int mapDataParentIdx = -1) {
8265 auto mapFlag = mapData.Types[mapDataIdx];
8266 auto mapInfoOp = llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIdx]);
8270 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH) ==
8271 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
8277 if (isTargetParam &&
8278 (targetDirective == TargetDirectiveEnumTy::Target &&
8279 !mapData.IsDeclareTarget[mapDataIdx]) &&
8281 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
8283 if (mapInfoOp.getMapCaptureType() == omp::VariableCaptureKind::ByCopy &&
8285 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL;
8294 if (memberOfFlag != llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE) {
8295 if (!isPtrTy && !isAttachMap)
8296 ompBuilder.setCorrectMemberOfFlag(mapFlag, memberOfFlag);
8303 mapFlag &=
~llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
8313 if (isPtrTy && !isAttachMap && mapData.IsDeclareTarget[mapDataIdx])
8314 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
8323 !bitEnumContainsAll(mapInfoOp.getMapType(),
8324 omp::ClauseMapFlags::ref_ptr) &&
8325 bitEnumContainsAll(mapInfoOp.getMapType(), omp::ClauseMapFlags::ref_ptee);
8326 bool isRefPtrPtee = bitEnumContainsAll(mapInfoOp.getMapType(),
8327 omp::ClauseMapFlags::ref_ptr |
8328 omp::ClauseMapFlags::ref_ptee);
8330 if (!mapInfoOp->getParentOfType<omp::DeclareMapperOp>() &&
8331 mapDataParentIdx >= 0 && !(isRefPtee || (isRefPtrPtee && isPtrTy))) {
8332 combinedInfo.BasePointers.emplace_back(
8333 mapData.BasePointers[mapDataParentIdx]);
8335 combinedInfo.BasePointers.emplace_back(mapData.BasePointers[mapDataIdx]);
8338 combinedInfo.Pointers.emplace_back(mapData.Pointers[mapDataIdx]);
8339 combinedInfo.DevicePointers.emplace_back(
8340 memberOfFlag != llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE
8341 ? llvm::OpenMPIRBuilder::DeviceInfoTy::None
8342 : mapData.DevicePointers[mapDataIdx]);
8343 combinedInfo.Mappers.emplace_back(mapData.Mappers[mapDataIdx]);
8344 combinedInfo.Names.emplace_back(mapData.Names[mapDataIdx]);
8345 combinedInfo.Types.emplace_back(mapFlag);
8347 combinedInfo.HasAttachPtr.emplace_back(
false);
8351 combinedInfo.Sizes.emplace_back(
8353 ? builder.CreateSelect(
8354 builder.CreateIsNull(mapData.Pointers[mapDataIdx]),
8355 builder.getInt64(0), mapData.Sizes[mapDataIdx])
8356 : mapData.Sizes[mapDataIdx]);
8357 if (targetDirective == TargetDirectiveEnumTy::TargetUpdate)
8379 llvm::OpenMPIRBuilder &ompBuilder,
DataLayout &dl, MapInfosTy &combinedInfo,
8380 MapInfoData &mapData, uint64_t mapDataIndex,
8381 llvm::omp::OpenMPOffloadMappingFlags memberOfFlag,
8382 TargetDirectiveEnumTy targetDirective) {
8383 using MapFlags = llvm::omp::OpenMPOffloadMappingFlags;
8384 assert(!ompBuilder.Config.isTargetDevice() &&
8385 "function only supported for host device codegen");
8387 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
8388 auto *parentMapper = mapData.Mappers[mapDataIndex];
8394 MapFlags baseFlag = (targetDirective == TargetDirectiveEnumTy::Target &&
8395 !mapData.IsDeclareTarget[mapDataIndex])
8396 ? MapFlags::OMP_MAP_TARGET_PARAM
8397 : MapFlags::OMP_MAP_NONE;
8403 MapFlags parentFlags = mapData.Types[mapDataIndex];
8404 MapFlags preserve = MapFlags::OMP_MAP_TO | MapFlags::OMP_MAP_FROM |
8405 MapFlags::OMP_MAP_ALWAYS | MapFlags::OMP_MAP_CLOSE |
8406 MapFlags::OMP_MAP_PRESENT |
8407 MapFlags::OMP_MAP_OMPX_HOLD |
8408 MapFlags::OMP_MAP_IMPLICIT;
8409 baseFlag |= (parentFlags & preserve);
8411 MapFlags parentFlags = mapData.Types[mapDataIndex];
8412 MapFlags preserve = MapFlags::OMP_MAP_TO | MapFlags::OMP_MAP_FROM |
8413 MapFlags::OMP_MAP_PRESENT |
8414 MapFlags::OMP_MAP_RETURN_PARAM |
8415 MapFlags::OMP_MAP_IMPLICIT;
8416 baseFlag |= (parentFlags & preserve);
8419 combinedInfo.Types.emplace_back(baseFlag);
8421 combinedInfo.HasAttachPtr.emplace_back(
false);
8422 combinedInfo.DevicePointers.emplace_back(
8423 mapData.DevicePointers[mapDataIndex]);
8427 combinedInfo.Mappers.emplace_back(
8428 parentMapper && !parentClause.getPartialMap() ? parentMapper :
nullptr);
8430 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder,
8432 combinedInfo.BasePointers.emplace_back(mapData.BasePointers[mapDataIndex]);
8441 llvm::Value *lowAddr, *highAddr;
8442 if (!parentClause.getPartialMap()) {
8443 lowAddr = builder.CreatePointerCast(mapData.Pointers[mapDataIndex],
8444 builder.getPtrTy());
8445 highAddr = builder.CreatePointerCast(
8446 builder.CreateConstGEP1_32(mapData.BaseType[mapDataIndex],
8447 mapData.Pointers[mapDataIndex], 1),
8448 builder.getPtrTy());
8449 combinedInfo.Pointers.emplace_back(mapData.Pointers[mapDataIndex]);
8451 auto mapOp = dyn_cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
8454 lowAddr = builder.CreatePointerCast(mapData.BasePointers[firstMemberIdx],
8455 builder.getPtrTy());
8459 auto lastMemberMapInfo =
8460 cast<omp::MapInfoOp>(mapData.MapClause[lastMemberIdx]);
8469 bool isRefPteeMap = bitEnumContainsAll(lastMemberMapInfo.getMapType(),
8470 omp::ClauseMapFlags::ref_ptee) &&
8471 !bitEnumContainsAll(lastMemberMapInfo.getMapType(),
8472 omp::ClauseMapFlags::ref_ptr);
8473 llvm::Type *castType = mapData.BaseType[lastMemberIdx];
8476 moduleTranslation.
convertType(lastMemberMapInfo.getVarPtrType());
8477 highAddr = builder.CreatePointerCast(
8478 builder.CreateGEP(castType, mapData.BasePointers[lastMemberIdx],
8479 builder.getInt64(1)),
8480 builder.getPtrTy());
8481 combinedInfo.Pointers.emplace_back(mapData.BasePointers[firstMemberIdx]);
8484 llvm::Value *size = builder.CreateIntCast(
8485 builder.CreatePtrDiff(builder.getInt8Ty(), highAddr, lowAddr),
8486 builder.getInt64Ty(),
8488 combinedInfo.Sizes.push_back(size);
8496 if (!parentClause.getPartialMap()) {
8501 MapFlags mapFlag = mapData.Types[mapDataIndex];
8502 bool hasMapClose = (MapFlags(mapFlag) & MapFlags::OMP_MAP_CLOSE) ==
8503 MapFlags::OMP_MAP_CLOSE;
8504 ompBuilder.setCorrectMemberOfFlag(mapFlag, memberOfFlag);
8520 if (targetDirective == TargetDirectiveEnumTy::TargetUpdate || hasMapClose ||
8521 overlapIdxs.size() == 1) {
8522 combinedInfo.Types.emplace_back(mapFlag);
8524 combinedInfo.HasAttachPtr.emplace_back(
false);
8525 combinedInfo.DevicePointers.emplace_back(
8526 mapData.DevicePointers[mapDataIndex]);
8528 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder,
8530 cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]))));
8531 combinedInfo.BasePointers.emplace_back(
8532 mapData.BasePointers[mapDataIndex]);
8533 combinedInfo.Pointers.emplace_back(mapData.Pointers[mapDataIndex]);
8534 combinedInfo.Sizes.emplace_back(mapData.Sizes[mapDataIndex]);
8535 combinedInfo.Mappers.emplace_back(
nullptr);
8541 lowAddr = builder.CreatePointerCast(mapData.Pointers[mapDataIndex],
8542 builder.getPtrTy());
8543 highAddr = builder.CreatePointerCast(
8544 builder.CreateConstGEP1_32(mapData.BaseType[mapDataIndex],
8545 mapData.Pointers[mapDataIndex], 1),
8546 builder.getPtrTy());
8553 mapFlag &=
~llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
8560 for (
auto v : overlapIdxs) {
8563 cast<omp::MapInfoOp>(parentClause.getMembers()[v].getDefiningOp()));
8565 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataOverlapIdx]));
8566 combinedInfo.Types.emplace_back(mapFlag);
8568 combinedInfo.HasAttachPtr.emplace_back(
false);
8569 combinedInfo.DevicePointers.emplace_back(
8570 llvm::OpenMPIRBuilder::DeviceInfoTy::None);
8572 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder,
8574 cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]))));
8575 combinedInfo.BasePointers.emplace_back(
8576 mapData.BasePointers[mapDataIndex]);
8577 combinedInfo.Mappers.emplace_back(
nullptr);
8578 combinedInfo.Pointers.emplace_back(lowAddr);
8579 auto sizeCalc = builder.CreateIntCast(
8580 builder.CreatePtrDiff(builder.getInt8Ty(),
8581 mapData.OriginalValue[mapDataOverlapIdx],
8583 builder.getInt64Ty(),
true);
8588 llvm::DataLayout dataLayout = builder.getDataLayout();
8589 auto sizeSel = builder.CreateSelect(
8590 builder.CreateICmpNE(builder.getInt64(0), sizeCalc), sizeCalc,
8591 isPtrMap ? builder.getInt64(dataLayout.getPointerSize())
8592 : mapData.Sizes[mapDataOverlapIdx]);
8593 combinedInfo.Sizes.emplace_back(sizeSel);
8594 lowAddr = builder.CreateConstGEP1_32(
8595 isPtrMap ? builder.getPtrTy() : mapData.BaseType[mapDataOverlapIdx],
8596 mapData.BasePointers[mapDataOverlapIdx], 1);
8599 combinedInfo.Types.emplace_back(mapFlag);
8601 combinedInfo.HasAttachPtr.emplace_back(
false);
8602 combinedInfo.DevicePointers.emplace_back(
8603 llvm::OpenMPIRBuilder::DeviceInfoTy::None);
8605 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder,
8607 cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]))));
8608 combinedInfo.BasePointers.emplace_back(
8609 mapData.BasePointers[mapDataIndex]);
8610 combinedInfo.Mappers.emplace_back(
nullptr);
8611 combinedInfo.Pointers.emplace_back(lowAddr);
8612 combinedInfo.Sizes.emplace_back(builder.CreateIntCast(
8613 builder.CreatePtrDiff(builder.getInt8Ty(), highAddr, lowAddr),
8614 builder.getInt64Ty(),
true));
8620 llvm::IRBuilderBase &builder,
8621 llvm::OpenMPIRBuilder &ompBuilder,
8623 MapInfoData &mapData, uint64_t mapDataIndex,
8624 TargetDirectiveEnumTy targetDirective) {
8625 assert(!ompBuilder.Config.isTargetDevice() &&
8626 "function only supported for host device codegen");
8629 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
8634 if (parentClause.getMembers().size() == 1 && parentClause.getPartialMap()) {
8635 auto memberClause = llvm::cast<omp::MapInfoOp>(
8636 parentClause.getMembers()[0].getDefiningOp());
8649 moduleTranslation, builder, ompBuilder, mapData, memberDataIdx,
8650 combinedInfo, targetDirective,
8651 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE,
8652 true, mapDataIndex);
8656 auto collectMapInfoIdxs =
8659 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
8661 for (
auto member : parentClause.getMembers())
8663 mapData, llvm::cast<omp::MapInfoOp>(member.getDefiningOp())));
8667 collectMapInfoIdxs(mapInfoIdx);
8669 llvm::omp::OpenMPOffloadMappingFlags memberOfFlag =
8670 ompBuilder.getMemberOfFlag(combinedInfo.Types.size());
8680 bool parentIsPrivatizeableAttach =
8682 for (
auto [i, idx] : llvm::enumerate(mapInfoIdx)) {
8683 bool emitParentMap = i == 0 && !parentIsPrivatizeableAttach;
8684 if (emitParentMap) {
8686 combinedInfo, mapData, idx, memberOfFlag,
8690 moduleTranslation, builder, ompBuilder, mapData, idx, combinedInfo,
8692 parentIsPrivatizeableAttach
8693 ? llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE
8695 false, mapDataIndex);
8707 llvm::IRBuilderBase &builder) {
8709 "function only supported for host device codegen");
8710 for (
size_t i = 0; i < mapData.MapClause.size(); ++i) {
8711 auto mapOp = cast<omp::MapInfoOp>(mapData.MapClause[i]);
8714 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH) ==
8715 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
8720 if (!mapData.IsDeclareTarget[i] ||
8721 (mapData.IsDeclareTarget[i] && isAttachMap)) {
8722 omp::VariableCaptureKind captureKind = mapOp.getMapCaptureType();
8732 switch (captureKind) {
8733 case omp::VariableCaptureKind::ByRef: {
8734 llvm::Value *newV = mapData.Pointers[i];
8735 bool isByteOffset =
false;
8737 moduleTranslation, builder, mapData.BaseType[i]->isArrayTy(),
8738 mapOp.getBounds(), isByteOffset);
8740 newV = builder.CreateLoad(builder.getPtrTy(), newV);
8742 if (!offsetIdx.empty())
8743 newV = builder.CreateInBoundsGEP(isByteOffset ? builder.getInt8Ty()
8744 : mapData.BaseType[i],
8745 newV, offsetIdx,
"array_offset");
8746 mapData.Pointers[i] = newV;
8748 case omp::VariableCaptureKind::ByCopy: {
8749 llvm::Type *type = mapData.BaseType[i];
8751 if (mapData.Pointers[i]->getType()->isPointerTy())
8752 newV = builder.CreateLoad(type, mapData.Pointers[i]);
8754 newV = mapData.Pointers[i];
8757 auto curInsert = builder.saveIP();
8758 llvm::DebugLoc DbgLoc = builder.getCurrentDebugLocation();
8760 auto *memTempAlloc =
8761 builder.CreateAlloca(builder.getPtrTy(),
nullptr,
".casted");
8762 builder.SetCurrentDebugLocation(DbgLoc);
8763 builder.restoreIP(curInsert);
8765 builder.CreateStore(newV, memTempAlloc);
8766 newV = builder.CreateLoad(builder.getPtrTy(), memTempAlloc);
8769 mapData.Pointers[i] = newV;
8770 mapData.BasePointers[i] = newV;
8772 case omp::VariableCaptureKind::This:
8773 case omp::VariableCaptureKind::VLAType:
8774 mapData.MapClause[i]->emitOpError(
"Unhandled capture kind");
8785 MapInfoData &mapData,
8786 TargetDirectiveEnumTy targetDirective) {
8788 "function only supported for host device codegen");
8809 for (
size_t i = 0; i < mapData.MapClause.size(); ++i) {
8810 if (mapData.IsAMember[i])
8813 auto mapInfoOp = dyn_cast<omp::MapInfoOp>(mapData.MapClause[i]);
8814 if (!mapInfoOp.getMembers().empty()) {
8816 combinedInfo, mapData, i, targetDirective);
8821 combinedInfo, targetDirective);
8823 if (!combinedInfo.NonContigInfo.Dims.empty())
8824 combinedInfo.NonContigInfo.Dims.resize(combinedInfo.Types.size(), 1);
8827static llvm::Expected<llvm::Function *>
8829 LLVM::ModuleTranslation &moduleTranslation,
8830 llvm::StringRef mapperFuncName,
8831 TargetDirectiveEnumTy targetDirective);
8833static llvm::Expected<llvm::Function *>
8836 TargetDirectiveEnumTy targetDirective) {
8838 "function only supported for host device codegen");
8839 auto declMapperOp = cast<omp::DeclareMapperOp>(op);
8840 std::string mapperFuncName =
8842 ->createPlatformSpecificName(
8843 {
"omp_mapper", declMapperOp.getSymName()});
8845 if (
auto *lookupFunc = moduleTranslation.
lookupFunction(mapperFuncName))
8853 if (llvm::Function *existingFunc =
8854 moduleTranslation.
getLLVMModule()->getFunction(mapperFuncName)) {
8855 moduleTranslation.
mapFunction(mapperFuncName, existingFunc);
8856 return existingFunc;
8860 mapperFuncName, targetDirective);
8863static llvm::Expected<llvm::Function *>
8866 llvm::StringRef mapperFuncName,
8867 TargetDirectiveEnumTy targetDirective) {
8869 "function only supported for host device codegen");
8870 auto declMapperOp = cast<omp::DeclareMapperOp>(op);
8871 auto declMapperInfoOp = declMapperOp.getDeclareMapperInfo();
8873 return llvm::make_error<PreviouslyReportedError>();
8877 llvm::Type *varType = moduleTranslation.
convertType(declMapperOp.getType());
8880 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
8883 MapInfosTy combinedInfo;
8885 [&](InsertPointTy codeGenIP, llvm::Value *ptrPHI,
8886 llvm::Value *unused2) -> llvm::OpenMPIRBuilder::MapInfosOrErrorTy {
8887 builder.restoreIP(codeGenIP);
8888 moduleTranslation.
mapValue(declMapperOp.getSymVal(), ptrPHI);
8889 moduleTranslation.
mapBlock(&declMapperOp.getRegion().front(),
8890 builder.GetInsertBlock());
8891 if (failed(moduleTranslation.
convertBlock(declMapperOp.getRegion().front(),
8894 return llvm::make_error<PreviouslyReportedError>();
8895 MapInfoData mapData;
8898 genMapInfos(builder, moduleTranslation, dl, combinedInfo, mapData,
8904 return combinedInfo;
8908 if (!combinedInfo.Mappers[i])
8911 moduleTranslation, targetDirective);
8915 genMapInfoCB, varType, mapperFuncName, customMapperCB,
8919 return newFn.takeError();
8920 if ([[maybe_unused]] llvm::Function *mappedFunc =
8922 assert(mappedFunc == *newFn &&
8923 "mapper function mapping disagrees with emitted function");
8925 moduleTranslation.
mapFunction(mapperFuncName, *newFn);
8931 llvm::OpenMPIRBuilder &ompBuilder,
8937 llvm::Function *parentFn = builder.GetInsertBlock()->getParent();
8938 llvm::StringRef fnName = parentFn ? parentFn->getName() :
"";
8940 fileLoc, ompBuilder, fnName, strSize);
8941 return ompBuilder.getOrCreateIdent(srcStr, strSize);
8947 llvm::Value *ifCond =
nullptr;
8948 llvm::Value *deviceID = builder.getInt64(llvm::omp::OMP_DEVICEID_UNDEF);
8952 llvm::omp::RuntimeFunction RTLFn;
8954 TargetDirectiveEnumTy targetDirective = getTargetDirectiveEnumTyFromOp(op);
8957 llvm::OpenMPIRBuilder::TargetDataInfo info(
8961 if (ompBuilder->Config.isTargetDevice())
8962 return op->
emitOpError() <<
"not allowed in a target device";
8964 bool isOffloadEntry = !ompBuilder->Config.TargetTriples.empty();
8966 auto getDeviceID = [&](
mlir::Value dev) -> llvm::Value * {
8967 llvm::Value *v = moduleTranslation.
lookupValue(dev);
8968 return builder.CreateIntCast(v, builder.getInt64Ty(),
true);
8973 .Case([&](omp::TargetDataOp dataOp) {
8977 if (
auto ifVar = dataOp.getIfExpr())
8981 deviceID = getDeviceID(devId);
8983 mapVars = dataOp.getMapVars();
8984 useDevicePtrVars = dataOp.getUseDevicePtrVars();
8985 useDeviceAddrVars = dataOp.getUseDeviceAddrVars();
8988 .Case([&](omp::TargetEnterDataOp enterDataOp) -> LogicalResult {
8992 if (
auto ifVar = enterDataOp.getIfExpr())
8996 deviceID = getDeviceID(devId);
8999 enterDataOp.getNowait()
9000 ? llvm::omp::OMPRTL___tgt_target_data_begin_nowait_mapper
9001 : llvm::omp::OMPRTL___tgt_target_data_begin_mapper;
9002 mapVars = enterDataOp.getMapVars();
9003 info.HasNoWait = enterDataOp.getNowait();
9006 .Case([&](omp::TargetExitDataOp exitDataOp) -> LogicalResult {
9010 if (
auto ifVar = exitDataOp.getIfExpr())
9014 deviceID = getDeviceID(devId);
9016 RTLFn = exitDataOp.getNowait()
9017 ? llvm::omp::OMPRTL___tgt_target_data_end_nowait_mapper
9018 : llvm::omp::OMPRTL___tgt_target_data_end_mapper;
9019 mapVars = exitDataOp.getMapVars();
9020 info.HasNoWait = exitDataOp.getNowait();
9023 .Case([&](omp::TargetUpdateOp updateDataOp) -> LogicalResult {
9027 if (
auto ifVar = updateDataOp.getIfExpr())
9031 deviceID = getDeviceID(devId);
9034 updateDataOp.getNowait()
9035 ? llvm::omp::OMPRTL___tgt_target_data_update_nowait_mapper
9036 : llvm::omp::OMPRTL___tgt_target_data_update_mapper;
9037 mapVars = updateDataOp.getMapVars();
9038 info.HasNoWait = updateDataOp.getNowait();
9041 .DefaultUnreachable(
"unexpected operation");
9046 if (!isOffloadEntry)
9047 ifCond = builder.getFalse();
9049 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
9050 MapInfoData mapData;
9052 builder, useDevicePtrVars, useDeviceAddrVars);
9055 MapInfosTy combinedInfo;
9056 auto genMapInfoCB = [&](InsertPointTy codeGenIP) -> MapInfosTy & {
9057 builder.restoreIP(codeGenIP);
9058 genMapInfos(builder, moduleTranslation, DL, combinedInfo, mapData,
9060 return combinedInfo;
9066 [&moduleTranslation](
9067 llvm::OpenMPIRBuilder::DeviceInfoTy type,
9071 for (
auto [arg, useDevVar] :
9072 llvm::zip_equal(blockArgs, useDeviceVars)) {
9074 auto getMapBasePtr = [](omp::MapInfoOp mapInfoOp) {
9075 return mapInfoOp.getVarPtrPtr() ? mapInfoOp.getVarPtrPtr()
9076 : mapInfoOp.getVarPtr();
9079 auto useDevMap = cast<omp::MapInfoOp>(useDevVar.getDefiningOp());
9080 for (
auto [mapClause, devicePointer, basePointer] : llvm::zip_equal(
9081 mapInfoData.MapClause, mapInfoData.DevicePointers,
9082 mapInfoData.BasePointers)) {
9083 auto mapOp = cast<omp::MapInfoOp>(mapClause);
9084 if (getMapBasePtr(mapOp) != getMapBasePtr(useDevMap) ||
9085 devicePointer != type)
9088 if (llvm::Value *devPtrInfoMap =
9089 mapper ? mapper(basePointer) : basePointer) {
9090 moduleTranslation.
mapValue(arg, devPtrInfoMap);
9097 using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy;
9098 auto bodyGenCB = [&](InsertPointTy codeGenIP, BodyGenTy bodyGenType)
9099 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
9102 builder.restoreIP(codeGenIP);
9103 assert(isa<omp::TargetDataOp>(op) &&
9104 "BodyGen requested for non TargetDataOp");
9105 auto blockArgIface = cast<omp::BlockArgOpenMPOpInterface>(op);
9106 Region ®ion = cast<omp::TargetDataOp>(op).getRegion();
9107 switch (bodyGenType) {
9108 case BodyGenTy::Priv:
9110 if (!info.DevicePtrInfoMap.empty()) {
9111 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Address,
9112 blockArgIface.getUseDeviceAddrBlockArgs(),
9113 useDeviceAddrVars, mapData,
9114 [&](llvm::Value *basePointer) -> llvm::Value * {
9115 if (!info.DevicePtrInfoMap[basePointer].second)
9117 return builder.CreateLoad(
9119 info.DevicePtrInfoMap[basePointer].second);
9121 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer,
9122 blockArgIface.getUseDevicePtrBlockArgs(), useDevicePtrVars,
9123 mapData, [&](llvm::Value *basePointer) {
9124 return info.DevicePtrInfoMap[basePointer].second;
9128 moduleTranslation)))
9129 return llvm::make_error<PreviouslyReportedError>();
9132 case BodyGenTy::DupNoPriv:
9133 if (info.DevicePtrInfoMap.empty()) {
9136 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Address,
9137 blockArgIface.getUseDeviceAddrBlockArgs(),
9138 useDeviceAddrVars, mapData);
9139 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer,
9140 blockArgIface.getUseDevicePtrBlockArgs(), useDevicePtrVars,
9144 case BodyGenTy::NoPriv:
9146 if (info.DevicePtrInfoMap.empty()) {
9148 moduleTranslation)))
9149 return llvm::make_error<PreviouslyReportedError>();
9153 return builder.saveIP();
9156 auto customMapperCB =
9158 if (!combinedInfo.Mappers[i])
9160 info.HasMapper =
true;
9162 moduleTranslation, targetDirective);
9165 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
9167 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
9174 llvm::Value *srcLocOverride =
9178 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP = [&]() {
9179 if (isa<omp::TargetDataOp>(op))
9180 return ompBuilder->createTargetData(
9181 ompLoc, allocaIP, builder.saveIP(), deallocBlocks, deviceID, ifCond,
9182 info, genMapInfoCB, customMapperCB,
9184 nullptr, srcLocOverride);
9185 return ompBuilder->createTargetData(
9186 ompLoc, allocaIP, builder.saveIP(), deallocBlocks, deviceID, ifCond,
9187 info, genMapInfoCB, customMapperCB, &RTLFn,
9189 nullptr, srcLocOverride);
9195 builder.restoreIP(*afterIP);
9203 auto distributeOp = cast<omp::DistributeOp>(opInst);
9210 bool doDistributeReduction =
9214 unsigned numReductionVars = teamsOp ? teamsOp.getNumReductionVars() : 0;
9219 if (doDistributeReduction) {
9220 isByRef =
getIsByRef(teamsOp.getReductionByref());
9221 assert(isByRef.size() == teamsOp.getNumReductionVars());
9224 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
9228 llvm::cast<omp::BlockArgOpenMPOpInterface>(*teamsOp)
9229 .getReductionBlockArgs();
9232 teamsOp, reductionArgs, builder, moduleTranslation, allocaIP,
9233 reductionDecls, privateReductionVariables, reductionVariableMap,
9238 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
9240 [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
9242 llvm::BasicBlock *allocaBlock = allocaIP.getNodeParent();
9244 builder.restoreIP(codeGenIP);
9245 PrivateVarsInfo privVarsInfo(distributeOp);
9248 distributeOp, builder, moduleTranslation, privVarsInfo, allocaIP);
9250 return llvm::make_error<PreviouslyReportedError>();
9256 moduleTranslation, allocaIP.getNodeParent(), deallocBlocks);
9261 return llvm::make_error<PreviouslyReportedError>();
9264 privVarsInfo.mlirVars, privVarsInfo.llvmVars,
9265 privVarsInfo.privatizers,
9266 distributeOp.getPrivateNeedsBarrier())))
9267 return llvm::make_error<PreviouslyReportedError>();
9270 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
9273 builder, moduleTranslation);
9275 return regionBlock.takeError();
9276 builder.SetInsertPoint((*regionBlock)->begin());
9281 if (!isa_and_present<omp::WsloopOp>(distributeOp.getNestedWrapper())) {
9284 bool hasDistSchedule = distributeOp.getDistScheduleStatic();
9285 auto schedule = hasDistSchedule ? omp::ClauseScheduleKind::Distribute
9286 : omp::ClauseScheduleKind::Static;
9288 bool isOrdered = hasDistSchedule;
9289 std::optional<omp::ScheduleModifier> scheduleMod;
9290 bool isSimd =
false;
9291 llvm::omp::WorksharingLoopType workshareLoopType =
9292 llvm::omp::WorksharingLoopType::DistributeStaticLoop;
9293 bool loopNeedsBarrier =
false;
9294 llvm::Value *chunk = moduleTranslation.
lookupValue(
9295 distributeOp.getDistScheduleChunkSize());
9296 llvm::CanonicalLoopInfo *loopInfo =
9299 allocaIP = allocaBlock->getFirstInsertionPt();
9300 llvm::OpenMPIRBuilder::InsertPointOrErrorTy wsloopIP =
9301 ompBuilder->applyWorkshareLoop(
9302 ompLoc.DL, loopInfo, allocaIP, loopNeedsBarrier,
9303 convertToScheduleKind(schedule), chunk, isSimd,
9304 scheduleMod == omp::ScheduleModifier::monotonic,
9305 scheduleMod == omp::ScheduleModifier::nonmonotonic, isOrdered,
9306 workshareLoopType,
false, hasDistSchedule, chunk);
9309 return wsloopIP.takeError();
9312 distributeOp.getLoc(), privVarsInfo)))
9313 return llvm::make_error<PreviouslyReportedError>();
9315 return llvm::Error::success();
9319 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
9321 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
9322 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
9323 ompBuilder->createDistribute(ompLoc, allocaIP, deallocBlocks, bodyGenCB);
9328 builder.restoreIP(*afterIP);
9330 if (doDistributeReduction) {
9333 teamsOp, builder, moduleTranslation, allocaIP, reductionDecls,
9334 privateReductionVariables, isByRef,
9346 auto offloadMod = dyn_cast<omp::OffloadModuleInterface>(op);
9348 return op->
emitOpError() <<
"omp flags attached to non offload module op";
9352 if (offloadMod.getIsTargetDevice())
9353 ompBuilder->M.addModuleFlag(llvm::Module::Max,
"openmp-device",
9354 attribute.getOpenmpDeviceVersion());
9357 if (!offloadMod.getIsGPU())
9360 if (attribute.getNoGpuLib())
9363 ompBuilder->createGlobalFlag(attribute.getDebugKind(),
9364 "__omp_rtl_debug_kind");
9365 ompBuilder->createGlobalFlag(attribute.getAssumeTeamsOversubscription(),
9366 "__omp_rtl_assume_teams_oversubscription");
9367 ompBuilder->createGlobalFlag(attribute.getAssumeThreadsOversubscription(),
9368 "__omp_rtl_assume_threads_oversubscription");
9369 ompBuilder->createGlobalFlag(attribute.getAssumeNoThreadState(),
9370 "__omp_rtl_assume_no_thread_state");
9371 ompBuilder->createGlobalFlag(attribute.getAssumeNoNestedParallelism(),
9372 "__omp_rtl_assume_no_nested_parallelism");
9377 omp::TargetOp targetOp,
9378 llvm::OpenMPIRBuilder &ompBuilder,
9379 llvm::vfs::FileSystem &vfs,
9380 llvm::StringRef parentName =
"") {
9381 auto fileLoc = targetOp.getLoc()->findInstanceOf<
FileLineColLoc>();
9382 assert(fileLoc &&
"No file found from location");
9384 auto fileInfoCallBack = [&fileLoc]() {
9385 return std::pair<std::string, uint64_t>(
9386 llvm::StringRef(fileLoc.getFilename()), fileLoc.getLine());
9390 ompBuilder.getTargetEntryUniqueInfo(fileInfoCallBack, vfs, parentName);
9433 omp::TargetOp targetOp, MapInfoData &mapData, llvm::Argument &arg,
9434 llvm::Value *input, llvm::Value *&retVal, llvm::IRBuilderBase &builder,
9435 llvm::OpenMPIRBuilder &ompBuilder,
9437 llvm::IRBuilderBase::InsertPoint allocaIP,
9438 llvm::IRBuilderBase::InsertPoint codeGenIP,
9440 assert(ompBuilder.Config.isTargetDevice() &&
9441 "function only supported for target device codegen");
9442 builder.restoreIP(allocaIP);
9444 omp::VariableCaptureKind capture = omp::VariableCaptureKind::ByRef;
9446 ompBuilder.M.getContext());
9447 unsigned alignmentValue = 0;
9450 cast<omp::BlockArgOpenMPOpInterface>(*targetOp).getBlockArgsPairs(
9453 for (
size_t i = 0; i < mapData.MapClause.size(); ++i) {
9454 if (mapData.OriginalValue[i] == input) {
9455 auto mapOp = cast<omp::MapInfoOp>(mapData.MapClause[i]);
9456 capture = mapOp.getMapCaptureType();
9459 mapOp.getVarPtrType(), ompBuilder.M.getDataLayout());
9463 for (
auto &[val, arg] : blockArgsPairs) {
9464 if (mapOp.getResult() == val) {
9469 assert(mlirArg &&
"expected to find entry block argument for map clause");
9474 unsigned int allocaAS = ompBuilder.M.getDataLayout().getAllocaAddrSpace();
9475 unsigned int defaultAS =
9476 ompBuilder.M.getDataLayout().getProgramAddressSpace();
9479 llvm::Value *v =
nullptr;
9487 builder.SetInsertPoint(codeGenIP.getNodeParent()->getFirstInsertionPt());
9488 v = ompBuilder.createOMPAllocShared(builder, arg.getType());
9492 llvm::IRBuilderBase::InsertPointGuard guard(builder);
9493 for (
auto deallocIP : deallocIPs) {
9494 builder.SetInsertPoint(deallocIP);
9495 ompBuilder.createOMPFreeShared(builder, v, arg.getType());
9499 v = builder.CreateAlloca(arg.getType(), allocaAS);
9501 if (allocaAS != defaultAS && arg.getType()->isPointerTy())
9502 v = builder.CreateAddrSpaceCast(v, builder.getPtrTy(defaultAS));
9505 builder.CreateStore(&arg, v);
9507 builder.restoreIP(codeGenIP);
9510 case omp::VariableCaptureKind::ByCopy: {
9514 case omp::VariableCaptureKind::ByRef: {
9515 llvm::LoadInst *loadInst = builder.CreateAlignedLoad(
9517 ompBuilder.M.getDataLayout().getPrefTypeAlign(v->getType()));
9532 if (v->getType()->isPointerTy() && alignmentValue) {
9533 llvm::MDBuilder MDB(builder.getContext());
9534 loadInst->setMetadata(
9535 llvm::LLVMContext::MD_align,
9536 llvm::MDNode::get(builder.getContext(),
9537 MDB.createConstant(llvm::ConstantInt::get(
9538 llvm::Type::getInt64Ty(builder.getContext()),
9545 case omp::VariableCaptureKind::This:
9546 case omp::VariableCaptureKind::VLAType:
9549 assert(
false &&
"Currently unsupported capture kind");
9553 return builder.saveIP();
9570 auto blockArgIface = llvm::cast<omp::BlockArgOpenMPOpInterface>(*targetOp);
9571 for (
auto item : llvm::zip_equal(targetOp.getHostEvalVars(),
9572 blockArgIface.getHostEvalBlockArgs())) {
9573 Value hostEvalVar = std::get<0>(item), blockArg = std::get<1>(item);
9577 .Case([&](omp::TeamsOp teamsOp) {
9578 if (teamsOp.getNumTeamsLower() == blockArg)
9579 numTeamsLower = hostEvalVar;
9580 else if (llvm::is_contained(teamsOp.getNumTeamsUpperVars(),
9582 numTeamsUpper = hostEvalVar;
9583 else if (!teamsOp.getThreadLimitVars().empty() &&
9584 teamsOp.getThreadLimit(0) == blockArg)
9585 threadLimit = hostEvalVar;
9587 llvm_unreachable(
"unsupported host_eval use");
9589 .Case([&](omp::ParallelOp parallelOp) {
9590 if (!parallelOp.getNumThreadsVars().empty() &&
9591 parallelOp.getNumThreads(0) == blockArg)
9592 numThreads = hostEvalVar;
9594 llvm_unreachable(
"unsupported host_eval use");
9596 .Case([&](omp::LoopNestOp loopOp) {
9597 auto processBounds =
9601 for (
auto [i, lb] : llvm::enumerate(opBounds)) {
9602 if (lb == blockArg) {
9605 (*outBounds)[i] = hostEvalVar;
9611 processBounds(loopOp.getLoopLowerBounds(), lowerBounds);
9612 found = processBounds(loopOp.getLoopUpperBounds(), upperBounds) ||
9614 found = processBounds(loopOp.getLoopSteps(), steps) || found;
9616 assert(found &&
"unsupported host_eval use");
9618 .DefaultUnreachable(
"unsupported host_eval use");
9630template <
typename OpTy>
9635 if (OpTy casted = dyn_cast<OpTy>(op))
9638 if (immediateParent)
9639 return dyn_cast_if_present<OpTy>(op->
getParentOp());
9648 return std::nullopt;
9651 if (
auto constAttr = dyn_cast<IntegerAttr>(constOp.getValue()))
9652 return constAttr.getInt();
9654 return std::nullopt;
9659 uint64_t sizeInBytes = sizeInBits / 8;
9663template <
typename OpTy>
9665 if (op.getNumReductionVars() > 0) {
9670 members.reserve(reductions.size());
9671 for (omp::DeclareReductionOp &red : reductions) {
9675 if (red.getByrefElementType())
9676 members.push_back(*red.getByrefElementType());
9678 members.push_back(red.getType());
9681 auto structType = mlir::LLVM::LLVMStructType::getLiteral(
9697 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &attrs,
9698 bool isTargetDevice,
bool isGPU) {
9701 Value numThreads, numTeamsLower, numTeamsUpper, threadLimit;
9702 if (!isTargetDevice) {
9710 numTeamsLower = teamsOp.getNumTeamsLower();
9712 if (!teamsOp.getNumTeamsUpperVars().empty())
9713 numTeamsUpper = teamsOp.getNumTeams(0);
9714 if (!teamsOp.getThreadLimitVars().empty())
9715 threadLimit = teamsOp.getThreadLimit(0);
9719 if (!parallelOp.getNumThreadsVars().empty())
9720 numThreads = parallelOp.getNumThreads(0);
9726 int32_t minTeamsVal = 1, maxTeamsVal = -1;
9730 if (numTeamsUpper) {
9732 minTeamsVal = maxTeamsVal = *val;
9734 minTeamsVal = maxTeamsVal = 0;
9740 minTeamsVal = maxTeamsVal = 1;
9742 minTeamsVal = maxTeamsVal = -1;
9747 auto setMaxValueFromClause = [](
Value clauseValue, int32_t &
result) {
9761 int32_t targetThreadLimitVal = -1, teamsThreadLimitVal = -1;
9762 if (!targetOp.getThreadLimitVars().empty())
9763 setMaxValueFromClause(targetOp.getThreadLimit(0), targetThreadLimitVal);
9764 setMaxValueFromClause(threadLimit, teamsThreadLimitVal);
9767 int32_t maxThreadsVal = -1;
9769 setMaxValueFromClause(numThreads, maxThreadsVal);
9777 int32_t combinedMaxThreadsVal = targetThreadLimitVal;
9778 if (combinedMaxThreadsVal < 0 ||
9779 (teamsThreadLimitVal >= 0 && teamsThreadLimitVal < combinedMaxThreadsVal))
9780 combinedMaxThreadsVal = teamsThreadLimitVal;
9782 if (combinedMaxThreadsVal < 0 ||
9783 (maxThreadsVal >= 0 && maxThreadsVal < combinedMaxThreadsVal))
9784 combinedMaxThreadsVal = maxThreadsVal;
9786 int32_t reductionDataSize = 0;
9787 if (isGPU && capturedOp) {
9794 omp::TargetExecMode execMode = targetOp.getKernelType();
9796 case omp::TargetExecMode::bare:
9797 attrs.ExecFlags = llvm::omp::OMP_TGT_EXEC_MODE_BARE;
9799 case omp::TargetExecMode::generic:
9800 attrs.ExecFlags = llvm::omp::OMP_TGT_EXEC_MODE_GENERIC;
9802 case omp::TargetExecMode::spmd:
9803 attrs.ExecFlags = llvm::omp::OMP_TGT_EXEC_MODE_SPMD;
9805 case omp::TargetExecMode::spmd_no_loop:
9806 attrs.ExecFlags = llvm::omp::OMP_TGT_EXEC_MODE_SPMD_NO_LOOP;
9809 attrs.MinTeams.front() = minTeamsVal;
9810 attrs.MaxTeams.front() = maxTeamsVal;
9811 attrs.MinThreads.front() = 1;
9812 attrs.MaxThreads.front() = combinedMaxThreadsVal;
9813 attrs.ReductionDataSize = reductionDataSize;
9825 omp::TargetOp targetOp,
Operation *capturedOp,
9826 llvm::OpenMPIRBuilder::TargetKernelRuntimeAttrs &attrs) {
9828 unsigned numLoops = loopOp ? loopOp.getNumLoops() : 0;
9830 Value numThreads, numTeamsLower, numTeamsUpper, teamsThreadLimit;
9834 teamsThreadLimit, &lowerBounds, &upperBounds, &steps);
9837 if (!targetOp.getThreadLimitVars().empty()) {
9838 Value targetThreadLimit = targetOp.getThreadLimit(0);
9839 attrs.TargetThreadLimit.front() =
9847 attrs.MinTeams.front() = builder.CreateSExtOrTrunc(
9848 moduleTranslation.
lookupValue(numTeamsLower), builder.getInt32Ty());
9851 attrs.MaxTeams.front() = builder.CreateSExtOrTrunc(
9852 moduleTranslation.
lookupValue(numTeamsUpper), builder.getInt32Ty());
9854 if (teamsThreadLimit)
9855 attrs.TeamsThreadLimit.front() = builder.CreateSExtOrTrunc(
9856 moduleTranslation.
lookupValue(teamsThreadLimit), builder.getInt32Ty());
9859 attrs.MaxThreads.front() = moduleTranslation.
lookupValue(numThreads);
9861 if (targetOp.hasHostEvalTripCount()) {
9863 attrs.LoopTripCount =
nullptr;
9868 for (
auto [loopLower, loopUpper, loopStep] :
9869 llvm::zip_equal(lowerBounds, upperBounds, steps)) {
9870 llvm::Value *lowerBound = moduleTranslation.
lookupValue(loopLower);
9871 llvm::Value *upperBound = moduleTranslation.
lookupValue(loopUpper);
9872 llvm::Value *step = moduleTranslation.
lookupValue(loopStep);
9874 if (!lowerBound || !upperBound || !step) {
9875 attrs.LoopTripCount =
nullptr;
9879 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
9880 llvm::Value *tripCount = ompBuilder->calculateCanonicalLoopTripCount(
9881 loc, lowerBound, upperBound, step,
true,
9882 loopOp.getLoopInclusive());
9884 if (!attrs.LoopTripCount) {
9885 attrs.LoopTripCount = tripCount;
9890 attrs.LoopTripCount = builder.CreateMul(attrs.LoopTripCount, tripCount,
9895 attrs.DeviceID = builder.getInt64(llvm::omp::OMP_DEVICEID_UNDEF);
9897 attrs.DeviceID = moduleTranslation.
lookupValue(devId);
9899 builder.CreateSExtOrTrunc(attrs.DeviceID, builder.getInt64Ty());
9903static llvm::omp::OMPDynGroupprivateFallbackType
9905 omp::FallbackModifier fb = fallbackAttr ? fallbackAttr.getValue()
9906 : omp::FallbackModifier::default_mem;
9908 case omp::FallbackModifier::abort:
9909 return llvm::omp::OMPDynGroupprivateFallbackType::Abort;
9910 case omp::FallbackModifier::null:
9911 return llvm::omp::OMPDynGroupprivateFallbackType::Null;
9912 case omp::FallbackModifier::default_mem:
9913 return llvm::omp::OMPDynGroupprivateFallbackType::DefaultMem;
9916 llvm_unreachable(
"unexpected dyn_groupprivate fallback type");
9922 auto targetOp = cast<omp::TargetOp>(opInst);
9927 llvm::DebugLoc outlinedFnLoc = builder.getCurrentDebugLocation();
9936 llvm::BasicBlock *parentBB = builder.GetInsertBlock();
9937 assert(parentBB &&
"No insert block is set for the builder");
9938 llvm::Function *parentLLVMFn = parentBB->getParent();
9939 assert(parentLLVMFn &&
"Parent Function must be valid");
9940 if (llvm::DISubprogram *SP = parentLLVMFn->getSubprogram())
9941 builder.SetCurrentDebugLocation(llvm::DILocation::get(
9942 parentLLVMFn->getContext(), outlinedFnLoc.getLine(),
9943 outlinedFnLoc.getCol(), SP, outlinedFnLoc.getInlinedAt()));
9951 llvm::DebugLoc outlinedFnDbgLoc;
9952 if (outlinedFnLoc && parentLLVMFn->getSubprogram())
9953 outlinedFnDbgLoc = outlinedFnLoc;
9956 bool isTargetDevice = ompBuilder->Config.isTargetDevice();
9957 bool isGPU = ompBuilder->Config.isGPU();
9960 auto argIface = cast<omp::BlockArgOpenMPOpInterface>(opInst);
9961 auto &targetRegion = targetOp.getRegion();
9978 llvm::Function *llvmOutlinedFn =
nullptr;
9979 TargetDirectiveEnumTy targetDirective =
9980 getTargetDirectiveEnumTyFromOp(&opInst);
9984 bool isOffloadEntry =
9985 isTargetDevice || !ompBuilder->Config.TargetTriples.empty();
10005 if (!targetOp.getInReductionVars().empty() && !isTargetDevice) {
10006 inRedOrigPtrs.reserve(targetOp.getInReductionVars().size());
10007 inRedMapArgIdx.reserve(targetOp.getInReductionVars().size());
10008 for (
Value v : targetOp.getInReductionVars()) {
10013 std::optional<unsigned> matchIdx;
10014 for (
auto [idx, mapV] : llvm::enumerate(targetOp.getMapVars())) {
10015 auto mapInfo = mapV.getDefiningOp<omp::MapInfoOp>();
10016 if (v != mapInfo.getVarPtr())
10019 return targetOp.emitError()
10020 <<
"in_reduction variable on omp.target has multiple matching "
10021 "map_entries entries; the redirect target is ambiguous";
10027 "TargetOp verifier guarantees a matching map_entries entry for "
10028 "each in_reduction variable");
10029 inRedMapArgIdx.push_back(*matchIdx);
10032 inRedOrigPtrs.push_back(moduleTranslation.
lookupValue(v));
10041 if (!targetOp.getPrivateVars().empty() && !targetOp.getMapVars().empty()) {
10043 std::optional<ArrayAttr> privateSyms = targetOp.getPrivateSyms();
10044 std::optional<DenseI64ArrayAttr> privateMapIndices =
10045 targetOp.getPrivateMapsAttr();
10047 for (
auto [privVarIdx, privVarSymPair] :
10048 llvm::enumerate(llvm::zip_equal(privateVars, *privateSyms))) {
10049 auto privVar = std::get<0>(privVarSymPair);
10050 auto privSym = std::get<1>(privVarSymPair);
10052 SymbolRefAttr privatizerName = llvm::cast<SymbolRefAttr>(privSym);
10053 omp::PrivateClauseOp privatizer =
10056 if (!privatizer.needsMap())
10060 targetOp.getMappedValueForPrivateVar(privVarIdx);
10061 assert(mappedValue &&
"Expected to find mapped value for a privatized "
10062 "variable that needs mapping");
10067 auto mapInfoOp = mappedValue.
getDefiningOp<omp::MapInfoOp>();
10068 [[maybe_unused]]
Type varType = mapInfoOp.getVarPtrType();
10072 if (!isa<LLVM::LLVMPointerType>(privVar.getType()))
10074 varType == privVar.getType() &&
10075 "Type of private var doesn't match the type of the mapped value");
10079 mappedPrivateVars.insert(
10081 targetRegion.getArgument(argIface.getMapBlockArgsStart() +
10082 (*privateMapIndices)[privVarIdx])});
10086 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
10087 auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
10089 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
10090 llvm::IRBuilderBase::InsertPointGuard guard(builder);
10091 builder.SetCurrentDebugLocation(llvm::DebugLoc());
10094 llvm::Function *llvmParentFn =
10096 llvmOutlinedFn = codeGenIP.getNodeParent()->getParent();
10097 assert(llvmParentFn && llvmOutlinedFn &&
10098 "Both parent and outlined functions must exist at this point");
10100 if (outlinedFnLoc && llvmParentFn->getSubprogram())
10101 llvmOutlinedFn->setSubprogram(outlinedFnLoc->getScope()->getSubprogram());
10103 if (
auto attr = llvmParentFn->getFnAttribute(
"target-cpu");
10104 attr.isStringAttribute())
10105 llvmOutlinedFn->addFnAttr(attr);
10107 if (
auto attr = llvmParentFn->getFnAttribute(
"target-features");
10108 attr.isStringAttribute())
10109 llvmOutlinedFn->addFnAttr(attr);
10111 for (
auto [idx, arg] : llvm::enumerate(mapBlockArgs)) {
10117 if (llvm::is_contained(inRedMapArgIdx, idx))
10119 auto mapInfoOp = cast<omp::MapInfoOp>(mapVars[idx].getDefiningOp());
10120 llvm::Value *mapOpValue =
10121 moduleTranslation.
lookupValue(mapInfoOp.getVarPtr());
10122 moduleTranslation.
mapValue(arg, mapOpValue);
10124 for (
auto [arg, mapOp] : llvm::zip_equal(hdaBlockArgs, hdaVars)) {
10125 auto mapInfoOp = cast<omp::MapInfoOp>(mapOp.getDefiningOp());
10126 llvm::Value *mapOpValue =
10127 moduleTranslation.
lookupValue(mapInfoOp.getVarPtr());
10128 moduleTranslation.
mapValue(arg, mapOpValue);
10133 PrivateVarsInfo privateVarsInfo(targetOp);
10137 privateVarsInfo, allocaIP, &mappedPrivateVars);
10139 if (failed(
handleError(afterAllocas, *targetOp)))
10140 return llvm::make_error<PreviouslyReportedError>();
10142 builder.restoreIP(codeGenIP);
10144 &mappedPrivateVars),
10147 return llvm::make_error<PreviouslyReportedError>();
10150 targetOp, builder, moduleTranslation, privateVarsInfo.mlirVars,
10151 privateVarsInfo.llvmVars, privateVarsInfo.privatizers,
10152 targetOp.getPrivateNeedsBarrier(), &mappedPrivateVars)))
10153 return llvm::make_error<PreviouslyReportedError>();
10164 if (!inRedOrigPtrs.empty()) {
10170 inRedResultPtrTys.reserve(inRedMapArgIdx.size());
10171 for (
unsigned mapArgIdx : inRedMapArgIdx)
10172 inRedResultPtrTys.push_back(
10173 moduleTranslation.
convertType(mapBlockArgs[mapArgIdx].getType()));
10175 llvm::OpenMPIRBuilder::LocationDescription bodyLoc(builder);
10176 llvm::OpenMPIRBuilder::InsertPointTy redIP =
10177 ompBuilder->createTargetInReduction(
10178 bodyLoc, inRedOrigPtrs, inRedResultPtrTys,
10179 [&](
unsigned idx, llvm::Value *priv) {
10180 moduleTranslation.
mapValue(mapBlockArgs[inRedMapArgIdx[idx]],
10183 builder.restoreIP(redIP);
10187 moduleTranslation, allocaIP.getNodeParent(), deallocBlocks);
10189 targetRegion,
"omp.target", builder, moduleTranslation);
10192 return llvm::make_error<PreviouslyReportedError>();
10194 builder.SetInsertPoint(exitBlock.get()->getTerminator());
10197 targetOp.getLoc(), privateVarsInfo)))
10198 return llvm::make_error<PreviouslyReportedError>();
10200 return builder.saveIP();
10203 StringRef parentName = parentFn.getName();
10205 llvm::TargetRegionEntryInfo entryInfo;
10211 MapInfoData mapData;
10216 MapInfosTy combinedInfos;
10217 auto genMapInfoCB =
10218 [&](llvm::OpenMPIRBuilder::InsertPointTy codeGenIP) -> MapInfosTy & {
10219 builder.restoreIP(codeGenIP);
10220 genMapInfos(builder, moduleTranslation, dl, combinedInfos, mapData,
10225 auto *nullPtr = llvm::Constant::getNullValue(builder.getPtrTy());
10226 combinedInfos.BasePointers.push_back(nullPtr);
10227 combinedInfos.Pointers.push_back(nullPtr);
10228 combinedInfos.DevicePointers.push_back(
10229 llvm::OpenMPIRBuilder::DeviceInfoTy::None);
10230 combinedInfos.Sizes.push_back(builder.getInt64(0));
10231 combinedInfos.Types.push_back(
10232 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
10233 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10235 combinedInfos.HasAttachPtr.push_back(
false);
10236 if (!combinedInfos.Names.empty())
10237 combinedInfos.Names.push_back(nullPtr);
10238 combinedInfos.Mappers.push_back(
nullptr);
10240 return combinedInfos;
10243 auto argAccessorCB = [&](llvm::Argument &arg, llvm::Value *input,
10244 llvm::Value *&retVal, InsertPointTy allocaIP,
10245 InsertPointTy codeGenIP,
10247 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
10248 llvm::IRBuilderBase::InsertPointGuard guard(builder);
10249 builder.SetCurrentDebugLocation(llvm::DebugLoc());
10255 if (!isTargetDevice) {
10256 retVal = cast<llvm::Value>(&arg);
10261 builder, *ompBuilder, moduleTranslation,
10262 allocaIP, codeGenIP, deallocIPs);
10265 llvm::OpenMPIRBuilder::TargetKernelRuntimeAttrs runtimeAttrs;
10266 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs defaultAttrs;
10268 cast<omp::ComposableOpInterface>(*targetOp).findCapturedOp();
10270 isTargetDevice, isGPU);
10274 if (!isTargetDevice)
10276 targetCapturedOp, runtimeAttrs);
10284 for (
auto [arg, var] : llvm::zip_equal(hostEvalBlockArgs, hostEvalVars)) {
10285 llvm::Value *value = moduleTranslation.
lookupValue(var);
10286 moduleTranslation.
mapValue(arg, value);
10288 if (!llvm::isa<llvm::Constant>(value))
10289 kernelInput.push_back(value);
10292 for (
size_t i = 0, e = mapData.OriginalValue.size(); i != e; ++i) {
10302 using MapFlags = llvm::omp::OpenMPOffloadMappingFlags;
10303 bool isAttachMap = (mapData.Types[i] & MapFlags::OMP_MAP_ATTACH) ==
10304 MapFlags::OMP_MAP_ATTACH;
10305 bool isPrivateTargetParam =
10306 (mapData.Types[i] &
10307 (MapFlags::OMP_MAP_PRIVATE | MapFlags::OMP_MAP_TARGET_PARAM)) ==
10308 (MapFlags::OMP_MAP_PRIVATE | MapFlags::OMP_MAP_TARGET_PARAM);
10310 if (!mapData.IsDeclareTarget[i] && !mapData.IsAMember[i] &&
10311 (!isAttachMap || (isAttachMap && isPrivateTargetParam)))
10312 kernelInput.push_back(mapData.OriginalValue[i]);
10316 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
10319 llvm::OpenMPIRBuilder::DependenciesInfo dds;
10321 targetOp.getDependVars(), targetOp.getDependKinds(),
10322 targetOp.getDependIterated(), targetOp.getDependIteratedKinds(),
10323 builder, moduleTranslation, dds)))
10326 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
10328 llvm::OpenMPIRBuilder::TargetDataInfo info(
10332 auto customMapperCB =
10334 if (!combinedInfos.Mappers[i])
10336 info.HasMapper =
true;
10338 moduleTranslation, targetDirective);
10341 llvm::Value *ifCond =
nullptr;
10342 if (
Value targetIfCond = targetOp.getIfExpr())
10343 ifCond = moduleTranslation.
lookupValue(targetIfCond);
10345 Value dynGroupPrivateSize = targetOp.getDynGroupprivateSize();
10346 llvm::Value *dynSizeVal =
nullptr;
10347 if (dynGroupPrivateSize) {
10348 dynSizeVal = moduleTranslation.
lookupValue(dynGroupPrivateSize);
10349 dynSizeVal = builder.CreateIntCast(dynSizeVal, builder.getInt32Ty(),
10353 llvm::omp::OMPDynGroupprivateFallbackType fallbackType =
10359 llvm::Value *rtLocOverride =
10360 (!isTargetDevice && isOffloadEntry)
10364 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
10366 ->createTarget(ompLoc, isOffloadEntry, allocaIP, builder.saveIP(),
10367 deallocBlocks, info, entryInfo, defaultAttrs,
10368 runtimeAttrs, ifCond, kernelInput, genMapInfoCB,
10369 bodyCB, argAccessorCB, customMapperCB, dds,
10370 targetOp.getNowait(), dynSizeVal, fallbackType,
10371 outlinedFnDbgLoc, rtLocOverride);
10376 builder.restoreIP(*afterIP);
10379 builder.CreateFree(dds.DepArray);
10384static LogicalResult
10386 llvm::OpenMPIRBuilder *ompBuilder,
10395 if (FunctionOpInterface funcOp = dyn_cast<FunctionOpInterface>(op)) {
10396 if (
auto offloadMod = dyn_cast<omp::OffloadModuleInterface>(
10398 if (!offloadMod.getIsTargetDevice())
10401 omp::DeclareTargetDeviceType declareType = attribute.getDeviceType();
10403 if (declareType == omp::DeclareTargetDeviceType::host) {
10404 llvm::Function *llvmFunc =
10406 llvmFunc->dropAllReferences();
10407 llvmFunc->eraseFromParent();
10411 ompBuilder->Builder.ClearInsertionPoint();
10412 ompBuilder->Builder.SetCurrentDebugLocation(llvm::DebugLoc());
10413 }
else if (llvm::Function *llvmFunc =
10425 if (!llvmFunc->isDeclaration() && llvmFunc->hasExternalLinkage() &&
10426 llvmFunc->getVisibility() == llvm::GlobalValue::DefaultVisibility)
10427 llvmFunc->setVisibility(llvm::GlobalValue::HiddenVisibility);
10433 if (LLVM::GlobalOp gOp = dyn_cast<LLVM::GlobalOp>(op)) {
10434 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
10435 if (
auto *gVal = llvmModule->getNamedValue(gOp.getSymName())) {
10436 auto *gVar = cast<llvm::GlobalVariable>(gVal);
10438 bool isDeclaration = gOp.isDeclaration();
10439 bool isExternallyVisible =
10442 llvm::StringRef mangledName = gOp.getSymName();
10443 mlir::omp::DeclareTargetCaptureClause captureClause =
10444 attribute.getCaptureClause();
10447 llvm::StringRef entryMangledName = mangledName;
10448 llvm::Constant *entryAddr = llvm::cast<llvm::Constant>(gVal);
10449 std::function<llvm::GlobalValue::LinkageTypes()> variableLinkage;
10451 bool requiresUSM = ompBuilder->Config.hasRequiresUnifiedSharedMemory();
10453 captureClause == omp::DeclareTargetCaptureClause::to ||
10454 captureClause == omp::DeclareTargetCaptureClause::enter;
10456 attribute.getDeviceType() == omp::DeclareTargetDeviceType::host;
10461 if (isToOrEnter && !isHostOnly && !requiresUSM &&
10462 gVar->hasLocalLinkage()) {
10463 gVar->setLinkage(llvm::GlobalValue::ExternalLinkage);
10464 isExternallyVisible =
true;
10468 if (ompBuilder->Config.isTargetDevice())
10469 gVar->setDSOLocal(
false);
10474 llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny &&
10475 !requiresUSM && !isDeclaration &&
10476 (gVal->hasLocalLinkage() || gVal->hasHiddenVisibility())) {
10480 entryNameStorage = (mangledName + llvm::Twine(
"_decl_tgt_entry")).str();
10481 entryMangledName = entryNameStorage;
10482 if (llvm::GlobalValue *existing =
10483 llvmModule->getNamedValue(entryMangledName)) {
10484 entryAddr = llvm::cast<llvm::Constant>(existing);
10486 entryAddr = llvm::GlobalAlias::create(
10487 gVal->getValueType(), gVal->getAddressSpace(),
10488 llvm::GlobalValue::WeakAnyLinkage, entryMangledName, entryAddr,
10490 llvm::cast<llvm::GlobalAlias>(entryAddr)->setVisibility(
10491 llvm::GlobalValue::DefaultVisibility);
10493 variableLinkage = [] {
return llvm::GlobalValue::WeakAnyLinkage; };
10497 std::vector<llvm::GlobalVariable *> generatedRefs;
10499 std::vector<llvm::Triple> targetTriple;
10500 auto targetTripleAttr = dyn_cast_or_null<mlir::StringAttr>(
10502 LLVM::LLVMDialect::getTargetTripleAttrName()));
10503 if (targetTripleAttr)
10504 targetTriple.emplace_back(targetTripleAttr.data());
10506 auto fileInfoCallBack = [&loc]() {
10507 std::string filename =
"";
10508 std::uint64_t lineNo = 0;
10511 filename = loc.getFilename().str();
10512 lineNo = loc.getLine();
10515 return std::pair<std::string, std::uint64_t>(llvm::StringRef(filename),
10519 llvm::vfs::FileSystem &vfs = moduleTranslation.
getFileSystem();
10520 ompBuilder->registerTargetGlobalVariable(
10521 captureClauseKind, deviceClause, isDeclaration, isExternallyVisible,
10522 ompBuilder->getTargetEntryUniqueInfo(fileInfoCallBack, vfs),
10523 entryMangledName, generatedRefs,
false, targetTriple,
10524 nullptr, variableLinkage, gVal->getType(),
10527 if (ompBuilder->Config.isTargetDevice() &&
10528 (captureClause == omp::DeclareTargetCaptureClause::link ||
10533 llvm::Type *ptrTy = llvm::PointerType::get(llvmModule->getContext(), 0);
10534 llvm::Constant *refPtr = ompBuilder->getAddrOfDeclareTargetVar(
10535 captureClauseKind, deviceClause, isDeclaration, isExternallyVisible,
10536 ompBuilder->getTargetEntryUniqueInfo(fileInfoCallBack, vfs),
10537 mangledName, generatedRefs,
false, targetTriple,
10548 if (!gVar->isDeclaration())
10549 gVar->setLinkage(llvm::GlobalValue::InternalLinkage);
10555 dyn_cast<llvm::GlobalValue>(refPtr->stripPointerCasts()))
10556 ompBuilder->registerDeclareTargetGlobalReplacement(gVal, newGV);
10563 if (ompBuilder->Config.isTargetDevice() && isHostOnly && isToOrEnter) {
10564 gVar->setLinkage(llvm::GlobalValue::ExternalLinkage);
10565 gVar->setInitializer(
nullptr);
10577class OpenMPDialectLLVMIRTranslationInterface
10578 :
public LLVMTranslationDialectInterface {
10580 using LLVMTranslationDialectInterface::LLVMTranslationDialectInterface;
10585 convertOperation(Operation *op, llvm::IRBuilderBase &builder,
10586 LLVM::ModuleTranslation &moduleTranslation)
const final;
10591 amendOperation(Operation *op, ArrayRef<llvm::Instruction *> instructions,
10592 NamedAttribute attribute,
10593 LLVM::ModuleTranslation &moduleTranslation)
const final;
10598 void registerAllocatedPtr(Value var, llvm::Value *ptr)
const {
10599 ompAllocatedPtrs[var] = ptr;
10604 llvm::Value *lookupAllocatedPtr(Value var)
const {
10605 auto it = ompAllocatedPtrs.find(var);
10606 return it != ompAllocatedPtrs.end() ? it->second :
nullptr;
10618LogicalResult OpenMPDialectLLVMIRTranslationInterface::amendOperation(
10619 Operation *op, ArrayRef<llvm::Instruction *> instructions,
10620 NamedAttribute attribute,
10621 LLVM::ModuleTranslation &moduleTranslation)
const {
10622 return llvm::StringSwitch<llvm::function_ref<LogicalResult(Attribute)>>(
10624 .Case(
"omp.is_target_device",
10625 [&](Attribute attr) {
10626 if (
auto deviceAttr = dyn_cast<BoolAttr>(attr)) {
10627 llvm::OpenMPIRBuilderConfig &config =
10629 config.setIsTargetDevice(deviceAttr.getValue());
10634 .Case(
"omp.is_gpu",
10635 [&](Attribute attr) {
10636 if (
auto gpuAttr = dyn_cast<BoolAttr>(attr)) {
10637 llvm::OpenMPIRBuilderConfig &config =
10639 config.setIsGPU(gpuAttr.getValue());
10644 .Case(
"omp.host_ir_filepath",
10645 [&](Attribute attr) {
10646 if (
auto filepathAttr = dyn_cast<StringAttr>(attr)) {
10647 llvm::OpenMPIRBuilder *ompBuilder =
10649 ompBuilder->loadOffloadInfoMetadata(
10650 moduleTranslation.
getFileSystem(), filepathAttr.getValue());
10656 [&](Attribute attr) {
10657 if (
auto rtlAttr = dyn_cast<omp::FlagsAttr>(attr))
10661 .Case(
"omp.version",
10662 [&](Attribute attr) {
10663 if (
auto versionAttr = dyn_cast<omp::VersionAttr>(attr)) {
10664 llvm::OpenMPIRBuilder *ompBuilder =
10666 ompBuilder->M.addModuleFlag(llvm::Module::Max,
"openmp",
10667 versionAttr.getVersion());
10672 .Case(
"omp.declare_target",
10673 [&](Attribute attr) {
10674 if (
auto declareTargetAttr =
10675 dyn_cast<omp::DeclareTargetAttr>(attr)) {
10676 llvm::OpenMPIRBuilder *ompBuilder =
10679 ompBuilder, moduleTranslation);
10683 .Case(
"omp.requires",
10684 [&](Attribute attr) {
10685 if (
auto requiresAttr = dyn_cast<omp::ClauseRequiresAttr>(attr)) {
10686 using Requires = omp::ClauseRequires;
10687 Requires flags = requiresAttr.getValue();
10688 llvm::OpenMPIRBuilderConfig &config =
10690 config.setHasRequiresReverseOffload(
10691 bitEnumContainsAll(flags, Requires::reverse_offload));
10692 config.setHasRequiresUnifiedAddress(
10693 bitEnumContainsAll(flags, Requires::unified_address));
10694 config.setHasRequiresUnifiedSharedMemory(
10695 bitEnumContainsAll(flags, Requires::unified_shared_memory));
10696 config.setHasRequiresDynamicAllocators(
10697 bitEnumContainsAll(flags, Requires::dynamic_allocators));
10702 .Case(
"omp.target_triples",
10703 [&](Attribute attr) {
10704 if (
auto triplesAttr = dyn_cast<ArrayAttr>(attr)) {
10705 llvm::OpenMPIRBuilderConfig &config =
10707 config.TargetTriples.clear();
10708 config.TargetTriples.reserve(triplesAttr.size());
10709 for (Attribute tripleAttr : triplesAttr) {
10710 if (
auto tripleStrAttr = dyn_cast<StringAttr>(tripleAttr))
10711 config.TargetTriples.emplace_back(tripleStrAttr.getValue());
10719 .Case(
"omp.integer_wrap_around",
10720 [&](Attribute attr) {
10721 if (
auto wrapAttr = dyn_cast<omp::IntegerWrapAroundAttr>(attr)) {
10722 llvm::OpenMPIRBuilderConfig &config =
10724 config.setNoSignedWrap(!wrapAttr.getIntegerWrapAround());
10729 .Default([](Attribute) {
10745 if (
auto declareTargetIface =
10746 llvm::dyn_cast<mlir::omp::DeclareTargetInterface>(
10747 parentFn.getOperation())) {
10748 omp::DeclareTargetAttr declareTargetAttr =
10749 declareTargetIface.getDeclareTarget();
10750 if (declareTargetAttr && declareTargetAttr.getDeviceType() !=
10751 mlir::omp::DeclareTargetDeviceType::host)
10762 llvm::Module *llvmModule) {
10763 llvm::Type *i64Ty = builder.getInt64Ty();
10764 llvm::Type *i32Ty = builder.getInt32Ty();
10765 llvm::Type *returnType = builder.getPtrTy(0);
10766 llvm::FunctionType *fnType =
10767 llvm::FunctionType::get(returnType, {i64Ty, i32Ty},
false);
10768 llvm::Function *
func = cast<llvm::Function>(
10769 llvmModule->getOrInsertFunction(
"omp_target_alloc", fnType).getCallee());
10773template <
typename T>
10774static llvm::Value *
10777 llvm::DataLayout dataLayout =
10779 llvm::Type *llvmHeapTy =
10780 moduleTranslation.
convertType(op.getMemElemTypeAttr().getValue());
10782 auto alignment = op.getMemAlignment();
10783 llvm::TypeSize typeSize = llvm::alignTo(
10784 dataLayout.getTypeStoreSize(llvmHeapTy),
10785 alignment ? *alignment : dataLayout.getABITypeAlign(llvmHeapTy).value());
10787 llvm::Value *allocSize = builder.getInt64(typeSize.getFixedValue());
10788 return builder.CreateMul(
10790 builder.CreateIntCast(moduleTranslation.
lookupValue(op.getMemArraySize()),
10791 builder.getInt64Ty(),
10798 omp::TargetAllocMemOp op) {
10799 llvm::DataLayout dataLayout =
10801 llvm::Type *llvmHeapTy = moduleTranslation.
convertType(op.getAllocatedType());
10802 llvm::TypeSize typeSize = dataLayout.getTypeAllocSize(llvmHeapTy);
10803 llvm::Value *allocSize = builder.getInt64(typeSize.getFixedValue());
10804 for (
auto typeParam : op.getTypeparams()) {
10805 allocSize = builder.CreateMul(
10807 builder.CreateIntCast(moduleTranslation.
lookupValue(typeParam),
10808 builder.getInt64Ty(),
10814static LogicalResult
10817 auto allocMemOp = cast<omp::TargetAllocMemOp>(opInst);
10822 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
10826 llvm::Value *llvmDeviceNum = moduleTranslation.
lookupValue(deviceNum);
10828 llvm::Value *allocSize =
10831 llvm::CallInst *call =
10832 builder.CreateCall(ompTargetAllocFunc, {allocSize, llvmDeviceNum});
10833 llvm::Value *resultI64 = builder.CreatePtrToInt(call, builder.getInt64Ty());
10836 moduleTranslation.
mapValue(allocMemOp.getResult(), resultI64);
10840static LogicalResult
10842 llvm::IRBuilderBase &builder,
10846 moduleTranslation.
mapValue(allocMemOp.getResult(),
10847 ompBuilder->createOMPAllocShared(builder, size));
10851static LogicalResult
10854 const OpenMPDialectLLVMIRTranslationInterface &ompIface) {
10855 auto allocateDirOp = cast<omp::AllocateDirOp>(opInst);
10858 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
10859 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
10860 llvm::DataLayout dataLayout = llvmModule->getDataLayout();
10862 std::optional<int64_t> alignAttr = allocateDirOp.getAlign();
10864 llvm::Value *allocator;
10865 if (
auto allocatorVar = allocateDirOp.getAllocator()) {
10866 allocator = moduleTranslation.
lookupValue(allocatorVar);
10867 if (allocator->getType()->isIntegerTy())
10868 allocator = builder.CreateIntToPtr(allocator, builder.getPtrTy());
10869 else if (allocator->getType()->isPointerTy())
10870 allocator = builder.CreatePointerBitCastOrAddrSpaceCast(
10871 allocator, builder.getPtrTy());
10873 allocator = llvm::ConstantPointerNull::get(builder.getPtrTy());
10876 for (
Value var : vars) {
10878 llvm::Type *typeToInspect =
10883 var, baseVar, moduleTranslation, builder, dataLayout)) {
10884 size = *dynamicSize;
10885 }
else if (typeToInspect->isArrayTy()) {
10886 size = builder.getInt64(
10887 dataLayout.getTypeAllocSize(typeToInspect).getFixedValue());
10889 size = builder.getInt64(
10890 dataLayout.getTypeAllocSize(typeToInspect).getFixedValue());
10893 uint64_t alignValue =
10894 alignAttr ? alignAttr.value()
10895 : dataLayout.getABITypeAlign(typeToInspect).value();
10896 llvm::Value *alignConst = builder.getInt64(alignValue);
10898 size = builder.CreateAdd(size, builder.getInt64(alignValue - 1),
"",
true);
10899 size = builder.CreateUDiv(size, alignConst);
10900 size = builder.CreateMul(size, alignConst,
"",
true);
10902 std::string allocName =
10903 ompBuilder->createPlatformSpecificName({
".void.addr"});
10904 llvm::CallInst *allocCall;
10905 if (alignAttr.has_value()) {
10906 allocCall = ompBuilder->createOMPAlignedAlloc(
10907 ompLoc, builder.getInt64(alignAttr.value()), size, allocator,
10911 ompBuilder->createOMPAlloc(ompLoc, size, allocator, allocName);
10914 ompIface.registerAllocatedPtr(var, allocCall);
10916 if (llvm::Value *baseLlvm = moduleTranslation.
lookupValue(baseVar)) {
10917 llvm::Value *boundPtr = builder.CreatePointerBitCastOrAddrSpaceCast(
10918 allocCall, baseLlvm->getType());
10920 }
else if (llvm::Value *varLlvm = moduleTranslation.
lookupValue(var)) {
10921 llvm::Value *boundPtr = builder.CreatePointerBitCastOrAddrSpaceCast(
10922 allocCall, varLlvm->getType());
10930static LogicalResult
10933 const OpenMPDialectLLVMIRTranslationInterface &ompIface) {
10934 auto freeOp = cast<omp::AllocateFreeOp>(opInst);
10936 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
10938 llvm::Value *allocator;
10939 if (
auto allocatorVar = freeOp.getAllocator()) {
10940 allocator = moduleTranslation.
lookupValue(allocatorVar);
10941 if (allocator->getType()->isIntegerTy())
10942 allocator = builder.CreateIntToPtr(allocator, builder.getPtrTy());
10943 else if (allocator->getType()->isPointerTy())
10944 allocator = builder.CreatePointerBitCastOrAddrSpaceCast(
10945 allocator, builder.getPtrTy());
10947 allocator = llvm::ConstantPointerNull::get(builder.getPtrTy());
10952 for (
Value var : llvm::reverse(vars)) {
10953 llvm::Value *allocPtr = ompIface.lookupAllocatedPtr(var);
10955 return opInst.
emitError(
"omp.allocate_free: no allocation recorded");
10956 ompBuilder->createOMPFree(ompLoc, allocPtr, allocator,
"");
10963 llvm::Module *llvmModule) {
10964 llvm::Type *ptrTy = builder.getPtrTy(0);
10965 llvm::Type *i32Ty = builder.getInt32Ty();
10966 llvm::Type *voidTy = builder.getVoidTy();
10967 llvm::FunctionType *fnType =
10968 llvm::FunctionType::get(voidTy, {ptrTy, i32Ty},
false);
10969 llvm::Function *
func = dyn_cast<llvm::Function>(
10970 llvmModule->getOrInsertFunction(
"omp_target_free", fnType).getCallee());
10974static LogicalResult
10977 auto freeMemOp = cast<omp::TargetFreeMemOp>(opInst);
10982 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
10983 llvm::Function *ompTragetFreeFunc =
getOmpTargetFree(builder, llvmModule);
10986 llvm::Value *llvmDeviceNum = moduleTranslation.
lookupValue(deviceNum);
10989 llvm::Value *llvmHeapref = moduleTranslation.
lookupValue(heapref);
10991 llvm::Value *intToPtr =
10992 builder.CreateIntToPtr(llvmHeapref, builder.getPtrTy(0));
10993 builder.CreateCall(ompTragetFreeFunc, {intToPtr, llvmDeviceNum});
10997static LogicalResult
10999 llvm::IRBuilderBase &builder,
11003 ompBuilder->createOMPFreeShared(
11004 builder, moduleTranslation.
lookupValue(freeMemOp.getHeapref()), size);
11009static LogicalResult
11013 auto groupprivateOp = cast<omp::GroupprivateOp>(opInst);
11018 bool isTargetDevice = ompBuilder->Config.isTargetDevice();
11022 bool shouldAllocate =
true;
11023 switch (groupprivateOp.getDeviceType().value_or(
11024 mlir::omp::DeclareTargetDeviceType::any)) {
11025 case mlir::omp::DeclareTargetDeviceType::host:
11026 shouldAllocate = !isTargetDevice;
11028 case mlir::omp::DeclareTargetDeviceType::nohost:
11029 shouldAllocate = isTargetDevice;
11031 case mlir::omp::DeclareTargetDeviceType::any:
11032 shouldAllocate =
true;
11038 &opInst, groupprivateOp.getSymNameAttr());
11041 <<
"expected symbol '" << groupprivateOp.getSymName()
11042 <<
"' to reference an LLVM global variable";
11044 llvm::GlobalValue *globalValue = moduleTranslation.
lookupGlobal(global);
11045 llvm::Type *varType = moduleTranslation.
convertType(global.getType());
11046 std::string varName = globalValue->getName().str();
11048 llvm::Value *resultPtr;
11049 if (shouldAllocate && isTargetDevice) {
11050 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
11051 llvm::Triple targetTriple(llvmModule->getTargetTriple());
11052 unsigned sharedAddressSpace;
11053 if (targetTriple.isAMDGCN())
11054 sharedAddressSpace = llvm::AMDGPUAS::LOCAL_ADDRESS;
11055 else if (targetTriple.isNVPTX())
11056 sharedAddressSpace = llvm::NVPTXAS::ADDRESS_SPACE_SHARED;
11058 return opInst.
emitError() <<
"groupprivate is not supported for target: "
11059 << targetTriple.str();
11060 llvm::GlobalVariable *sharedVar =
new llvm::GlobalVariable(
11061 *llvmModule, varType,
false,
11062 llvm::GlobalValue::InternalLinkage, llvm::PoisonValue::get(varType),
11063 varName,
nullptr, llvm::GlobalValue::NotThreadLocal,
11064 sharedAddressSpace,
11066 resultPtr = sharedVar;
11068 if (shouldAllocate && !isTargetDevice)
11069 opInst.
emitWarning(
"groupprivate directive is currently ignored on the "
11070 "host, using original global");
11071 resultPtr = globalValue;
11080LogicalResult OpenMPDialectLLVMIRTranslationInterface::convertOperation(
11081 Operation *op, llvm::IRBuilderBase &builder,
11082 LLVM::ModuleTranslation &moduleTranslation)
const {
11085 if (ompBuilder->Config.isTargetDevice() &&
11086 !isa<omp::TargetOp, omp::MapInfoOp, omp::TerminatorOp, omp::YieldOp>(
11089 return op->
emitOpError() <<
"unsupported host op found in device";
11097 bool isOutermostLoopWrapper =
11098 isa_and_present<omp::LoopWrapperInterface>(op) &&
11099 !dyn_cast_if_present<omp::LoopWrapperInterface>(op->
getParentOp());
11108 if (isa<omp::TaskloopContextOp>(op))
11109 isOutermostLoopWrapper =
true;
11110 else if (isa<omp::TaskloopWrapperOp>(op))
11111 isOutermostLoopWrapper =
false;
11113 if (isOutermostLoopWrapper)
11114 moduleTranslation.
stackPush<OpenMPLoopInfoStackFrame>();
11117 llvm::TypeSwitch<Operation *, LogicalResult>(op)
11118 .Case([&](omp::BarrierOp op) -> LogicalResult {
11122 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
11123 ompBuilder->createBarrier(builder, llvm::omp::OMPD_barrier);
11125 if (res.succeeded()) {
11128 builder.restoreIP(*afterIP);
11132 .Case([&](omp::TaskyieldOp op) {
11136 ompBuilder->createTaskyield(builder);
11139 .Case([&](omp::FlushOp op) {
11151 ompBuilder->createFlush(builder);
11154 .Case([&](omp::ErrorOp op) {
11158 llvm::Value *message =
nullptr;
11159 if (mlir::Value messageExpr = op.getMessageExpr())
11160 message = moduleTranslation.
lookupValue(messageExpr);
11161 else if (std::optional<StringRef> msg = op.getMessage();
11162 msg && !msg->empty())
11163 message = builder.CreateGlobalString(*msg);
11164 ompBuilder->createError(
11165 llvm::OpenMPIRBuilder::LocationDescription(builder),
11166 op.getSeverity() == omp::ClauseSeverity::fatal, message);
11169 .Case([&](omp::ParallelOp op) {
11172 .Case([&](omp::DispatchOp) {
11175 .Case([&](omp::MaskedOp) {
11178 .Case([&](omp::MasterOp) {
11181 .Case([&](omp::CriticalOp) {
11184 .Case([&](omp::OrderedRegionOp) {
11187 .Case([&](omp::OrderedOp) {
11190 .Case([&](omp::WsloopOp) {
11193 .Case([&](omp::SimdOp) {
11196 .Case([&](omp::AtomicReadOp) {
11199 .Case([&](omp::AtomicWriteOp) {
11202 .Case([&](omp::AtomicUpdateOp op) {
11205 .Case([&](omp::AtomicCaptureOp op) {
11208 .Case([&](omp::AtomicCompareOp op) {
11211 .Case([&](omp::CancelOp op) {
11214 .Case([&](omp::CancellationPointOp op) {
11217 .Case([&](omp::SectionsOp) {
11220 .Case([&](omp::ScopeOp op) {
11223 .Case([&](omp::SingleOp op) {
11226 .Case([&](omp::TeamsOp op) {
11229 .Case([&](omp::TaskOp op) {
11232 .Case([&](omp::TaskloopWrapperOp op) {
11235 .Case([&](omp::TaskloopContextOp op) {
11238 .Case([&](omp::TaskgroupOp op) {
11241 .Case([&](omp::TaskwaitOp op) {
11244 .Case([&](omp::InteropInitOp op) {
11247 .Case([&](omp::InteropDestroyOp op) {
11250 .Case([&](omp::InteropUseOp op) {
11253 .Case<omp::YieldOp, omp::TerminatorOp, omp::DeclareMapperOp,
11254 omp::DeclareMapperInfoOp, omp::DeclareReductionOp,
11255 omp::CriticalDeclareOp>([](
auto op) {
11268 .Case([&](omp::ThreadprivateOp) {
11271 .Case<omp::TargetDataOp, omp::TargetEnterDataOp,
11272 omp::TargetExitDataOp, omp::TargetUpdateOp>([&](
auto op) {
11275 .Case([&](omp::TargetOp) {
11278 .Case([&](omp::DistributeOp) {
11281 .Case([&](omp::LoopNestOp) {
11284 .Case<omp::MapInfoOp, omp::MapBoundsOp, omp::PrivateClauseOp,
11285 omp::AffinityEntryOp, omp::IteratorOp>([&](
auto op) {
11291 .Case([&](omp::NewCliOp op) {
11296 .Case([&](omp::CanonicalLoopOp op) {
11299 .Case([&](omp::UnrollHeuristicOp op) {
11308 .Case([&](omp::UnrollFullOp op) {
11311 .Case([&](omp::UnrollPartialOp op) {
11314 .Case([&](omp::TileOp op) {
11315 return applyTile(op, builder, moduleTranslation);
11317 .Case([&](omp::FuseOp op) {
11318 return applyFuse(op, builder, moduleTranslation);
11320 .Case([&](omp::TargetAllocMemOp) {
11323 .Case([&](omp::TargetFreeMemOp) {
11326 .Case([&](omp::AllocateDirOp) {
11329 .Case([&](omp::AllocateFreeOp) {
11333 .Case([&](omp::AllocSharedMemOp op) {
11336 .Case([&](omp::FreeSharedMemOp op) {
11339 .Case([&](omp::GroupprivateOp) {
11342 .Case([&](omp::DeclareSimdOp) {
11349 .Default([&](Operation *inst) {
11351 <<
"not yet implemented: " << inst->
getName();
11354 if (isOutermostLoopWrapper)
11361 static llvm::cl::opt<
bool,
true> option(
11362 "openmp-disable-virtual-collapse", llvm::cl::Hidden,
11363 llvm::cl::desc(
"Disable virtual collapse of eligible host loops"),
11364 llvm::cl::location(disableVirtualCollapse));
11368 registry.
insert<omp::OpenMPDialect>();
11370 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 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 void invalidateOmpLoop(LLVM::ModuleTranslation &moduleTranslation, Value mlir)
Mark an OpenMP loop as having been consumed.
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 void addNonContiguousUpdate(LLVM::ModuleTranslation &moduleTranslation, llvm::IRBuilderBase &builder, MapInfoData &mapData, size_t mapDataIdx, MapInfosTy &combinedInfo)
Describe a bounded update as a set of contiguous pieces. Bounds follow the dialect's normalized faste...
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 OpenMPTranslationState & getOpenMPState(LLVM::ModuleTranslation &moduleTranslation)
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 void processIndividualMap(LLVM::ModuleTranslation &moduleTranslation, 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 LogicalResult convertOmpInteropDestroyOp(omp::InteropDestroyOp destroyOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static void mapOmpLoop(LLVM::ModuleTranslation &moduleTranslation, Value mlir, llvm::CanonicalLoopInfo *llvm)
Map an MLIR OpenMP dialect CanonicalLoopInfo to its lowered LLVM-IR OpenMPIRBuilder CanonicalLoopInfo...
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::CanonicalLoopInfo * lookupOMPLoop(LLVM::ModuleTranslation &moduleTranslation, Value mlir)
Find the LLVM-IR loop that represents an MLIR loop.
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 llvm::OpenMPIRBuilder * getOpenMPBuilder(LLVM::ModuleTranslation &moduleTranslation)
Returns the OpenMP IR builder associated with the LLVM IR module being constructed.
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 llvm::OpenMPIRBuilder::CollapseIVMapping selectCollapseIVMapping(omp::LoopNestOp loopOp, bool isTargetDevice, ArrayRef< llvm::CanonicalLoopInfo * > loops)
Select Virtual only for two constant-count host worksharing loops.
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::Value * emitTaskReductionModifierInitCall(OpTy op, ArrayRef< omp::DeclareReductionOp > reductionDecls, ArrayRef< llvm::Value * > privateReductionVariables, llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder::InsertPointTy allocaIP, LLVM::ModuleTranslation &moduleTranslation, bool isWorksharing)
Register only the task-modified items. All items still participate in the enclosing construct's ordin...
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.
Base class for state that lives as long as the module translation.
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.
T & getOrCreateExtension(Args &&...args)
Returns the extension of type T, constructing it from args on first use.
llvm::Value * lookupValue(Value value) const
Finds an LLVM IR value corresponding to the given MLIR value.
SymbolTableCollection & symbolTable()
llvm::Type * convertType(Type type)
Converts the type from MLIR LLVM dialect to LLVM.
llvm::vfs::FileSystem & getFileSystem()
Returns the virtual filesystem to use for file operations.
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::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
void registerOpenMPTranslationCLOptions()
Register OpenMP translation command-line options before parsing them.
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.
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.