26 #include "llvm/ADT/ArrayRef.h"
27 #include "llvm/ADT/SetVector.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/ReplaceConstant.h"
37 #include "llvm/Support/FileSystem.h"
38 #include "llvm/TargetParser/Triple.h"
39 #include "llvm/Transforms/Utils/ModuleUtils.h"
51 static llvm::omp::ScheduleKind
52 convertToScheduleKind(std::optional<omp::ClauseScheduleKind> schedKind) {
53 if (!schedKind.has_value())
54 return llvm::omp::OMP_SCHEDULE_Default;
55 switch (schedKind.value()) {
56 case omp::ClauseScheduleKind::Static:
57 return llvm::omp::OMP_SCHEDULE_Static;
58 case omp::ClauseScheduleKind::Dynamic:
59 return llvm::omp::OMP_SCHEDULE_Dynamic;
60 case omp::ClauseScheduleKind::Guided:
61 return llvm::omp::OMP_SCHEDULE_Guided;
62 case omp::ClauseScheduleKind::Auto:
63 return llvm::omp::OMP_SCHEDULE_Auto;
65 return llvm::omp::OMP_SCHEDULE_Runtime;
67 llvm_unreachable(
"unhandled schedule clause argument");
72 class OpenMPAllocaStackFrame
77 explicit OpenMPAllocaStackFrame(llvm::OpenMPIRBuilder::InsertPointTy allocaIP)
78 : allocaInsertPoint(allocaIP) {}
79 llvm::OpenMPIRBuilder::InsertPointTy allocaInsertPoint;
85 class OpenMPLoopInfoStackFrame
89 llvm::CanonicalLoopInfo *loopInfo =
nullptr;
108 class PreviouslyReportedError
109 :
public llvm::ErrorInfo<PreviouslyReportedError> {
111 void log(raw_ostream &)
const override {
115 std::error_code convertToErrorCode()
const override {
117 "PreviouslyReportedError doesn't support ECError conversion");
131 SymbolRefAttr symbolName) {
132 omp::PrivateClauseOp privatizer =
133 SymbolTable::lookupNearestSymbolFrom<omp::PrivateClauseOp>(from,
135 assert(privatizer &&
"privatizer not found in the symbol table");
146 auto todo = [&op](StringRef clauseName) {
147 return op.
emitError() <<
"not yet implemented: Unhandled clause "
148 << clauseName <<
" in " << op.
getName()
152 auto checkAllocate = [&todo](
auto op, LogicalResult &result) {
153 if (!op.getAllocateVars().empty() || !op.getAllocatorVars().empty())
154 result = todo(
"allocate");
156 auto checkBare = [&todo](
auto op, LogicalResult &result) {
158 result = todo(
"ompx_bare");
160 auto checkDepend = [&todo](
auto op, LogicalResult &result) {
161 if (!op.getDependVars().empty() || op.getDependKinds())
162 result = todo(
"depend");
164 auto checkDevice = [&todo](
auto op, LogicalResult &result) {
166 result = todo(
"device");
168 auto checkDistSchedule = [&todo](
auto op, LogicalResult &result) {
169 if (op.getDistScheduleChunkSize())
170 result = todo(
"dist_schedule with chunk_size");
172 auto checkHint = [](
auto op, LogicalResult &) {
176 auto checkInReduction = [&todo](
auto op, LogicalResult &result) {
177 if (!op.getInReductionVars().empty() || op.getInReductionByref() ||
178 op.getInReductionSyms())
179 result = todo(
"in_reduction");
181 auto checkIsDevicePtr = [&todo](
auto op, LogicalResult &result) {
182 if (!op.getIsDevicePtrVars().empty())
183 result = todo(
"is_device_ptr");
185 auto checkLinear = [&todo](
auto op, LogicalResult &result) {
186 if (!op.getLinearVars().empty() || !op.getLinearStepVars().empty())
187 result = todo(
"linear");
189 auto checkNontemporal = [&todo](
auto op, LogicalResult &result) {
190 if (!op.getNontemporalVars().empty())
191 result = todo(
"nontemporal");
193 auto checkNowait = [&todo](
auto op, LogicalResult &result) {
195 result = todo(
"nowait");
197 auto checkOrder = [&todo](
auto op, LogicalResult &result) {
198 if (op.getOrder() || op.getOrderMod())
199 result = todo(
"order");
201 auto checkParLevelSimd = [&todo](
auto op, LogicalResult &result) {
202 if (op.getParLevelSimd())
203 result = todo(
"parallelization-level");
205 auto checkPriority = [&todo](
auto op, LogicalResult &result) {
206 if (op.getPriority())
207 result = todo(
"priority");
209 auto checkPrivate = [&todo](
auto op, LogicalResult &result) {
210 if constexpr (std::is_same_v<std::decay_t<decltype(op)>, omp::TargetOp>) {
214 if (std::optional<ArrayAttr> privateSyms = op.getPrivateSyms()) {
215 for (
Attribute privatizerNameAttr : *privateSyms) {
217 op.getOperation(), cast<SymbolRefAttr>(privatizerNameAttr));
219 if (privatizer.getDataSharingType() ==
220 omp::DataSharingClauseType::FirstPrivate)
221 result = todo(
"firstprivate");
225 if (!op.getPrivateVars().empty() || op.getPrivateSyms())
226 result = todo(
"privatization");
229 auto checkReduction = [&todo](
auto op, LogicalResult &result) {
230 if (isa<omp::TeamsOp>(op) || isa<omp::SimdOp>(op))
231 if (!op.getReductionVars().empty() || op.getReductionByref() ||
232 op.getReductionSyms())
233 result = todo(
"reduction");
234 if (op.getReductionMod() &&
235 op.getReductionMod().value() != omp::ReductionModifier::defaultmod)
236 result = todo(
"reduction with modifier");
238 auto checkTaskReduction = [&todo](
auto op, LogicalResult &result) {
239 if (!op.getTaskReductionVars().empty() || op.getTaskReductionByref() ||
240 op.getTaskReductionSyms())
241 result = todo(
"task_reduction");
243 auto checkUntied = [&todo](
auto op, LogicalResult &result) {
245 result = todo(
"untied");
248 LogicalResult result = success();
250 .Case([&](omp::DistributeOp op) {
251 checkAllocate(op, result);
252 checkDistSchedule(op, result);
253 checkOrder(op, result);
255 .Case([&](omp::OrderedRegionOp op) { checkParLevelSimd(op, result); })
256 .Case([&](omp::SectionsOp op) {
257 checkAllocate(op, result);
258 checkPrivate(op, result);
259 checkReduction(op, result);
261 .Case([&](omp::SingleOp op) {
262 checkAllocate(op, result);
263 checkPrivate(op, result);
265 .Case([&](omp::TeamsOp op) {
266 checkAllocate(op, result);
267 checkPrivate(op, result);
268 checkReduction(op, result);
270 .Case([&](omp::TaskOp op) {
271 checkAllocate(op, result);
272 checkInReduction(op, result);
274 .Case([&](omp::TaskgroupOp op) {
275 checkAllocate(op, result);
276 checkTaskReduction(op, result);
278 .Case([&](omp::TaskwaitOp op) {
279 checkDepend(op, result);
280 checkNowait(op, result);
282 .Case([&](omp::TaskloopOp op) {
284 checkUntied(op, result);
285 checkPriority(op, result);
287 .Case([&](omp::WsloopOp op) {
288 checkAllocate(op, result);
289 checkLinear(op, result);
290 checkOrder(op, result);
291 checkReduction(op, result);
293 .Case([&](omp::ParallelOp op) {
294 checkAllocate(op, result);
295 checkReduction(op, result);
297 .Case([&](omp::SimdOp op) {
298 checkLinear(op, result);
299 checkNontemporal(op, result);
300 checkReduction(op, result);
302 .Case<omp::AtomicReadOp, omp::AtomicWriteOp, omp::AtomicUpdateOp,
303 omp::AtomicCaptureOp>([&](
auto op) { checkHint(op, result); })
304 .Case<omp::TargetEnterDataOp, omp::TargetExitDataOp, omp::TargetUpdateOp>(
305 [&](
auto op) { checkDepend(op, result); })
306 .Case([&](omp::TargetOp op) {
307 checkAllocate(op, result);
308 checkBare(op, result);
309 checkDevice(op, result);
310 checkInReduction(op, result);
311 checkIsDevicePtr(op, result);
312 checkPrivate(op, result);
322 LogicalResult result = success();
324 llvm::handleAllErrors(
326 [&](
const PreviouslyReportedError &) { result = failure(); },
327 [&](
const llvm::ErrorInfoBase &err) {
334 template <
typename T>
344 static llvm::OpenMPIRBuilder::InsertPointTy
350 llvm::OpenMPIRBuilder::InsertPointTy allocaInsertPoint;
352 [&](OpenMPAllocaStackFrame &frame) {
353 allocaInsertPoint = frame.allocaInsertPoint;
357 return allocaInsertPoint;
366 if (builder.GetInsertBlock() ==
367 &builder.GetInsertBlock()->getParent()->getEntryBlock()) {
368 assert(builder.GetInsertPoint() == builder.GetInsertBlock()->end() &&
369 "Assuming end of basic block");
370 llvm::BasicBlock *entryBB = llvm::BasicBlock::Create(
371 builder.getContext(),
"entry", builder.GetInsertBlock()->getParent(),
372 builder.GetInsertBlock()->getNextNode());
373 builder.CreateBr(entryBB);
374 builder.SetInsertPoint(entryBB);
377 llvm::BasicBlock &funcEntryBlock =
378 builder.GetInsertBlock()->getParent()->getEntryBlock();
379 return llvm::OpenMPIRBuilder::InsertPointTy(
380 &funcEntryBlock, funcEntryBlock.getFirstInsertionPt());
386 static llvm::CanonicalLoopInfo *
388 llvm::CanonicalLoopInfo *loopInfo =
nullptr;
389 moduleTranslation.
stackWalk<OpenMPLoopInfoStackFrame>(
390 [&](OpenMPLoopInfoStackFrame &frame) {
391 loopInfo = frame.loopInfo;
403 Region ®ion, StringRef blockName, llvm::IRBuilderBase &builder,
406 bool isLoopWrapper = isa<omp::LoopWrapperInterface>(region.
getParentOp());
408 llvm::BasicBlock *continuationBlock =
409 splitBB(builder,
true,
"omp.region.cont");
410 llvm::BasicBlock *sourceBlock = builder.GetInsertBlock();
412 llvm::LLVMContext &llvmContext = builder.getContext();
413 for (
Block &bb : region) {
414 llvm::BasicBlock *llvmBB = llvm::BasicBlock::Create(
415 llvmContext, blockName, builder.GetInsertBlock()->getParent(),
416 builder.GetInsertBlock()->getNextNode());
417 moduleTranslation.
mapBlock(&bb, llvmBB);
420 llvm::Instruction *sourceTerminator = sourceBlock->getTerminator();
427 unsigned numYields = 0;
429 if (!isLoopWrapper) {
430 bool operandsProcessed =
false;
432 if (omp::YieldOp yield = dyn_cast<omp::YieldOp>(bb.getTerminator())) {
433 if (!operandsProcessed) {
434 for (
unsigned i = 0, e = yield->getNumOperands(); i < e; ++i) {
435 continuationBlockPHITypes.push_back(
436 moduleTranslation.
convertType(yield->getOperand(i).getType()));
438 operandsProcessed =
true;
440 assert(continuationBlockPHITypes.size() == yield->getNumOperands() &&
441 "mismatching number of values yielded from the region");
442 for (
unsigned i = 0, e = yield->getNumOperands(); i < e; ++i) {
443 llvm::Type *operandType =
444 moduleTranslation.
convertType(yield->getOperand(i).getType());
446 assert(continuationBlockPHITypes[i] == operandType &&
447 "values of mismatching types yielded from the region");
457 if (!continuationBlockPHITypes.empty())
459 continuationBlockPHIs &&
460 "expected continuation block PHIs if converted regions yield values");
461 if (continuationBlockPHIs) {
462 llvm::IRBuilderBase::InsertPointGuard guard(builder);
463 continuationBlockPHIs->reserve(continuationBlockPHITypes.size());
464 builder.SetInsertPoint(continuationBlock, continuationBlock->begin());
465 for (llvm::Type *ty : continuationBlockPHITypes)
466 continuationBlockPHIs->push_back(builder.CreatePHI(ty, numYields));
472 for (
Block *bb : blocks) {
473 llvm::BasicBlock *llvmBB = moduleTranslation.
lookupBlock(bb);
476 if (bb->isEntryBlock()) {
477 assert(sourceTerminator->getNumSuccessors() == 1 &&
478 "provided entry block has multiple successors");
479 assert(sourceTerminator->getSuccessor(0) == continuationBlock &&
480 "ContinuationBlock is not the successor of the entry block");
481 sourceTerminator->setSuccessor(0, llvmBB);
484 llvm::IRBuilderBase::InsertPointGuard guard(builder);
486 moduleTranslation.
convertBlock(*bb, bb->isEntryBlock(), builder)))
487 return llvm::make_error<PreviouslyReportedError>();
492 builder.CreateBr(continuationBlock);
503 Operation *terminator = bb->getTerminator();
504 if (isa<omp::TerminatorOp, omp::YieldOp>(terminator)) {
505 builder.CreateBr(continuationBlock);
507 for (
unsigned i = 0, e = terminator->
getNumOperands(); i < e; ++i)
508 (*continuationBlockPHIs)[i]->addIncoming(
522 return continuationBlock;
528 case omp::ClauseProcBindKind::Close:
529 return llvm::omp::ProcBindKind::OMP_PROC_BIND_close;
530 case omp::ClauseProcBindKind::Master:
531 return llvm::omp::ProcBindKind::OMP_PROC_BIND_master;
532 case omp::ClauseProcBindKind::Primary:
533 return llvm::omp::ProcBindKind::OMP_PROC_BIND_primary;
534 case omp::ClauseProcBindKind::Spread:
535 return llvm::omp::ProcBindKind::OMP_PROC_BIND_spread;
537 llvm_unreachable(
"Unknown ClauseProcBindKind kind");
547 omp::BlockArgOpenMPOpInterface blockArgIface) {
549 blockArgIface.getBlockArgsPairs(blockArgsPairs);
550 for (
auto [var, arg] : blockArgsPairs)
567 .Case([&](omp::SimdOp op) {
569 cast<omp::BlockArgOpenMPOpInterface>(*op));
570 op.emitWarning() <<
"simd information on composite construct discarded";
574 return op->emitError() <<
"cannot ignore wrapper";
582 auto maskedOp = cast<omp::MaskedOp>(opInst);
583 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
588 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP) {
590 auto ®ion = maskedOp.getRegion();
591 builder.restoreIP(codeGenIP);
599 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
601 llvm::Value *filterVal =
nullptr;
602 if (
auto filterVar = maskedOp.getFilteredThreadId()) {
603 filterVal = moduleTranslation.
lookupValue(filterVar);
605 llvm::LLVMContext &llvmContext = builder.getContext();
609 assert(filterVal !=
nullptr);
610 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
611 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
618 builder.restoreIP(*afterIP);
626 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
627 auto masterOp = cast<omp::MasterOp>(opInst);
632 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP) {
634 auto ®ion = masterOp.getRegion();
635 builder.restoreIP(codeGenIP);
643 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
645 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
646 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
653 builder.restoreIP(*afterIP);
661 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
662 auto criticalOp = cast<omp::CriticalOp>(opInst);
667 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP) {
669 auto ®ion = cast<omp::CriticalOp>(opInst).getRegion();
670 builder.restoreIP(codeGenIP);
678 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
680 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
681 llvm::LLVMContext &llvmContext = moduleTranslation.
getLLVMContext();
682 llvm::Constant *hint =
nullptr;
685 if (criticalOp.getNameAttr()) {
688 auto symbolRef = cast<SymbolRefAttr>(criticalOp.getNameAttr());
689 auto criticalDeclareOp =
690 SymbolTable::lookupNearestSymbolFrom<omp::CriticalDeclareOp>(criticalOp,
694 static_cast<int>(criticalDeclareOp.getHint()));
696 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
698 ompLoc, bodyGenCB, finiCB, criticalOp.getName().value_or(
""), hint);
703 builder.restoreIP(*afterIP);
710 template <
typename OP>
713 cast<omp::BlockArgOpenMPOpInterface>(*op).getPrivateBlockArgs()) {
714 mlirVars.reserve(blockArgs.size());
715 llvmVars.reserve(blockArgs.size());
716 collectPrivatizationDecls<OP>(op);
719 mlirVars.push_back(privateVar);
731 void collectPrivatizationDecls(OP op) {
732 std::optional<ArrayAttr> attr = op.getPrivateSyms();
736 privatizers.reserve(privatizers.size() + attr->size());
737 for (
auto symbolRef : attr->getAsRange<SymbolRefAttr>()) {
744 template <
typename T>
748 std::optional<ArrayAttr> attr = op.getReductionSyms();
752 reductions.reserve(reductions.size() + op.getNumReductionVars());
753 for (
auto symbolRef : attr->getAsRange<SymbolRefAttr>()) {
754 reductions.push_back(
755 SymbolTable::lookupNearestSymbolFrom<omp::DeclareReductionOp>(
766 Region ®ion, StringRef blockName, llvm::IRBuilderBase &builder,
774 if (llvm::hasSingleElement(region)) {
775 llvm::Instruction *potentialTerminator =
776 builder.GetInsertBlock()->empty() ? nullptr
777 : &builder.GetInsertBlock()->back();
779 if (potentialTerminator && potentialTerminator->isTerminator())
780 potentialTerminator->removeFromParent();
781 moduleTranslation.
mapBlock(®ion.
front(), builder.GetInsertBlock());
784 region.
front(),
true, builder)))
788 if (continuationBlockArgs)
790 *continuationBlockArgs,
797 if (potentialTerminator && potentialTerminator->isTerminator()) {
798 llvm::BasicBlock *block = builder.GetInsertBlock();
799 if (block->empty()) {
805 potentialTerminator->insertInto(block, block->begin());
807 potentialTerminator->insertAfter(&block->back());
821 if (continuationBlockArgs)
822 llvm::append_range(*continuationBlockArgs, phis);
823 builder.SetInsertPoint(*continuationBlock,
824 (*continuationBlock)->getFirstInsertionPt());
831 using OwningReductionGen =
832 std::function<llvm::OpenMPIRBuilder::InsertPointOrErrorTy(
833 llvm::OpenMPIRBuilder::InsertPointTy, llvm::Value *, llvm::Value *,
835 using OwningAtomicReductionGen =
836 std::function<llvm::OpenMPIRBuilder::InsertPointOrErrorTy(
837 llvm::OpenMPIRBuilder::InsertPointTy, llvm::Type *, llvm::Value *,
844 static OwningReductionGen
850 OwningReductionGen gen =
851 [&, decl](llvm::OpenMPIRBuilder::InsertPointTy insertPoint,
852 llvm::Value *lhs, llvm::Value *rhs,
853 llvm::Value *&result)
mutable
854 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
855 moduleTranslation.
mapValue(decl.getReductionLhsArg(), lhs);
856 moduleTranslation.
mapValue(decl.getReductionRhsArg(), rhs);
857 builder.restoreIP(insertPoint);
860 "omp.reduction.nonatomic.body", builder,
861 moduleTranslation, &phis)))
862 return llvm::createStringError(
863 "failed to inline `combiner` region of `omp.declare_reduction`");
864 result = llvm::getSingleElement(phis);
865 return builder.saveIP();
874 static OwningAtomicReductionGen
876 llvm::IRBuilderBase &builder,
878 if (decl.getAtomicReductionRegion().empty())
879 return OwningAtomicReductionGen();
884 OwningAtomicReductionGen atomicGen =
885 [&, decl](llvm::OpenMPIRBuilder::InsertPointTy insertPoint, llvm::Type *,
886 llvm::Value *lhs, llvm::Value *rhs)
mutable
887 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
888 moduleTranslation.
mapValue(decl.getAtomicReductionLhsArg(), lhs);
889 moduleTranslation.
mapValue(decl.getAtomicReductionRhsArg(), rhs);
890 builder.restoreIP(insertPoint);
893 "omp.reduction.atomic.body", builder,
894 moduleTranslation, &phis)))
895 return llvm::createStringError(
896 "failed to inline `atomic` region of `omp.declare_reduction`");
897 assert(phis.empty());
898 return builder.saveIP();
907 auto orderedOp = cast<omp::OrderedOp>(opInst);
912 omp::ClauseDepend dependType = *orderedOp.getDoacrossDependType();
913 bool isDependSource = dependType == omp::ClauseDepend::dependsource;
914 unsigned numLoops = *orderedOp.getDoacrossNumLoops();
916 moduleTranslation.
lookupValues(orderedOp.getDoacrossDependVars());
918 size_t indexVecValues = 0;
919 while (indexVecValues < vecValues.size()) {
921 storeValues.reserve(numLoops);
922 for (
unsigned i = 0; i < numLoops; i++) {
923 storeValues.push_back(vecValues[indexVecValues]);
926 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
928 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
929 builder.restoreIP(moduleTranslation.
getOpenMPBuilder()->createOrderedDepend(
930 ompLoc, allocaIP, numLoops, storeValues,
".cnt.addr", isDependSource));
940 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
941 auto orderedRegionOp = cast<omp::OrderedRegionOp>(opInst);
946 auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP) {
948 auto ®ion = cast<omp::OrderedRegionOp>(opInst).getRegion();
949 builder.restoreIP(codeGenIP);
957 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
959 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
960 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
962 ompLoc, bodyGenCB, finiCB, !orderedRegionOp.getParLevelSimd());
967 builder.restoreIP(*afterIP);
973 struct DeferredStore {
974 DeferredStore(llvm::Value *value, llvm::Value *address)
975 : value(value), address(address) {}
978 llvm::Value *address;
985 template <
typename T>
988 llvm::IRBuilderBase &builder,
990 const llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
996 llvm::IRBuilderBase::InsertPointGuard guard(builder);
997 builder.SetInsertPoint(allocaIP.getBlock()->getTerminator());
1000 deferredStores.reserve(loop.getNumReductionVars());
1002 for (std::size_t i = 0; i < loop.getNumReductionVars(); ++i) {
1003 Region &allocRegion = reductionDecls[i].getAllocRegion();
1005 if (allocRegion.
empty())
1010 builder, moduleTranslation, &phis)))
1011 return loop.emitError(
1012 "failed to inline `alloc` region of `omp.declare_reduction`");
1014 assert(phis.size() == 1 &&
"expected one allocation to be yielded");
1015 builder.SetInsertPoint(allocaIP.getBlock()->getTerminator());
1019 llvm::Value *var = builder.CreateAlloca(
1020 moduleTranslation.
convertType(reductionDecls[i].getType()));
1021 deferredStores.emplace_back(phis[0], var);
1023 privateReductionVariables[i] = var;
1024 moduleTranslation.
mapValue(reductionArgs[i], phis[0]);
1025 reductionVariableMap.try_emplace(loop.getReductionVars()[i], phis[0]);
1027 assert(allocRegion.
empty() &&
1028 "allocaction is implicit for by-val reduction");
1029 llvm::Value *var = builder.CreateAlloca(
1030 moduleTranslation.
convertType(reductionDecls[i].getType()));
1031 moduleTranslation.
mapValue(reductionArgs[i], var);
1032 privateReductionVariables[i] = var;
1033 reductionVariableMap.try_emplace(loop.getReductionVars()[i], var);
1041 template <
typename T>
1048 mlir::omp::DeclareReductionOp &reduction = reductionDecls[i];
1049 Region &initializerRegion = reduction.getInitializerRegion();
1052 mlir::Value mlirSource = loop.getReductionVars()[i];
1053 llvm::Value *llvmSource = moduleTranslation.
lookupValue(mlirSource);
1054 assert(llvmSource &&
"lookup reduction var");
1055 moduleTranslation.
mapValue(reduction.getInitializerMoldArg(), llvmSource);
1058 llvm::Value *allocation =
1059 reductionVariableMap.lookup(loop.getReductionVars()[i]);
1060 moduleTranslation.
mapValue(reduction.getInitializerAllocArg(), allocation);
1066 llvm::BasicBlock *block =
nullptr) {
1067 if (block ==
nullptr)
1068 block = builder.GetInsertBlock();
1070 if (block->empty() || block->getTerminator() ==
nullptr)
1071 builder.SetInsertPoint(block);
1073 builder.SetInsertPoint(block->getTerminator());
1081 template <
typename OP>
1082 static LogicalResult
1084 llvm::IRBuilderBase &builder,
1086 llvm::BasicBlock *latestAllocaBlock,
1092 if (op.getNumReductionVars() == 0)
1095 llvm::BasicBlock *initBlock = splitBB(builder,
true,
"omp.reduction.init");
1096 auto allocaIP = llvm::IRBuilderBase::InsertPoint(
1097 latestAllocaBlock, latestAllocaBlock->getTerminator()->getIterator());
1098 builder.restoreIP(allocaIP);
1101 for (
unsigned i = 0; i < op.getNumReductionVars(); ++i) {
1103 if (!reductionDecls[i].getAllocRegion().empty())
1109 byRefVars[i] = builder.CreateAlloca(
1110 moduleTranslation.
convertType(reductionDecls[i].getType()));
1118 for (
auto [data, addr] : deferredStores)
1119 builder.CreateStore(data, addr);
1124 for (
unsigned i = 0; i < op.getNumReductionVars(); ++i) {
1129 reductionVariableMap, i);
1132 "omp.reduction.neutral", builder,
1133 moduleTranslation, &phis)))
1136 assert(phis.size() == 1 &&
"expected one value to be yielded from the "
1137 "reduction neutral element declaration region");
1142 if (!reductionDecls[i].getAllocRegion().empty())
1151 builder.CreateStore(phis[0], byRefVars[i]);
1153 privateReductionVariables[i] = byRefVars[i];
1154 moduleTranslation.
mapValue(reductionArgs[i], phis[0]);
1155 reductionVariableMap.try_emplace(op.getReductionVars()[i], phis[0]);
1158 builder.CreateStore(phis[0], privateReductionVariables[i]);
1165 moduleTranslation.
forgetMapping(reductionDecls[i].getInitializerRegion());
1172 template <
typename T>
1174 T loop, llvm::IRBuilderBase &builder,
1181 unsigned numReductions = loop.getNumReductionVars();
1183 for (
unsigned i = 0; i < numReductions; ++i) {
1184 owningReductionGens.push_back(
1186 owningAtomicReductionGens.push_back(
1191 reductionInfos.reserve(numReductions);
1192 for (
unsigned i = 0; i < numReductions; ++i) {
1193 llvm::OpenMPIRBuilder::ReductionGenAtomicCBTy atomicGen =
nullptr;
1194 if (owningAtomicReductionGens[i])
1195 atomicGen = owningAtomicReductionGens[i];
1196 llvm::Value *variable =
1197 moduleTranslation.
lookupValue(loop.getReductionVars()[i]);
1198 reductionInfos.push_back(
1200 privateReductionVariables[i],
1201 llvm::OpenMPIRBuilder::EvalKind::Scalar,
1202 owningReductionGens[i],
1203 nullptr, atomicGen});
1208 static LogicalResult
1212 llvm::IRBuilderBase &builder, StringRef regionName,
1213 bool shouldLoadCleanupRegionArg =
true) {
1215 if (cleanupRegion->empty())
1221 llvm::Instruction *potentialTerminator =
1222 builder.GetInsertBlock()->empty() ? nullptr
1223 : &builder.GetInsertBlock()->back();
1224 if (potentialTerminator && potentialTerminator->isTerminator())
1225 builder.SetInsertPoint(potentialTerminator);
1226 llvm::Value *privateVarValue =
1227 shouldLoadCleanupRegionArg
1228 ? builder.CreateLoad(
1230 privateVariables[i])
1231 : privateVariables[i];
1236 moduleTranslation)))
1249 OP op, llvm::IRBuilderBase &builder,
1251 llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
1255 if (op.getNumReductionVars() == 0)
1266 owningReductionGens, owningAtomicReductionGens,
1267 privateReductionVariables, reductionInfos);
1272 llvm::UnreachableInst *tempTerminator = builder.CreateUnreachable();
1273 builder.SetInsertPoint(tempTerminator);
1274 llvm::OpenMPIRBuilder::InsertPointOrErrorTy contInsertPoint =
1275 ompBuilder->createReductions(builder.saveIP(), allocaIP, reductionInfos,
1276 isByRef, op.getNowait());
1281 if (!contInsertPoint->getBlock())
1282 return op->emitOpError() <<
"failed to convert reductions";
1284 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
1285 ompBuilder->createBarrier(*contInsertPoint, llvm::omp::OMPD_for);
1290 tempTerminator->eraseFromParent();
1291 builder.restoreIP(*afterIP);
1295 llvm::transform(reductionDecls, std::back_inserter(reductionRegions),
1296 [](omp::DeclareReductionOp reductionDecl) {
1297 return &reductionDecl.getCleanupRegion();
1300 moduleTranslation, builder,
1301 "omp.reduction.cleanup");
1312 template <
typename OP>
1316 llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
1321 if (op.getNumReductionVars() == 0)
1327 allocaIP, reductionDecls,
1328 privateReductionVariables, reductionVariableMap,
1329 deferredStores, isByRef)))
1333 allocaIP.getBlock(), reductionDecls,
1334 privateReductionVariables, reductionVariableMap,
1335 isByRef, deferredStores);
1345 static llvm::Value *
1349 if (mappedPrivateVars ==
nullptr || !mappedPrivateVars->contains(privateVar))
1352 Value blockArg = (*mappedPrivateVars)[privateVar];
1355 assert(isa<LLVM::LLVMPointerType>(blockArgType) &&
1356 "A block argument corresponding to a mapped var should have "
1359 if (privVarType == blockArgType)
1366 if (!isa<LLVM::LLVMPointerType>(privVarType))
1367 return builder.CreateLoad(moduleTranslation.
convertType(privVarType),
1380 llvm::Value *llvmPrivateVar, llvm::BasicBlock *privInitBlock,
1382 Region &initRegion = privDecl.getInitRegion();
1383 if (initRegion.
empty())
1384 return llvmPrivateVar;
1388 mlirPrivVar, builder, moduleTranslation, mappedPrivateVars);
1389 assert(nonPrivateVar);
1390 moduleTranslation.
mapValue(privDecl.getInitMoldArg(), nonPrivateVar);
1391 moduleTranslation.
mapValue(privDecl.getInitPrivateArg(), llvmPrivateVar);
1396 moduleTranslation, &phis)))
1397 return llvm::createStringError(
1398 "failed to inline `init` region of `omp.private`");
1400 assert(phis.size() == 1 &&
"expected one allocation to be yielded");
1419 return llvm::Error::success();
1421 llvm::BasicBlock *privInitBlock = splitBB(builder,
true,
"omp.private.init");
1427 auto [privDecl, mlirPrivVar, blockArg, llvmPrivateVar] = zip;
1429 builder, moduleTranslation, privDecl, mlirPrivVar, blockArg,
1430 llvmPrivateVar, privInitBlock, mappedPrivateVars);
1433 return privVarOrErr.takeError();
1435 llvmPrivateVar = privVarOrErr.get();
1436 moduleTranslation.
mapValue(blockArg, llvmPrivateVar);
1441 return llvm::Error::success();
1451 const llvm::OpenMPIRBuilder::InsertPointTy &allocaIP,
1454 llvm::Instruction *allocaTerminator = allocaIP.getBlock()->getTerminator();
1455 splitBB(llvm::OpenMPIRBuilder::InsertPointTy(allocaIP.getBlock(),
1456 allocaTerminator->getIterator()),
1457 true, allocaTerminator->getStableDebugLoc(),
1458 "omp.region.after_alloca");
1460 llvm::IRBuilderBase::InsertPointGuard guard(builder);
1462 allocaTerminator = allocaIP.getBlock()->getTerminator();
1463 builder.SetInsertPoint(allocaTerminator);
1465 assert(allocaTerminator->getNumSuccessors() == 1 &&
1466 "This is an unconditional branch created by splitBB");
1468 llvm::BasicBlock *afterAllocas = allocaTerminator->getSuccessor(0);
1470 unsigned int allocaAS =
1471 moduleTranslation.
getLLVMModule()->getDataLayout().getAllocaAddrSpace();
1474 .getProgramAddressSpace();
1476 for (
auto [privDecl, mlirPrivVar, blockArg] :
1479 llvm::Type *llvmAllocType =
1480 moduleTranslation.
convertType(privDecl.getType());
1481 builder.SetInsertPoint(allocaIP.getBlock()->getTerminator());
1482 llvm::Value *llvmPrivateVar = builder.CreateAlloca(
1483 llvmAllocType,
nullptr,
"omp.private.alloc");
1484 if (allocaAS != defaultAS)
1485 llvmPrivateVar = builder.CreateAddrSpaceCast(llvmPrivateVar,
1486 builder.getPtrTy(defaultAS));
1488 privateVarsInfo.
llvmVars.push_back(llvmPrivateVar);
1491 return afterAllocas;
1494 static LogicalResult
1501 bool needsFirstprivate =
1502 llvm::any_of(privateDecls, [](omp::PrivateClauseOp &privOp) {
1503 return privOp.getDataSharingType() ==
1504 omp::DataSharingClauseType::FirstPrivate;
1507 if (!needsFirstprivate)
1510 llvm::BasicBlock *copyBlock =
1511 splitBB(builder,
true,
"omp.private.copy");
1514 for (
auto [decl, mlirVar, llvmVar] :
1515 llvm::zip_equal(privateDecls, mlirPrivateVars, llvmPrivateVars)) {
1516 if (decl.getDataSharingType() != omp::DataSharingClauseType::FirstPrivate)
1520 Region ©Region = decl.getCopyRegion();
1523 llvm::Value *nonPrivateVar = moduleTranslation.
lookupValue(mlirVar);
1524 assert(nonPrivateVar);
1525 moduleTranslation.
mapValue(decl.getCopyMoldArg(), nonPrivateVar);
1528 moduleTranslation.
mapValue(decl.getCopyPrivateArg(), llvmVar);
1532 moduleTranslation)))
1533 return decl.emitError(
"failed to inline `copy` region of `omp.private`");
1548 static LogicalResult
1555 llvm::transform(privateDecls, std::back_inserter(privateCleanupRegions),
1556 [](omp::PrivateClauseOp privatizer) {
1557 return &privatizer.getDeallocRegion();
1561 privateCleanupRegions, llvmPrivateVars, moduleTranslation, builder,
1562 "omp.private.dealloc",
false)))
1563 return mlir::emitError(loc,
"failed to inline `dealloc` region of an "
1564 "`omp.private` op in");
1569 static LogicalResult
1572 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1573 using StorableBodyGenCallbackTy =
1574 llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
1576 auto sectionsOp = cast<omp::SectionsOp>(opInst);
1582 assert(isByRef.size() == sectionsOp.getNumReductionVars());
1586 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
1590 sectionsOp.getNumReductionVars());
1594 cast<omp::BlockArgOpenMPOpInterface>(opInst).getReductionBlockArgs();
1597 sectionsOp, reductionArgs, builder, moduleTranslation, allocaIP,
1598 reductionDecls, privateReductionVariables, reductionVariableMap,
1605 auto sectionOp = dyn_cast<omp::SectionOp>(op);
1609 Region ®ion = sectionOp.getRegion();
1610 auto sectionCB = [§ionsOp, ®ion, &builder, &moduleTranslation](
1611 InsertPointTy allocaIP, InsertPointTy codeGenIP) {
1612 builder.restoreIP(codeGenIP);
1619 sectionsOp.getRegion().getNumArguments());
1620 for (
auto [sectionsArg, sectionArg] : llvm::zip_equal(
1621 sectionsOp.getRegion().getArguments(), region.
getArguments())) {
1622 llvm::Value *llvmVal = moduleTranslation.
lookupValue(sectionsArg);
1624 moduleTranslation.
mapValue(sectionArg, llvmVal);
1631 sectionCBs.push_back(sectionCB);
1637 if (sectionCBs.empty())
1640 assert(isa<omp::SectionOp>(*sectionsOp.getRegion().op_begin()));
1645 auto privCB = [&](InsertPointTy, InsertPointTy codeGenIP, llvm::Value &,
1646 llvm::Value &vPtr, llvm::Value *&replacementValue)
1647 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
1648 replacementValue = &vPtr;
1654 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
1657 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
1658 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
1660 ompLoc, allocaIP, sectionCBs, privCB, finiCB,
false,
1661 sectionsOp.getNowait());
1666 builder.restoreIP(*afterIP);
1670 allocaIP, reductionDecls,
1671 privateReductionVariables, isByRef);
1675 static LogicalResult
1678 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1679 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
1684 auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codegenIP) {
1685 builder.restoreIP(codegenIP);
1687 builder, moduleTranslation)
1690 auto finiCB = [&](InsertPointTy codeGenIP) {
return llvm::Error::success(); };
1694 std::optional<ArrayAttr> cpFuncs = singleOp.getCopyprivateSyms();
1697 for (
size_t i = 0, e = cpVars.size(); i < e; ++i) {
1698 llvmCPVars.push_back(moduleTranslation.
lookupValue(cpVars[i]));
1699 auto llvmFuncOp = SymbolTable::lookupNearestSymbolFrom<LLVM::LLVMFuncOp>(
1700 singleOp, cast<SymbolRefAttr>((*cpFuncs)[i]));
1701 llvmCPFuncs.push_back(
1705 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
1707 ompLoc, bodyCB, finiCB, singleOp.getNowait(), llvmCPVars,
1713 builder.restoreIP(*afterIP);
1718 static LogicalResult
1721 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1725 auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codegenIP) {
1727 moduleTranslation, allocaIP);
1728 builder.restoreIP(codegenIP);
1734 llvm::Value *numTeamsLower =
nullptr;
1735 if (
Value numTeamsLowerVar = op.getNumTeamsLower())
1736 numTeamsLower = moduleTranslation.
lookupValue(numTeamsLowerVar);
1738 llvm::Value *numTeamsUpper =
nullptr;
1739 if (
Value numTeamsUpperVar = op.getNumTeamsUpper())
1740 numTeamsUpper = moduleTranslation.
lookupValue(numTeamsUpperVar);
1742 llvm::Value *threadLimit =
nullptr;
1743 if (
Value threadLimitVar = op.getThreadLimit())
1744 threadLimit = moduleTranslation.
lookupValue(threadLimitVar);
1746 llvm::Value *ifExpr =
nullptr;
1747 if (
Value ifVar = op.getIfExpr())
1750 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
1751 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
1753 ompLoc, bodyCB, numTeamsLower, numTeamsUpper, threadLimit, ifExpr);
1758 builder.restoreIP(*afterIP);
1766 if (dependVars.empty())
1768 for (
auto dep : llvm::zip(dependVars, dependKinds->getValue())) {
1769 llvm::omp::RTLDependenceKindTy type;
1771 cast<mlir::omp::ClauseTaskDependAttr>(std::get<1>(dep)).getValue()) {
1772 case mlir::omp::ClauseTaskDepend::taskdependin:
1773 type = llvm::omp::RTLDependenceKindTy::DepIn;
1778 case mlir::omp::ClauseTaskDepend::taskdependout:
1779 case mlir::omp::ClauseTaskDepend::taskdependinout:
1780 type = llvm::omp::RTLDependenceKindTy::DepInOut;
1782 case mlir::omp::ClauseTaskDepend::taskdependmutexinoutset:
1783 type = llvm::omp::RTLDependenceKindTy::DepMutexInOutSet;
1785 case mlir::omp::ClauseTaskDepend::taskdependinoutset:
1786 type = llvm::omp::RTLDependenceKindTy::DepInOutSet;
1789 llvm::Value *depVal = moduleTranslation.
lookupValue(std::get<0>(dep));
1790 llvm::OpenMPIRBuilder::DependData dd(type, depVal->getType(), depVal);
1791 dds.emplace_back(dd);
1798 class TaskContextStructManager {
1800 TaskContextStructManager(llvm::IRBuilderBase &builder,
1803 : builder{builder}, moduleTranslation{moduleTranslation},
1804 privateDecls{privateDecls} {}
1810 void generateTaskContextStruct();
1816 void createGEPsToPrivateVars();
1819 void freeStructPtr();
1822 return llvmPrivateVarGEPs;
1825 llvm::Value *getStructPtr() {
return structPtr; }
1828 llvm::IRBuilderBase &builder;
1840 llvm::Value *structPtr =
nullptr;
1842 llvm::Type *structTy =
nullptr;
1846 void TaskContextStructManager::generateTaskContextStruct() {
1847 if (privateDecls.empty())
1849 privateVarTypes.reserve(privateDecls.size());
1851 for (omp::PrivateClauseOp &privOp : privateDecls) {
1854 if (!privOp.readsFromMold())
1856 Type mlirType = privOp.getType();
1857 privateVarTypes.push_back(moduleTranslation.convertType(mlirType));
1863 llvm::DataLayout dataLayout =
1864 builder.GetInsertBlock()->getModule()->getDataLayout();
1865 llvm::Type *intPtrTy = builder.getIntPtrTy(dataLayout);
1866 llvm::Constant *allocSize = llvm::ConstantExpr::getSizeOf(structTy);
1869 structPtr = builder.CreateMalloc(intPtrTy, structTy, allocSize,
1871 "omp.task.context_ptr");
1874 void TaskContextStructManager::createGEPsToPrivateVars() {
1876 assert(privateVarTypes.empty());
1881 llvmPrivateVarGEPs.clear();
1882 llvmPrivateVarGEPs.reserve(privateDecls.size());
1883 llvm::Value *zero = builder.getInt32(0);
1885 for (
auto privDecl : privateDecls) {
1886 if (!privDecl.readsFromMold()) {
1888 llvmPrivateVarGEPs.push_back(
nullptr);
1891 llvm::Value *iVal = builder.getInt32(i);
1892 llvm::Value *gep = builder.CreateGEP(structTy, structPtr, {zero, iVal});
1893 llvmPrivateVarGEPs.push_back(gep);
1898 void TaskContextStructManager::freeStructPtr() {
1902 llvm::IRBuilderBase::InsertPointGuard guard{builder};
1904 builder.SetInsertPoint(builder.GetInsertBlock()->getTerminator());
1905 builder.CreateFree(structPtr);
1909 static LogicalResult
1912 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1917 TaskContextStructManager taskStructMgr{builder, moduleTranslation,
1929 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
1934 assert(builder.GetInsertPoint() == builder.GetInsertBlock()->end());
1935 llvm::BasicBlock *taskStartBlock = llvm::BasicBlock::Create(
1936 builder.getContext(),
"omp.task.start",
1937 builder.GetInsertBlock()->getParent());
1938 llvm::Instruction *branchToTaskStartBlock = builder.CreateBr(taskStartBlock);
1939 builder.SetInsertPoint(branchToTaskStartBlock);
1942 llvm::BasicBlock *copyBlock =
1943 splitBB(builder,
true,
"omp.private.copy");
1944 llvm::BasicBlock *initBlock =
1945 splitBB(builder,
true,
"omp.private.init");
1961 moduleTranslation, allocaIP);
1964 builder.SetInsertPoint(initBlock->getTerminator());
1967 taskStructMgr.generateTaskContextStruct();
1974 taskStructMgr.createGEPsToPrivateVars();
1976 for (
auto [privDecl, mlirPrivVar, blockArg, llvmPrivateVarAlloc] :
1979 taskStructMgr.getLLVMPrivateVarGEPs())) {
1981 if (!privDecl.readsFromMold())
1983 assert(llvmPrivateVarAlloc &&
1984 "reads from mold so shouldn't have been skipped");
1987 initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar,
1988 blockArg, llvmPrivateVarAlloc, initBlock);
1989 if (!privateVarOrErr)
1990 return handleError(privateVarOrErr, *taskOp.getOperation());
1992 llvm::IRBuilderBase::InsertPointGuard guard(builder);
1993 builder.SetInsertPoint(builder.GetInsertBlock()->getTerminator());
2000 if ((privateVarOrErr.get() != llvmPrivateVarAlloc) &&
2001 !mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
2002 builder.CreateStore(privateVarOrErr.get(), llvmPrivateVarAlloc);
2004 llvmPrivateVarAlloc = builder.CreateLoad(privateVarOrErr.get()->getType(),
2005 llvmPrivateVarAlloc);
2007 assert(llvmPrivateVarAlloc->getType() ==
2008 moduleTranslation.
convertType(blockArg.getType()));
2018 builder, moduleTranslation, privateVarsInfo.
mlirVars,
2019 taskStructMgr.getLLVMPrivateVarGEPs(), privateVarsInfo.
privatizers)))
2020 return llvm::failure();
2023 builder.SetInsertPoint(taskStartBlock);
2025 auto bodyCB = [&](InsertPointTy allocaIP,
2026 InsertPointTy codegenIP) -> llvm::Error {
2030 moduleTranslation, allocaIP);
2033 builder.restoreIP(codegenIP);
2035 llvm::BasicBlock *privInitBlock =
nullptr;
2040 auto [blockArg, privDecl, mlirPrivVar] = zip;
2042 if (privDecl.readsFromMold())
2045 llvm::IRBuilderBase::InsertPointGuard guard(builder);
2046 llvm::Type *llvmAllocType =
2047 moduleTranslation.
convertType(privDecl.getType());
2048 builder.SetInsertPoint(allocaIP.getBlock()->getTerminator());
2049 llvm::Value *llvmPrivateVar = builder.CreateAlloca(
2050 llvmAllocType,
nullptr,
"omp.private.alloc");
2053 initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar,
2054 blockArg, llvmPrivateVar, privInitBlock);
2055 if (!privateVarOrError)
2056 return privateVarOrError.takeError();
2057 moduleTranslation.
mapValue(blockArg, privateVarOrError.get());
2058 privateVarsInfo.
llvmVars[i] = privateVarOrError.get();
2061 taskStructMgr.createGEPsToPrivateVars();
2062 for (
auto [i, llvmPrivVar] :
2065 assert(privateVarsInfo.
llvmVars[i] &&
2066 "This is added in the loop above");
2069 privateVarsInfo.
llvmVars[i] = llvmPrivVar;
2074 for (
auto [blockArg, llvmPrivateVar, privateDecl] :
2078 if (!privateDecl.readsFromMold())
2081 if (!mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) {
2082 llvmPrivateVar = builder.CreateLoad(
2083 moduleTranslation.
convertType(blockArg.getType()), llvmPrivateVar);
2085 assert(llvmPrivateVar->getType() ==
2086 moduleTranslation.
convertType(blockArg.getType()));
2087 moduleTranslation.
mapValue(blockArg, llvmPrivateVar);
2091 taskOp.getRegion(),
"omp.task.region", builder, moduleTranslation);
2092 if (failed(
handleError(continuationBlockOrError, *taskOp)))
2093 return llvm::make_error<PreviouslyReportedError>();
2095 builder.SetInsertPoint(continuationBlockOrError.get()->getTerminator());
2100 return llvm::make_error<PreviouslyReportedError>();
2103 taskStructMgr.freeStructPtr();
2105 return llvm::Error::success();
2110 moduleTranslation, dds);
2112 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2113 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2115 ompLoc, allocaIP, bodyCB, !taskOp.getUntied(),
2117 moduleTranslation.
lookupValue(taskOp.getIfExpr()), dds,
2118 taskOp.getMergeable(),
2119 moduleTranslation.
lookupValue(taskOp.getEventHandle()),
2120 moduleTranslation.
lookupValue(taskOp.getPriority()));
2125 builder.restoreIP(*afterIP);
2130 static LogicalResult
2133 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2137 auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codegenIP) {
2138 builder.restoreIP(codegenIP);
2140 builder, moduleTranslation)
2145 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2146 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2153 builder.restoreIP(*afterIP);
2157 static LogicalResult
2168 static LogicalResult
2172 auto wsloopOp = cast<omp::WsloopOp>(opInst);
2176 auto loopOp = cast<omp::LoopNestOp>(wsloopOp.getWrappedLoop());
2178 assert(isByRef.size() == wsloopOp.getNumReductionVars());
2182 wsloopOp.getScheduleKind().value_or(omp::ClauseScheduleKind::Static);
2185 llvm::Value *step = moduleTranslation.
lookupValue(loopOp.getLoopSteps()[0]);
2186 llvm::Type *ivType = step->getType();
2187 llvm::Value *chunk =
nullptr;
2188 if (wsloopOp.getScheduleChunk()) {
2189 llvm::Value *chunkVar =
2190 moduleTranslation.
lookupValue(wsloopOp.getScheduleChunk());
2191 chunk = builder.CreateSExtOrTrunc(chunkVar, ivType);
2198 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
2202 wsloopOp.getNumReductionVars());
2205 builder, moduleTranslation, privateVarsInfo, allocaIP);
2212 cast<omp::BlockArgOpenMPOpInterface>(opInst).getReductionBlockArgs();
2217 moduleTranslation, allocaIP, reductionDecls,
2218 privateReductionVariables, reductionVariableMap,
2219 deferredStores, isByRef)))
2228 builder, moduleTranslation, privateVarsInfo.
mlirVars,
2232 assert(afterAllocas.get()->getSinglePredecessor());
2235 afterAllocas.get()->getSinglePredecessor(),
2236 reductionDecls, privateReductionVariables,
2237 reductionVariableMap, isByRef, deferredStores)))
2241 bool isOrdered = wsloopOp.getOrdered().has_value();
2242 std::optional<omp::ScheduleModifier> scheduleMod = wsloopOp.getScheduleMod();
2243 bool isSimd = wsloopOp.getScheduleSimd();
2244 bool loopNeedsBarrier = !wsloopOp.getNowait();
2249 llvm::omp::WorksharingLoopType workshareLoopType =
2250 llvm::isa_and_present<omp::DistributeOp>(opInst.
getParentOp())
2251 ? llvm::omp::WorksharingLoopType::DistributeForStaticLoop
2252 : llvm::omp::WorksharingLoopType::ForStaticLoop;
2254 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2256 wsloopOp.getRegion(),
"omp.wsloop.region", builder, moduleTranslation);
2261 builder.SetInsertPoint(*regionBlock, (*regionBlock)->begin());
2264 llvm::OpenMPIRBuilder::InsertPointOrErrorTy wsloopIP =
2265 ompBuilder->applyWorkshareLoop(
2266 ompLoc.DL, loopInfo, allocaIP, loopNeedsBarrier,
2267 convertToScheduleKind(schedule), chunk, isSimd,
2268 scheduleMod == omp::ScheduleModifier::monotonic,
2269 scheduleMod == omp::ScheduleModifier::nonmonotonic, isOrdered,
2277 allocaIP, reductionDecls,
2278 privateReductionVariables, isByRef)))
2287 static LogicalResult
2290 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2292 assert(isByRef.size() == opInst.getNumReductionVars());
2304 opInst.getNumReductionVars());
2307 auto bodyGenCB = [&](InsertPointTy allocaIP,
2308 InsertPointTy codeGenIP) -> llvm::Error {
2310 builder, moduleTranslation, privateVarsInfo, allocaIP);
2312 return llvm::make_error<PreviouslyReportedError>();
2318 cast<omp::BlockArgOpenMPOpInterface>(*opInst).getReductionBlockArgs();
2321 InsertPointTy(allocaIP.getBlock(),
2322 allocaIP.getBlock()->getTerminator()->getIterator());
2325 opInst, reductionArgs, builder, moduleTranslation, allocaIP,
2326 reductionDecls, privateReductionVariables, reductionVariableMap,
2327 deferredStores, isByRef)))
2328 return llvm::make_error<PreviouslyReportedError>();
2330 assert(afterAllocas.get()->getSinglePredecessor());
2331 builder.restoreIP(codeGenIP);
2337 return llvm::make_error<PreviouslyReportedError>();
2340 builder, moduleTranslation, privateVarsInfo.
mlirVars,
2342 return llvm::make_error<PreviouslyReportedError>();
2346 afterAllocas.get()->getSinglePredecessor(),
2347 reductionDecls, privateReductionVariables,
2348 reductionVariableMap, isByRef, deferredStores)))
2349 return llvm::make_error<PreviouslyReportedError>();
2354 moduleTranslation, allocaIP);
2358 opInst.getRegion(),
"omp.par.region", builder, moduleTranslation);
2360 return regionBlock.takeError();
2363 if (opInst.getNumReductionVars() > 0) {
2369 owningReductionGens, owningAtomicReductionGens,
2370 privateReductionVariables, reductionInfos);
2373 builder.SetInsertPoint((*regionBlock)->getTerminator());
2376 llvm::UnreachableInst *tempTerminator = builder.CreateUnreachable();
2377 builder.SetInsertPoint(tempTerminator);
2379 llvm::OpenMPIRBuilder::InsertPointOrErrorTy contInsertPoint =
2380 ompBuilder->createReductions(builder.saveIP(), allocaIP,
2381 reductionInfos, isByRef,
false);
2382 if (!contInsertPoint)
2383 return contInsertPoint.takeError();
2385 if (!contInsertPoint->getBlock())
2386 return llvm::make_error<PreviouslyReportedError>();
2388 tempTerminator->eraseFromParent();
2389 builder.restoreIP(*contInsertPoint);
2392 return llvm::Error::success();
2395 auto privCB = [](InsertPointTy allocaIP, InsertPointTy codeGenIP,
2396 llvm::Value &, llvm::Value &val, llvm::Value *&replVal) {
2405 auto finiCB = [&](InsertPointTy codeGenIP) -> llvm::Error {
2406 InsertPointTy oldIP = builder.saveIP();
2407 builder.restoreIP(codeGenIP);
2412 llvm::transform(reductionDecls, std::back_inserter(reductionCleanupRegions),
2413 [](omp::DeclareReductionOp reductionDecl) {
2414 return &reductionDecl.getCleanupRegion();
2417 reductionCleanupRegions, privateReductionVariables,
2418 moduleTranslation, builder,
"omp.reduction.cleanup")))
2419 return llvm::createStringError(
2420 "failed to inline `cleanup` region of `omp.declare_reduction`");
2425 return llvm::make_error<PreviouslyReportedError>();
2427 builder.restoreIP(oldIP);
2428 return llvm::Error::success();
2431 llvm::Value *ifCond =
nullptr;
2432 if (
auto ifVar = opInst.getIfExpr())
2434 llvm::Value *numThreads =
nullptr;
2435 if (
auto numThreadsVar = opInst.getNumThreads())
2436 numThreads = moduleTranslation.
lookupValue(numThreadsVar);
2437 auto pbKind = llvm::omp::OMP_PROC_BIND_default;
2438 if (
auto bind = opInst.getProcBindKind())
2441 bool isCancellable =
false;
2443 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
2445 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2447 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2448 ompBuilder->createParallel(ompLoc, allocaIP, bodyGenCB, privCB, finiCB,
2449 ifCond, numThreads, pbKind, isCancellable);
2454 builder.restoreIP(*afterIP);
2459 static llvm::omp::OrderKind
2462 return llvm::omp::OrderKind::OMP_ORDER_unknown;
2464 case omp::ClauseOrderKind::Concurrent:
2465 return llvm::omp::OrderKind::OMP_ORDER_concurrent;
2467 llvm_unreachable(
"Unknown ClauseOrderKind kind");
2471 static LogicalResult
2475 auto simdOp = cast<omp::SimdOp>(opInst);
2481 if (simdOp.isComposite()) {
2486 builder, moduleTranslation);
2494 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
2498 builder, moduleTranslation, privateVarsInfo, allocaIP);
2507 llvm::ConstantInt *simdlen =
nullptr;
2508 if (std::optional<uint64_t> simdlenVar = simdOp.getSimdlen())
2509 simdlen = builder.getInt64(simdlenVar.value());
2511 llvm::ConstantInt *safelen =
nullptr;
2512 if (std::optional<uint64_t> safelenVar = simdOp.getSafelen())
2513 safelen = builder.getInt64(safelenVar.value());
2515 llvm::MapVector<llvm::Value *, llvm::Value *> alignedVars;
2517 llvm::BasicBlock *sourceBlock = builder.GetInsertBlock();
2518 std::optional<ArrayAttr> alignmentValues = simdOp.getAlignments();
2520 for (
size_t i = 0; i < operands.size(); ++i) {
2521 llvm::Value *alignment =
nullptr;
2522 llvm::Value *llvmVal = moduleTranslation.
lookupValue(operands[i]);
2523 llvm::Type *ty = llvmVal->getType();
2525 auto intAttr = cast<IntegerAttr>((*alignmentValues)[i]);
2526 alignment = builder.getInt64(intAttr.getInt());
2527 assert(ty->isPointerTy() &&
"Invalid type for aligned variable");
2528 assert(alignment &&
"Invalid alignment value");
2529 auto curInsert = builder.saveIP();
2530 builder.SetInsertPoint(sourceBlock);
2531 llvmVal = builder.CreateLoad(ty, llvmVal);
2532 builder.restoreIP(curInsert);
2533 alignedVars[llvmVal] = alignment;
2537 simdOp.getRegion(),
"omp.simd.region", builder, moduleTranslation);
2542 builder.SetInsertPoint(*regionBlock, (*regionBlock)->begin());
2544 ompBuilder->applySimd(loopInfo, alignedVars,
2546 ? moduleTranslation.
lookupValue(simdOp.getIfExpr())
2548 order, simdlen, safelen);
2556 static LogicalResult
2560 auto loopOp = cast<omp::LoopNestOp>(opInst);
2563 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2568 auto bodyGen = [&](llvm::OpenMPIRBuilder::InsertPointTy ip,
2569 llvm::Value *iv) -> llvm::Error {
2572 loopOp.getRegion().front().getArgument(loopInfos.size()), iv);
2577 bodyInsertPoints.push_back(ip);
2579 if (loopInfos.size() != loopOp.getNumLoops() - 1)
2580 return llvm::Error::success();
2583 builder.restoreIP(ip);
2585 loopOp.getRegion(),
"omp.loop_nest.region", builder, moduleTranslation);
2587 return regionBlock.takeError();
2589 builder.SetInsertPoint(*regionBlock, (*regionBlock)->begin());
2590 return llvm::Error::success();
2598 for (
unsigned i = 0, e = loopOp.getNumLoops(); i < e; ++i) {
2599 llvm::Value *lowerBound =
2600 moduleTranslation.
lookupValue(loopOp.getLoopLowerBounds()[i]);
2601 llvm::Value *upperBound =
2602 moduleTranslation.
lookupValue(loopOp.getLoopUpperBounds()[i]);
2603 llvm::Value *step = moduleTranslation.
lookupValue(loopOp.getLoopSteps()[i]);
2608 llvm::OpenMPIRBuilder::LocationDescription loc = ompLoc;
2609 llvm::OpenMPIRBuilder::InsertPointTy computeIP = ompLoc.IP;
2611 loc = llvm::OpenMPIRBuilder::LocationDescription(bodyInsertPoints.back(),
2613 computeIP = loopInfos.front()->getPreheaderIP();
2617 ompBuilder->createCanonicalLoop(
2618 loc, bodyGen, lowerBound, upperBound, step,
2619 true, loopOp.getLoopInclusive(), computeIP);
2624 loopInfos.push_back(*loopResult);
2629 llvm::OpenMPIRBuilder::InsertPointTy afterIP =
2630 loopInfos.front()->getAfterIP();
2634 moduleTranslation.
stackWalk<OpenMPLoopInfoStackFrame>(
2635 [&](OpenMPLoopInfoStackFrame &frame) {
2636 frame.loopInfo = ompBuilder->collapseLoops(ompLoc.DL, loopInfos, {});
2644 builder.restoreIP(afterIP);
2649 static llvm::AtomicOrdering
2652 return llvm::AtomicOrdering::Monotonic;
2655 case omp::ClauseMemoryOrderKind::Seq_cst:
2656 return llvm::AtomicOrdering::SequentiallyConsistent;
2657 case omp::ClauseMemoryOrderKind::Acq_rel:
2658 return llvm::AtomicOrdering::AcquireRelease;
2659 case omp::ClauseMemoryOrderKind::Acquire:
2660 return llvm::AtomicOrdering::Acquire;
2661 case omp::ClauseMemoryOrderKind::Release:
2662 return llvm::AtomicOrdering::Release;
2663 case omp::ClauseMemoryOrderKind::Relaxed:
2664 return llvm::AtomicOrdering::Monotonic;
2666 llvm_unreachable(
"Unknown ClauseMemoryOrderKind kind");
2670 static LogicalResult
2673 auto readOp = cast<omp::AtomicReadOp>(opInst);
2679 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2682 llvm::Value *x = moduleTranslation.
lookupValue(readOp.getX());
2683 llvm::Value *v = moduleTranslation.
lookupValue(readOp.getV());
2685 llvm::Type *elementType =
2686 moduleTranslation.
convertType(readOp.getElementType());
2688 llvm::OpenMPIRBuilder::AtomicOpValue V = {v, elementType,
false,
false};
2689 llvm::OpenMPIRBuilder::AtomicOpValue X = {x, elementType,
false,
false};
2690 builder.restoreIP(ompBuilder->createAtomicRead(ompLoc, X, V, AO));
2695 static LogicalResult
2698 auto writeOp = cast<omp::AtomicWriteOp>(opInst);
2704 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2706 llvm::Value *expr = moduleTranslation.
lookupValue(writeOp.getExpr());
2707 llvm::Value *dest = moduleTranslation.
lookupValue(writeOp.getX());
2708 llvm::Type *ty = moduleTranslation.
convertType(writeOp.getExpr().getType());
2709 llvm::OpenMPIRBuilder::AtomicOpValue x = {dest, ty,
false,
2711 builder.restoreIP(ompBuilder->createAtomicWrite(ompLoc, x, expr, ao));
2719 .Case([&](LLVM::AddOp) {
return llvm::AtomicRMWInst::BinOp::Add; })
2720 .Case([&](LLVM::SubOp) {
return llvm::AtomicRMWInst::BinOp::Sub; })
2721 .Case([&](LLVM::AndOp) {
return llvm::AtomicRMWInst::BinOp::And; })
2722 .Case([&](LLVM::OrOp) {
return llvm::AtomicRMWInst::BinOp::Or; })
2723 .Case([&](LLVM::XOrOp) {
return llvm::AtomicRMWInst::BinOp::Xor; })
2724 .Case([&](LLVM::UMaxOp) {
return llvm::AtomicRMWInst::BinOp::UMax; })
2725 .Case([&](LLVM::UMinOp) {
return llvm::AtomicRMWInst::BinOp::UMin; })
2726 .Case([&](LLVM::FAddOp) {
return llvm::AtomicRMWInst::BinOp::FAdd; })
2727 .Case([&](LLVM::FSubOp) {
return llvm::AtomicRMWInst::BinOp::FSub; })
2728 .Default(llvm::AtomicRMWInst::BinOp::BAD_BINOP);
2732 static LogicalResult
2734 llvm::IRBuilderBase &builder,
2741 auto &innerOpList = opInst.getRegion().front().getOperations();
2742 bool isXBinopExpr{
false};
2743 llvm::AtomicRMWInst::BinOp binop;
2745 llvm::Value *llvmExpr =
nullptr;
2746 llvm::Value *llvmX =
nullptr;
2747 llvm::Type *llvmXElementType =
nullptr;
2748 if (innerOpList.size() == 2) {
2754 opInst.getRegion().getArgument(0))) {
2755 return opInst.emitError(
"no atomic update operation with region argument"
2756 " as operand found inside atomic.update region");
2759 isXBinopExpr = innerOp.
getOperand(0) == opInst.getRegion().getArgument(0);
2761 llvmExpr = moduleTranslation.
lookupValue(mlirExpr);
2765 binop = llvm::AtomicRMWInst::BinOp::BAD_BINOP;
2767 llvmX = moduleTranslation.
lookupValue(opInst.getX());
2769 opInst.getRegion().getArgument(0).getType());
2770 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {llvmX, llvmXElementType,
2774 llvm::AtomicOrdering atomicOrdering =
2779 [&opInst, &moduleTranslation](
2780 llvm::Value *atomicx,
2783 moduleTranslation.
mapValue(*opInst.getRegion().args_begin(), atomicx);
2784 moduleTranslation.
mapBlock(&bb, builder.GetInsertBlock());
2785 if (failed(moduleTranslation.
convertBlock(bb,
true, builder)))
2786 return llvm::make_error<PreviouslyReportedError>();
2788 omp::YieldOp yieldop = dyn_cast<omp::YieldOp>(bb.
getTerminator());
2789 assert(yieldop && yieldop.getResults().size() == 1 &&
2790 "terminator must be omp.yield op and it must have exactly one "
2792 return moduleTranslation.
lookupValue(yieldop.getResults()[0]);
2797 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2798 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2799 ompBuilder->createAtomicUpdate(ompLoc, allocaIP, llvmAtomicX, llvmExpr,
2800 atomicOrdering, binop, updateFn,
2806 builder.restoreIP(*afterIP);
2810 static LogicalResult
2812 llvm::IRBuilderBase &builder,
2819 bool isXBinopExpr =
false, isPostfixUpdate =
false;
2820 llvm::AtomicRMWInst::BinOp binop = llvm::AtomicRMWInst::BinOp::BAD_BINOP;
2822 omp::AtomicUpdateOp atomicUpdateOp = atomicCaptureOp.getAtomicUpdateOp();
2823 omp::AtomicWriteOp atomicWriteOp = atomicCaptureOp.getAtomicWriteOp();
2825 assert((atomicUpdateOp || atomicWriteOp) &&
2826 "internal op must be an atomic.update or atomic.write op");
2828 if (atomicWriteOp) {
2829 isPostfixUpdate =
true;
2830 mlirExpr = atomicWriteOp.getExpr();
2832 isPostfixUpdate = atomicCaptureOp.getSecondOp() ==
2833 atomicCaptureOp.getAtomicUpdateOp().getOperation();
2834 auto &innerOpList = atomicUpdateOp.getRegion().front().getOperations();
2837 if (innerOpList.size() == 2) {
2840 atomicUpdateOp.getRegion().getArgument(0))) {
2841 return atomicUpdateOp.emitError(
2842 "no atomic update operation with region argument"
2843 " as operand found inside atomic.update region");
2847 innerOp.
getOperand(0) == atomicUpdateOp.getRegion().getArgument(0);
2850 binop = llvm::AtomicRMWInst::BinOp::BAD_BINOP;
2854 llvm::Value *llvmExpr = moduleTranslation.
lookupValue(mlirExpr);
2855 llvm::Value *llvmX =
2856 moduleTranslation.
lookupValue(atomicCaptureOp.getAtomicReadOp().getX());
2857 llvm::Value *llvmV =
2858 moduleTranslation.
lookupValue(atomicCaptureOp.getAtomicReadOp().getV());
2859 llvm::Type *llvmXElementType = moduleTranslation.
convertType(
2860 atomicCaptureOp.getAtomicReadOp().getElementType());
2861 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {llvmX, llvmXElementType,
2864 llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicV = {llvmV, llvmXElementType,
2868 llvm::AtomicOrdering atomicOrdering =
2872 [&](llvm::Value *atomicx,
2875 return moduleTranslation.
lookupValue(atomicWriteOp.getExpr());
2876 Block &bb = *atomicUpdateOp.getRegion().
begin();
2877 moduleTranslation.
mapValue(*atomicUpdateOp.getRegion().args_begin(),
2879 moduleTranslation.
mapBlock(&bb, builder.GetInsertBlock());
2880 if (failed(moduleTranslation.
convertBlock(bb,
true, builder)))
2881 return llvm::make_error<PreviouslyReportedError>();
2883 omp::YieldOp yieldop = dyn_cast<omp::YieldOp>(bb.
getTerminator());
2884 assert(yieldop && yieldop.getResults().size() == 1 &&
2885 "terminator must be omp.yield op and it must have exactly one "
2887 return moduleTranslation.
lookupValue(yieldop.getResults()[0]);
2892 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2893 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
2894 ompBuilder->createAtomicCapture(
2895 ompLoc, allocaIP, llvmAtomicX, llvmAtomicV, llvmExpr, atomicOrdering,
2896 binop, updateFn, atomicUpdateOp, isPostfixUpdate, isXBinopExpr);
2898 if (failed(
handleError(afterIP, *atomicCaptureOp)))
2901 builder.restoreIP(*afterIP);
2907 static LogicalResult
2910 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
2912 auto threadprivateOp = cast<omp::ThreadprivateOp>(opInst);
2917 Value symAddr = threadprivateOp.getSymAddr();
2920 if (
auto asCast = dyn_cast<LLVM::AddrSpaceCastOp>(symOp))
2923 if (!isa<LLVM::AddressOfOp>(symOp))
2924 return opInst.
emitError(
"Addressing symbol not found");
2925 LLVM::AddressOfOp addressOfOp = dyn_cast<LLVM::AddressOfOp>(symOp);
2927 LLVM::GlobalOp global =
2928 addressOfOp.getGlobal(moduleTranslation.
symbolTable());
2929 llvm::GlobalValue *globalValue = moduleTranslation.
lookupGlobal(global);
2931 if (!ompBuilder->Config.isTargetDevice()) {
2932 llvm::Type *type = globalValue->getValueType();
2933 llvm::TypeSize typeSize =
2934 builder.GetInsertBlock()->getModule()->getDataLayout().getTypeStoreSize(
2936 llvm::ConstantInt *size = builder.getInt64(typeSize.getFixedValue());
2937 llvm::Value *callInst = ompBuilder->createCachedThreadPrivate(
2938 ompLoc, globalValue, size, global.getSymName() +
".cache");
2947 static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind
2949 switch (deviceClause) {
2950 case mlir::omp::DeclareTargetDeviceType::host:
2951 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseHost;
2953 case mlir::omp::DeclareTargetDeviceType::nohost:
2954 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNoHost;
2956 case mlir::omp::DeclareTargetDeviceType::any:
2957 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny;
2960 llvm_unreachable(
"unhandled device clause");
2963 static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind
2965 mlir::omp::DeclareTargetCaptureClause captureClause) {
2966 switch (captureClause) {
2967 case mlir::omp::DeclareTargetCaptureClause::to:
2968 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo;
2969 case mlir::omp::DeclareTargetCaptureClause::link:
2970 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink;
2971 case mlir::omp::DeclareTargetCaptureClause::enter:
2972 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter;
2974 llvm_unreachable(
"unhandled capture clause");
2979 llvm::OpenMPIRBuilder &ompBuilder) {
2981 llvm::raw_svector_ostream os(suffix);
2984 auto fileInfoCallBack = [&loc]() {
2985 return std::pair<std::string, uint64_t>(
2986 llvm::StringRef(loc.getFilename()), loc.getLine());
2990 "_%x", ompBuilder.getTargetEntryUniqueInfo(fileInfoCallBack).FileID);
2992 os <<
"_decl_tgt_ref_ptr";
2998 if (
auto addressOfOp =
2999 llvm::dyn_cast_if_present<LLVM::AddressOfOp>(value.
getDefiningOp())) {
3000 auto modOp = addressOfOp->getParentOfType<mlir::ModuleOp>();
3001 Operation *gOp = modOp.lookupSymbol(addressOfOp.getGlobalName());
3002 if (
auto declareTargetGlobal =
3003 llvm::dyn_cast<mlir::omp::DeclareTargetInterface>(gOp))
3004 if (declareTargetGlobal.getDeclareTargetCaptureClause() ==
3005 mlir::omp::DeclareTargetCaptureClause::link)
3014 static llvm::Value *
3021 if (
auto addressOfOp =
3022 llvm::dyn_cast_if_present<LLVM::AddressOfOp>(value.
getDefiningOp())) {
3023 if (
auto gOp = llvm::dyn_cast_or_null<LLVM::GlobalOp>(
3024 addressOfOp->getParentOfType<mlir::ModuleOp>().lookupSymbol(
3025 addressOfOp.getGlobalName()))) {
3027 if (
auto declareTargetGlobal =
3028 llvm::dyn_cast<mlir::omp::DeclareTargetInterface>(
3029 gOp.getOperation())) {
3033 if ((declareTargetGlobal.getDeclareTargetCaptureClause() ==
3034 mlir::omp::DeclareTargetCaptureClause::link) ||
3035 (declareTargetGlobal.getDeclareTargetCaptureClause() ==
3036 mlir::omp::DeclareTargetCaptureClause::to &&
3037 ompBuilder->Config.hasRequiresUnifiedSharedMemory())) {
3041 if (gOp.getSymName().contains(suffix))
3046 (gOp.getSymName().str() + suffix.str()).str());
3057 struct MapInfosTy : llvm::OpenMPIRBuilder::MapInfosTy {
3061 void append(MapInfosTy &curInfo) {
3062 Mappers.append(curInfo.Mappers.begin(), curInfo.Mappers.end());
3063 llvm::OpenMPIRBuilder::MapInfosTy::append(curInfo);
3072 struct MapInfoData : MapInfosTy {
3084 void append(MapInfoData &CurInfo) {
3085 IsDeclareTarget.append(CurInfo.IsDeclareTarget.begin(),
3086 CurInfo.IsDeclareTarget.end());
3087 MapClause.append(CurInfo.MapClause.begin(), CurInfo.MapClause.end());
3088 OriginalValue.append(CurInfo.OriginalValue.begin(),
3089 CurInfo.OriginalValue.end());
3090 BaseType.append(CurInfo.BaseType.begin(), CurInfo.BaseType.end());
3091 MapInfosTy::append(CurInfo);
3097 if (
auto nestedArrTy = llvm::dyn_cast_if_present<LLVM::LLVMArrayType>(
3098 arrTy.getElementType()))
3114 Operation *clauseOp, llvm::Value *basePointer,
3115 llvm::Type *baseType, llvm::IRBuilderBase &builder,
3117 if (
auto memberClause =
3118 mlir::dyn_cast_if_present<mlir::omp::MapInfoOp>(clauseOp)) {
3123 if (!memberClause.getBounds().empty()) {
3124 llvm::Value *elementCount = builder.getInt64(1);
3125 for (
auto bounds : memberClause.getBounds()) {
3126 if (
auto boundOp = mlir::dyn_cast_if_present<mlir::omp::MapBoundsOp>(
3127 bounds.getDefiningOp())) {
3132 elementCount = builder.CreateMul(
3136 moduleTranslation.
lookupValue(boundOp.getUpperBound()),
3137 moduleTranslation.
lookupValue(boundOp.getLowerBound())),
3138 builder.getInt64(1)));
3145 if (
auto arrTy = llvm::dyn_cast_if_present<LLVM::LLVMArrayType>(type))
3153 return builder.CreateMul(elementCount,
3154 builder.getInt64(underlyingTypeSzInBits / 8));
3167 auto checkIsAMember = [](
const auto &mapVars,
auto mapOp) {
3175 for (
Value mapValue : mapVars) {
3176 auto map = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
3177 for (
auto member : map.getMembers())
3178 if (member == mapOp)
3185 for (
Value mapValue : mapVars) {
3186 auto mapOp = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
3188 mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtr() : mapOp.getVarPtr();
3189 mapData.OriginalValue.push_back(moduleTranslation.
lookupValue(offloadPtr));
3190 mapData.Pointers.push_back(mapData.OriginalValue.back());
3192 if (llvm::Value *refPtr =
3194 moduleTranslation)) {
3195 mapData.IsDeclareTarget.push_back(
true);
3196 mapData.BasePointers.push_back(refPtr);
3198 mapData.IsDeclareTarget.push_back(
false);
3199 mapData.BasePointers.push_back(mapData.OriginalValue.back());
3202 mapData.BaseType.push_back(
3203 moduleTranslation.
convertType(mapOp.getVarType()));
3204 mapData.Sizes.push_back(
3205 getSizeInBytes(dl, mapOp.getVarType(), mapOp, mapData.Pointers.back(),
3206 mapData.BaseType.back(), builder, moduleTranslation));
3207 mapData.MapClause.push_back(mapOp.getOperation());
3208 mapData.Types.push_back(
3209 llvm::omp::OpenMPOffloadMappingFlags(mapOp.getMapType()));
3213 if (mapOp.getMapperId())
3214 mapData.Mappers.push_back(
3215 SymbolTable::lookupNearestSymbolFrom<omp::DeclareMapperOp>(
3216 mapOp, mapOp.getMapperIdAttr()));
3218 mapData.Mappers.push_back(
nullptr);
3219 mapData.IsAMapping.push_back(
true);
3220 mapData.IsAMember.push_back(checkIsAMember(mapVars, mapOp));
3223 auto findMapInfo = [&mapData](llvm::Value *val,
3224 llvm::OpenMPIRBuilder::DeviceInfoTy devInfoTy) {
3227 for (llvm::Value *basePtr : mapData.OriginalValue) {
3228 if (basePtr == val && mapData.IsAMapping[index]) {
3230 mapData.Types[index] |=
3231 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
3232 mapData.DevicePointers[index] = devInfoTy;
3241 llvm::OpenMPIRBuilder::DeviceInfoTy devInfoTy) {
3242 for (
Value mapValue : useDevOperands) {
3243 auto mapOp = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
3245 mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtr() : mapOp.getVarPtr();
3246 llvm::Value *origValue = moduleTranslation.
lookupValue(offloadPtr);
3249 if (!findMapInfo(origValue, devInfoTy)) {
3250 mapData.OriginalValue.push_back(origValue);
3251 mapData.Pointers.push_back(mapData.OriginalValue.back());
3252 mapData.IsDeclareTarget.push_back(
false);
3253 mapData.BasePointers.push_back(mapData.OriginalValue.back());
3254 mapData.BaseType.push_back(
3255 moduleTranslation.
convertType(mapOp.getVarType()));
3256 mapData.Sizes.push_back(builder.getInt64(0));
3257 mapData.MapClause.push_back(mapOp.getOperation());
3258 mapData.Types.push_back(
3259 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM);
3262 mapData.DevicePointers.push_back(devInfoTy);
3263 mapData.Mappers.push_back(
nullptr);
3264 mapData.IsAMapping.push_back(
false);
3265 mapData.IsAMember.push_back(checkIsAMember(useDevOperands, mapOp));
3270 addDevInfos(useDevAddrOperands, llvm::OpenMPIRBuilder::DeviceInfoTy::Address);
3271 addDevInfos(useDevPtrOperands, llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer);
3273 for (
Value mapValue : hasDevAddrOperands) {
3274 auto mapOp = cast<omp::MapInfoOp>(mapValue.getDefiningOp());
3276 mapOp.getVarPtrPtr() ? mapOp.getVarPtrPtr() : mapOp.getVarPtr();
3277 llvm::Value *origValue = moduleTranslation.
lookupValue(offloadPtr);
3279 static_cast<llvm::omp::OpenMPOffloadMappingFlags
>(mapOp.getMapType());
3280 auto mapTypeAlways = llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
3282 mapData.OriginalValue.push_back(origValue);
3283 mapData.BasePointers.push_back(origValue);
3284 mapData.Pointers.push_back(origValue);
3285 mapData.IsDeclareTarget.push_back(
false);
3286 mapData.BaseType.push_back(
3287 moduleTranslation.
convertType(mapOp.getVarType()));
3288 mapData.Sizes.push_back(
3289 builder.getInt64(dl.
getTypeSize(mapOp.getVarType())));
3290 mapData.MapClause.push_back(mapOp.getOperation());
3291 if (llvm::to_underlying(mapType & mapTypeAlways)) {
3295 mapData.Types.push_back(mapType);
3299 if (mapOp.getMapperId()) {
3300 mapData.Mappers.push_back(
3301 SymbolTable::lookupNearestSymbolFrom<omp::DeclareMapperOp>(
3302 mapOp, mapOp.getMapperIdAttr()));
3304 mapData.Mappers.push_back(
nullptr);
3307 mapData.Types.push_back(
3308 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
3309 mapData.Mappers.push_back(
nullptr);
3313 mapData.DevicePointers.push_back(
3314 llvm::OpenMPIRBuilder::DeviceInfoTy::Address);
3315 mapData.IsAMapping.push_back(
false);
3316 mapData.IsAMember.push_back(checkIsAMember(hasDevAddrOperands, mapOp));
3321 auto *res = llvm::find(mapData.MapClause, memberOp);
3322 assert(res != mapData.MapClause.end() &&
3323 "MapInfoOp for member not found in MapData, cannot return index");
3324 return std::distance(mapData.MapClause.begin(), res);
3329 ArrayAttr indexAttr = mapInfo.getMembersIndexAttr();
3331 if (indexAttr.size() == 1)
3332 return cast<omp::MapInfoOp>(mapInfo.getMembers()[0].getDefiningOp());
3335 std::iota(indices.begin(), indices.end(), 0);
3337 llvm::sort(indices.begin(), indices.end(),
3338 [&](
const size_t a,
const size_t b) {
3339 auto memberIndicesA = cast<ArrayAttr>(indexAttr[a]);
3340 auto memberIndicesB = cast<ArrayAttr>(indexAttr[b]);
3341 for (const auto it : llvm::zip(memberIndicesA, memberIndicesB)) {
3342 int64_t aIndex = cast<IntegerAttr>(std::get<0>(it)).getInt();
3343 int64_t bIndex = cast<IntegerAttr>(std::get<1>(it)).getInt();
3345 if (aIndex == bIndex)
3348 if (aIndex < bIndex)
3351 if (aIndex > bIndex)
3358 return memberIndicesA.size() < memberIndicesB.size();
3361 return llvm::cast<omp::MapInfoOp>(
3362 mapInfo.getMembers()[indices.front()].getDefiningOp());
3384 std::vector<llvm::Value *>
3386 llvm::IRBuilderBase &builder,
bool isArrayTy,
3388 std::vector<llvm::Value *> idx;
3399 idx.push_back(builder.getInt64(0));
3400 for (
int i = bounds.size() - 1; i >= 0; --i) {
3401 if (
auto boundOp = dyn_cast_if_present<omp::MapBoundsOp>(
3402 bounds[i].getDefiningOp())) {
3403 idx.push_back(moduleTranslation.
lookupValue(boundOp.getLowerBound()));
3425 std::vector<llvm::Value *> dimensionIndexSizeOffset{builder.getInt64(1)};
3426 for (
size_t i = 1; i < bounds.size(); ++i) {
3427 if (
auto boundOp = dyn_cast_if_present<omp::MapBoundsOp>(
3428 bounds[i].getDefiningOp())) {
3429 dimensionIndexSizeOffset.push_back(builder.CreateMul(
3430 moduleTranslation.
lookupValue(boundOp.getExtent()),
3431 dimensionIndexSizeOffset[i - 1]));
3439 for (
int i = bounds.size() - 1; i >= 0; --i) {
3440 if (
auto boundOp = dyn_cast_if_present<omp::MapBoundsOp>(
3441 bounds[i].getDefiningOp())) {
3443 idx.emplace_back(builder.CreateMul(
3444 moduleTranslation.
lookupValue(boundOp.getLowerBound()),
3445 dimensionIndexSizeOffset[i]));
3447 idx.back() = builder.CreateAdd(
3448 idx.back(), builder.CreateMul(moduleTranslation.
lookupValue(
3449 boundOp.getLowerBound()),
3450 dimensionIndexSizeOffset[i]));
3475 llvm::OpenMPIRBuilder &ompBuilder,
DataLayout &dl, MapInfosTy &combinedInfo,
3476 MapInfoData &mapData, uint64_t mapDataIndex,
bool isTargetParams) {
3478 combinedInfo.Types.emplace_back(
3480 ? llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM
3481 : llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE);
3482 combinedInfo.DevicePointers.emplace_back(
3483 mapData.DevicePointers[mapDataIndex]);
3484 combinedInfo.Mappers.emplace_back(mapData.Mappers[mapDataIndex]);
3486 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder));
3487 combinedInfo.BasePointers.emplace_back(mapData.BasePointers[mapDataIndex]);
3497 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
3499 llvm::Value *lowAddr, *highAddr;
3500 if (!parentClause.getPartialMap()) {
3501 lowAddr = builder.CreatePointerCast(mapData.Pointers[mapDataIndex],
3502 builder.getPtrTy());
3503 highAddr = builder.CreatePointerCast(
3504 builder.CreateConstGEP1_32(mapData.BaseType[mapDataIndex],
3505 mapData.Pointers[mapDataIndex], 1),
3506 builder.getPtrTy());
3507 combinedInfo.Pointers.emplace_back(mapData.Pointers[mapDataIndex]);
3509 auto mapOp = dyn_cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
3512 lowAddr = builder.CreatePointerCast(mapData.Pointers[firstMemberIdx],
3513 builder.getPtrTy());
3516 highAddr = builder.CreatePointerCast(
3517 builder.CreateGEP(mapData.BaseType[lastMemberIdx],
3518 mapData.Pointers[lastMemberIdx], builder.getInt64(1)),
3519 builder.getPtrTy());
3520 combinedInfo.Pointers.emplace_back(mapData.Pointers[firstMemberIdx]);
3523 llvm::Value *size = builder.CreateIntCast(
3524 builder.CreatePtrDiff(builder.getInt8Ty(), highAddr, lowAddr),
3525 builder.getInt64Ty(),
3527 combinedInfo.Sizes.push_back(size);
3529 llvm::omp::OpenMPOffloadMappingFlags memberOfFlag =
3530 ompBuilder.getMemberOfFlag(combinedInfo.BasePointers.size() - 1);
3538 if (!parentClause.getPartialMap()) {
3543 llvm::omp::OpenMPOffloadMappingFlags mapFlag = mapData.Types[mapDataIndex];
3544 ompBuilder.setCorrectMemberOfFlag(mapFlag, memberOfFlag);
3545 combinedInfo.Types.emplace_back(mapFlag);
3546 combinedInfo.DevicePointers.emplace_back(
3548 combinedInfo.Mappers.emplace_back(
nullptr);
3550 mapData.MapClause[mapDataIndex]->getLoc(), ompBuilder));
3551 combinedInfo.BasePointers.emplace_back(mapData.BasePointers[mapDataIndex]);
3552 combinedInfo.Pointers.emplace_back(mapData.Pointers[mapDataIndex]);
3553 combinedInfo.Sizes.emplace_back(mapData.Sizes[mapDataIndex]);
3555 return memberOfFlag;
3567 if (mapOp.getVarPtrPtr())
3582 llvm::OpenMPIRBuilder &ompBuilder,
DataLayout &dl, MapInfosTy &combinedInfo,
3583 MapInfoData &mapData, uint64_t mapDataIndex,
3584 llvm::omp::OpenMPOffloadMappingFlags memberOfFlag) {
3587 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
3589 for (
auto mappedMembers : parentClause.getMembers()) {
3591 llvm::cast<omp::MapInfoOp>(mappedMembers.getDefiningOp());
3594 assert(memberDataIdx >= 0 &&
"could not find mapped member of structure");
3605 llvm::omp::OpenMPOffloadMappingFlags(memberClause.getMapType());
3606 mapFlag &= ~
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
3607 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
3608 ompBuilder.setCorrectMemberOfFlag(mapFlag, memberOfFlag);
3609 combinedInfo.Types.emplace_back(mapFlag);
3610 combinedInfo.DevicePointers.emplace_back(
3612 combinedInfo.Mappers.emplace_back(
nullptr);
3613 combinedInfo.Names.emplace_back(
3615 combinedInfo.BasePointers.emplace_back(
3616 mapData.BasePointers[mapDataIndex]);
3617 combinedInfo.Pointers.emplace_back(mapData.BasePointers[memberDataIdx]);
3618 combinedInfo.Sizes.emplace_back(builder.getInt64(
3619 moduleTranslation.
getLLVMModule()->getDataLayout().getPointerSize()));
3625 llvm::omp::OpenMPOffloadMappingFlags(memberClause.getMapType());
3626 mapFlag &= ~
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
3627 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
3628 ompBuilder.setCorrectMemberOfFlag(mapFlag, memberOfFlag);
3630 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
3632 combinedInfo.Types.emplace_back(mapFlag);
3633 combinedInfo.DevicePointers.emplace_back(
3634 mapData.DevicePointers[memberDataIdx]);
3635 combinedInfo.Mappers.emplace_back(mapData.Mappers[memberDataIdx]);
3636 combinedInfo.Names.emplace_back(
3638 uint64_t basePointerIndex =
3640 combinedInfo.BasePointers.emplace_back(
3641 mapData.BasePointers[basePointerIndex]);
3642 combinedInfo.Pointers.emplace_back(mapData.Pointers[memberDataIdx]);
3644 llvm::Value *size = mapData.Sizes[memberDataIdx];
3646 size = builder.CreateSelect(
3647 builder.CreateIsNull(mapData.Pointers[memberDataIdx]),
3648 builder.getInt64(0), size);
3651 combinedInfo.Sizes.emplace_back(size);
3656 MapInfosTy &combinedInfo,
bool isTargetParams,
3657 int mapDataParentIdx = -1) {
3661 auto mapFlag = mapData.Types[mapDataIdx];
3662 auto mapInfoOp = llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIdx]);
3666 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
3668 if (isTargetParams && !mapData.IsDeclareTarget[mapDataIdx])
3669 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
3671 if (mapInfoOp.getMapCaptureType() == omp::VariableCaptureKind::ByCopy &&
3673 mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL;
3678 if (mapDataParentIdx >= 0)
3679 combinedInfo.BasePointers.emplace_back(
3680 mapData.BasePointers[mapDataParentIdx]);
3682 combinedInfo.BasePointers.emplace_back(mapData.BasePointers[mapDataIdx]);
3684 combinedInfo.Pointers.emplace_back(mapData.Pointers[mapDataIdx]);
3685 combinedInfo.DevicePointers.emplace_back(mapData.DevicePointers[mapDataIdx]);
3686 combinedInfo.Mappers.emplace_back(mapData.Mappers[mapDataIdx]);
3687 combinedInfo.Names.emplace_back(mapData.Names[mapDataIdx]);
3688 combinedInfo.Types.emplace_back(mapFlag);
3689 combinedInfo.Sizes.emplace_back(mapData.Sizes[mapDataIdx]);
3693 llvm::IRBuilderBase &builder,
3694 llvm::OpenMPIRBuilder &ompBuilder,
3696 MapInfoData &mapData, uint64_t mapDataIndex,
3697 bool isTargetParams) {
3699 llvm::cast<omp::MapInfoOp>(mapData.MapClause[mapDataIndex]);
3704 if (parentClause.getMembers().size() == 1 && parentClause.getPartialMap()) {
3705 auto memberClause = llvm::cast<omp::MapInfoOp>(
3706 parentClause.getMembers()[0].getDefiningOp());
3723 llvm::omp::OpenMPOffloadMappingFlags memberOfParentFlag =
3725 combinedInfo, mapData, mapDataIndex, isTargetParams);
3727 combinedInfo, mapData, mapDataIndex,
3728 memberOfParentFlag);
3738 llvm::IRBuilderBase &builder) {
3739 for (
size_t i = 0; i < mapData.MapClause.size(); ++i) {
3741 if (!mapData.IsDeclareTarget[i]) {
3742 auto mapOp = cast<omp::MapInfoOp>(mapData.MapClause[i]);
3743 omp::VariableCaptureKind captureKind = mapOp.getMapCaptureType();
3753 switch (captureKind) {
3754 case omp::VariableCaptureKind::ByRef: {
3755 llvm::Value *newV = mapData.Pointers[i];
3757 moduleTranslation, builder, mapData.BaseType[i]->isArrayTy(),
3760 newV = builder.CreateLoad(builder.getPtrTy(), newV);
3762 if (!offsetIdx.empty())
3763 newV = builder.CreateInBoundsGEP(mapData.BaseType[i], newV, offsetIdx,
3765 mapData.Pointers[i] = newV;
3767 case omp::VariableCaptureKind::ByCopy: {
3768 llvm::Type *type = mapData.BaseType[i];
3770 if (mapData.Pointers[i]->getType()->isPointerTy())
3771 newV = builder.CreateLoad(type, mapData.Pointers[i]);
3773 newV = mapData.Pointers[i];
3776 auto curInsert = builder.saveIP();
3778 auto *memTempAlloc =
3779 builder.CreateAlloca(builder.getPtrTy(),
nullptr,
".casted");
3780 builder.restoreIP(curInsert);
3782 builder.CreateStore(newV, memTempAlloc);
3783 newV = builder.CreateLoad(builder.getPtrTy(), memTempAlloc);
3786 mapData.Pointers[i] = newV;
3787 mapData.BasePointers[i] = newV;
3789 case omp::VariableCaptureKind::This:
3790 case omp::VariableCaptureKind::VLAType:
3791 mapData.MapClause[i]->emitOpError(
"Unhandled capture kind");
3802 MapInfoData &mapData,
bool isTargetParams =
false) {
3824 for (
size_t i = 0; i < mapData.MapClause.size(); ++i) {
3827 if (mapData.IsAMember[i])
3830 auto mapInfoOp = dyn_cast<omp::MapInfoOp>(mapData.MapClause[i]);
3831 if (!mapInfoOp.getMembers().empty()) {
3833 combinedInfo, mapData, i, isTargetParams);
3844 llvm::StringRef mapperFuncName);
3849 auto declMapperOp = cast<omp::DeclareMapperOp>(op);
3850 std::string mapperFuncName =
3852 {
"omp_mapper", declMapperOp.getSymName()});
3854 if (
auto *lookupFunc = moduleTranslation.
lookupFunction(mapperFuncName))
3864 llvm::StringRef mapperFuncName) {
3865 auto declMapperOp = cast<omp::DeclareMapperOp>(op);
3866 auto declMapperInfoOp = declMapperOp.getDeclareMapperInfo();
3869 llvm::Type *varType = moduleTranslation.
convertType(declMapperOp.getType());
3872 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
3875 MapInfosTy combinedInfo;
3877 [&](InsertPointTy codeGenIP, llvm::Value *ptrPHI,
3878 llvm::Value *unused2) -> llvm::OpenMPIRBuilder::MapInfosOrErrorTy {
3879 builder.restoreIP(codeGenIP);
3880 moduleTranslation.
mapValue(declMapperOp.getSymVal(), ptrPHI);
3881 moduleTranslation.
mapBlock(&declMapperOp.getRegion().front(),
3882 builder.GetInsertBlock());
3883 if (failed(moduleTranslation.
convertBlock(declMapperOp.getRegion().front(),
3886 return llvm::make_error<PreviouslyReportedError>();
3887 MapInfoData mapData;
3890 genMapInfos(builder, moduleTranslation, dl, combinedInfo, mapData);
3895 return combinedInfo;
3899 if (!combinedInfo.Mappers[i])
3906 genMapInfoCB, varType, mapperFuncName, customMapperCB);
3908 return newFn.takeError();
3909 moduleTranslation.
mapFunction(mapperFuncName, *newFn);
3913 static LogicalResult
3916 llvm::Value *ifCond =
nullptr;
3917 int64_t deviceID = llvm::omp::OMP_DEVICEID_UNDEF;
3921 llvm::omp::RuntimeFunction RTLFn;
3925 llvm::OpenMPIRBuilder::TargetDataInfo info(
true,
3928 LogicalResult result =
3930 .Case([&](omp::TargetDataOp dataOp) {
3934 if (
auto ifVar = dataOp.getIfExpr())
3937 if (
auto devId = dataOp.getDevice())
3939 dyn_cast<LLVM::ConstantOp>(devId.getDefiningOp()))
3940 if (
auto intAttr = dyn_cast<IntegerAttr>(constOp.getValue()))
3941 deviceID = intAttr.getInt();
3943 mapVars = dataOp.getMapVars();
3944 useDevicePtrVars = dataOp.getUseDevicePtrVars();
3945 useDeviceAddrVars = dataOp.getUseDeviceAddrVars();
3948 .Case([&](omp::TargetEnterDataOp enterDataOp) -> LogicalResult {
3952 if (
auto ifVar = enterDataOp.getIfExpr())
3955 if (
auto devId = enterDataOp.getDevice())
3957 dyn_cast<LLVM::ConstantOp>(devId.getDefiningOp()))
3958 if (
auto intAttr = dyn_cast<IntegerAttr>(constOp.getValue()))
3959 deviceID = intAttr.getInt();
3961 enterDataOp.getNowait()
3962 ? llvm::omp::OMPRTL___tgt_target_data_begin_nowait_mapper
3963 : llvm::omp::OMPRTL___tgt_target_data_begin_mapper;
3964 mapVars = enterDataOp.getMapVars();
3965 info.HasNoWait = enterDataOp.getNowait();
3968 .Case([&](omp::TargetExitDataOp exitDataOp) -> LogicalResult {
3972 if (
auto ifVar = exitDataOp.getIfExpr())
3975 if (
auto devId = exitDataOp.getDevice())
3977 dyn_cast<LLVM::ConstantOp>(devId.getDefiningOp()))
3978 if (
auto intAttr = dyn_cast<IntegerAttr>(constOp.getValue()))
3979 deviceID = intAttr.getInt();
3981 RTLFn = exitDataOp.getNowait()
3982 ? llvm::omp::OMPRTL___tgt_target_data_end_nowait_mapper
3983 : llvm::omp::OMPRTL___tgt_target_data_end_mapper;
3984 mapVars = exitDataOp.getMapVars();
3985 info.HasNoWait = exitDataOp.getNowait();
3988 .Case([&](omp::TargetUpdateOp updateDataOp) -> LogicalResult {
3992 if (
auto ifVar = updateDataOp.getIfExpr())
3995 if (
auto devId = updateDataOp.getDevice())
3997 dyn_cast<LLVM::ConstantOp>(devId.getDefiningOp()))
3998 if (
auto intAttr = dyn_cast<IntegerAttr>(constOp.getValue()))
3999 deviceID = intAttr.getInt();
4002 updateDataOp.getNowait()
4003 ? llvm::omp::OMPRTL___tgt_target_data_update_nowait_mapper
4004 : llvm::omp::OMPRTL___tgt_target_data_update_mapper;
4005 mapVars = updateDataOp.getMapVars();
4006 info.HasNoWait = updateDataOp.getNowait();
4010 llvm_unreachable(
"unexpected operation");
4017 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4018 MapInfoData mapData;
4020 builder, useDevicePtrVars, useDeviceAddrVars);
4023 MapInfosTy combinedInfo;
4024 auto genMapInfoCB = [&](InsertPointTy codeGenIP) -> MapInfosTy & {
4025 builder.restoreIP(codeGenIP);
4026 genMapInfos(builder, moduleTranslation, DL, combinedInfo, mapData);
4027 return combinedInfo;
4033 [&moduleTranslation](
4034 llvm::OpenMPIRBuilder::DeviceInfoTy type,
4038 for (
auto [arg, useDevVar] :
4039 llvm::zip_equal(blockArgs, useDeviceVars)) {
4041 auto getMapBasePtr = [](omp::MapInfoOp mapInfoOp) {
4042 return mapInfoOp.getVarPtrPtr() ? mapInfoOp.getVarPtrPtr()
4043 : mapInfoOp.getVarPtr();
4046 auto useDevMap = cast<omp::MapInfoOp>(useDevVar.getDefiningOp());
4047 for (
auto [mapClause, devicePointer, basePointer] : llvm::zip_equal(
4048 mapInfoData.MapClause, mapInfoData.DevicePointers,
4049 mapInfoData.BasePointers)) {
4050 auto mapOp = cast<omp::MapInfoOp>(mapClause);
4051 if (getMapBasePtr(mapOp) != getMapBasePtr(useDevMap) ||
4052 devicePointer != type)
4055 if (llvm::Value *devPtrInfoMap =
4056 mapper ? mapper(basePointer) : basePointer) {
4057 moduleTranslation.
mapValue(arg, devPtrInfoMap);
4064 using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy;
4065 auto bodyGenCB = [&](InsertPointTy codeGenIP, BodyGenTy bodyGenType)
4066 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
4067 builder.restoreIP(codeGenIP);
4068 assert(isa<omp::TargetDataOp>(op) &&
4069 "BodyGen requested for non TargetDataOp");
4070 auto blockArgIface = cast<omp::BlockArgOpenMPOpInterface>(op);
4071 Region ®ion = cast<omp::TargetDataOp>(op).getRegion();
4072 switch (bodyGenType) {
4073 case BodyGenTy::Priv:
4075 if (!info.DevicePtrInfoMap.empty()) {
4076 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Address,
4077 blockArgIface.getUseDeviceAddrBlockArgs(),
4078 useDeviceAddrVars, mapData,
4079 [&](llvm::Value *basePointer) -> llvm::Value * {
4080 if (!info.DevicePtrInfoMap[basePointer].second)
4082 return builder.CreateLoad(
4084 info.DevicePtrInfoMap[basePointer].second);
4086 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer,
4087 blockArgIface.getUseDevicePtrBlockArgs(), useDevicePtrVars,
4088 mapData, [&](llvm::Value *basePointer) {
4089 return info.DevicePtrInfoMap[basePointer].second;
4093 moduleTranslation)))
4094 return llvm::make_error<PreviouslyReportedError>();
4097 case BodyGenTy::DupNoPriv:
4100 builder.restoreIP(codeGenIP);
4102 case BodyGenTy::NoPriv:
4104 if (info.DevicePtrInfoMap.empty()) {
4107 if (ompBuilder->Config.IsTargetDevice.value_or(
false)) {
4108 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Address,
4109 blockArgIface.getUseDeviceAddrBlockArgs(),
4110 useDeviceAddrVars, mapData);
4111 mapUseDevice(llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer,
4112 blockArgIface.getUseDevicePtrBlockArgs(),
4113 useDevicePtrVars, mapData);
4117 moduleTranslation)))
4118 return llvm::make_error<PreviouslyReportedError>();
4122 return builder.saveIP();
4125 auto customMapperCB =
4127 if (!combinedInfo.Mappers[i])
4129 info.HasMapper =
true;
4134 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4135 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
4137 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP = [&]() {
4138 if (isa<omp::TargetDataOp>(op))
4139 return ompBuilder->createTargetData(ompLoc, allocaIP, builder.saveIP(),
4140 builder.getInt64(deviceID), ifCond,
4141 info, genMapInfoCB, customMapperCB,
4144 return ompBuilder->createTargetData(
4145 ompLoc, allocaIP, builder.saveIP(), builder.getInt64(deviceID), ifCond,
4146 info, genMapInfoCB, customMapperCB, &RTLFn);
4152 builder.restoreIP(*afterIP);
4156 static LogicalResult
4160 auto distributeOp = cast<omp::DistributeOp>(opInst);
4164 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4165 auto bodyGenCB = [&](InsertPointTy allocaIP,
4166 InsertPointTy codeGenIP) -> llvm::Error {
4170 moduleTranslation, allocaIP);
4173 builder.restoreIP(codeGenIP);
4179 return llvm::make_error<PreviouslyReportedError>();
4184 return llvm::make_error<PreviouslyReportedError>();
4187 builder, moduleTranslation, privVarsInfo.
mlirVars,
4189 return llvm::make_error<PreviouslyReportedError>();
4192 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4195 builder, moduleTranslation);
4197 return regionBlock.takeError();
4198 builder.SetInsertPoint(*regionBlock, (*regionBlock)->begin());
4203 if (!isa_and_present<omp::WsloopOp>(distributeOp.getNestedWrapper())) {
4206 auto schedule = omp::ClauseScheduleKind::Static;
4207 bool isOrdered =
false;
4208 std::optional<omp::ScheduleModifier> scheduleMod;
4209 bool isSimd =
false;
4210 llvm::omp::WorksharingLoopType workshareLoopType =
4211 llvm::omp::WorksharingLoopType::DistributeStaticLoop;
4212 bool loopNeedsBarrier =
false;
4213 llvm::Value *chunk =
nullptr;
4215 llvm::CanonicalLoopInfo *loopInfo =
4217 llvm::OpenMPIRBuilder::InsertPointOrErrorTy wsloopIP =
4218 ompBuilder->applyWorkshareLoop(
4219 ompLoc.DL, loopInfo, allocaIP, loopNeedsBarrier,
4220 convertToScheduleKind(schedule), chunk, isSimd,
4221 scheduleMod == omp::ScheduleModifier::monotonic,
4222 scheduleMod == omp::ScheduleModifier::nonmonotonic, isOrdered,
4226 return wsloopIP.takeError();
4230 distributeOp.getLoc(), privVarsInfo.
llvmVars,
4232 return llvm::make_error<PreviouslyReportedError>();
4234 return llvm::Error::success();
4237 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
4239 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4240 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
4241 ompBuilder->createDistribute(ompLoc, allocaIP, bodyGenCB);
4246 builder.restoreIP(*afterIP);
4255 if (!cast<mlir::ModuleOp>(op))
4260 ompBuilder->M.addModuleFlag(llvm::Module::Max,
"openmp-device",
4261 attribute.getOpenmpDeviceVersion());
4263 if (attribute.getNoGpuLib())
4266 ompBuilder->createGlobalFlag(
4267 attribute.getDebugKind() ,
4268 "__omp_rtl_debug_kind");
4269 ompBuilder->createGlobalFlag(
4271 .getAssumeTeamsOversubscription()
4273 "__omp_rtl_assume_teams_oversubscription");
4274 ompBuilder->createGlobalFlag(
4276 .getAssumeThreadsOversubscription()
4278 "__omp_rtl_assume_threads_oversubscription");
4279 ompBuilder->createGlobalFlag(
4280 attribute.getAssumeNoThreadState() ,
4281 "__omp_rtl_assume_no_thread_state");
4282 ompBuilder->createGlobalFlag(
4284 .getAssumeNoNestedParallelism()
4286 "__omp_rtl_assume_no_nested_parallelism");
4291 omp::TargetOp targetOp,
4292 llvm::StringRef parentName =
"") {
4293 auto fileLoc = targetOp.getLoc()->findInstanceOf<
FileLineColLoc>();
4295 assert(fileLoc &&
"No file found from location");
4296 StringRef fileName = fileLoc.getFilename().getValue();
4298 llvm::sys::fs::UniqueID id;
4299 uint64_t line = fileLoc.getLine();
4300 if (
auto ec = llvm::sys::fs::getUniqueID(fileName,
id)) {
4302 size_t deviceId = 0xdeadf17e;
4304 llvm::TargetRegionEntryInfo(parentName, deviceId, fileHash, line);
4306 targetInfo = llvm::TargetRegionEntryInfo(parentName,
id.getDevice(),
4307 id.getFile(), line);
4314 llvm::IRBuilderBase &builder, llvm::Function *func) {
4315 for (
size_t i = 0; i < mapData.MapClause.size(); ++i) {
4328 if (mapData.IsDeclareTarget[i]) {
4335 if (
auto *constant = dyn_cast<llvm::Constant>(mapData.OriginalValue[i]))
4336 convertUsersOfConstantsToInstructions(constant, func,
false);
4343 for (llvm::User *user : mapData.OriginalValue[i]->users())
4344 userVec.push_back(user);
4346 for (llvm::User *user : userVec) {
4347 if (
auto *insn = dyn_cast<llvm::Instruction>(user)) {
4348 if (insn->getFunction() == func) {
4349 auto *load = builder.CreateLoad(mapData.BasePointers[i]->getType(),
4350 mapData.BasePointers[i]);
4351 load->moveBefore(insn->getIterator());
4352 user->replaceUsesOfWith(mapData.OriginalValue[i], load);
4399 static llvm::IRBuilderBase::InsertPoint
4401 llvm::Value *input, llvm::Value *&retVal,
4402 llvm::IRBuilderBase &builder,
4403 llvm::OpenMPIRBuilder &ompBuilder,
4405 llvm::IRBuilderBase::InsertPoint allocaIP,
4406 llvm::IRBuilderBase::InsertPoint codeGenIP) {
4407 builder.restoreIP(allocaIP);
4409 omp::VariableCaptureKind capture = omp::VariableCaptureKind::ByRef;
4412 for (
size_t i = 0; i < mapData.MapClause.size(); ++i)
4413 if (mapData.OriginalValue[i] == input) {
4414 auto mapOp = cast<omp::MapInfoOp>(mapData.MapClause[i]);
4415 capture = mapOp.getMapCaptureType();
4420 unsigned int allocaAS = ompBuilder.M.getDataLayout().getAllocaAddrSpace();
4421 unsigned int defaultAS =
4422 ompBuilder.M.getDataLayout().getProgramAddressSpace();
4425 llvm::Value *v = builder.CreateAlloca(arg.getType(), allocaAS);
4427 if (allocaAS != defaultAS && arg.getType()->isPointerTy())
4428 v = builder.CreateAddrSpaceCast(v, builder.getPtrTy(defaultAS));
4430 builder.CreateStore(&arg, v);
4432 builder.restoreIP(codeGenIP);
4435 case omp::VariableCaptureKind::ByCopy: {
4439 case omp::VariableCaptureKind::ByRef: {
4440 retVal = builder.CreateAlignedLoad(
4442 ompBuilder.M.getDataLayout().getPrefTypeAlign(v->getType()));
4445 case omp::VariableCaptureKind::This:
4446 case omp::VariableCaptureKind::VLAType:
4449 assert(
false &&
"Currently unsupported capture kind");
4453 return builder.saveIP();
4470 auto blockArgIface = llvm::cast<omp::BlockArgOpenMPOpInterface>(*targetOp);
4471 for (
auto item : llvm::zip_equal(targetOp.getHostEvalVars(),
4472 blockArgIface.getHostEvalBlockArgs())) {
4473 Value hostEvalVar = std::get<0>(item), blockArg = std::get<1>(item);
4477 .Case([&](omp::TeamsOp teamsOp) {
4478 if (teamsOp.getNumTeamsLower() == blockArg)
4479 numTeamsLower = hostEvalVar;
4480 else if (teamsOp.getNumTeamsUpper() == blockArg)
4481 numTeamsUpper = hostEvalVar;
4482 else if (teamsOp.getThreadLimit() == blockArg)
4483 threadLimit = hostEvalVar;
4485 llvm_unreachable(
"unsupported host_eval use");
4487 .Case([&](omp::ParallelOp parallelOp) {
4488 if (parallelOp.getNumThreads() == blockArg)
4489 numThreads = hostEvalVar;
4491 llvm_unreachable(
"unsupported host_eval use");
4493 .Case([&](omp::LoopNestOp loopOp) {
4494 auto processBounds =
4499 if (lb == blockArg) {
4502 (*outBounds)[i] = hostEvalVar;
4508 processBounds(loopOp.getLoopLowerBounds(), lowerBounds);
4509 found = processBounds(loopOp.getLoopUpperBounds(), upperBounds) ||
4511 found = processBounds(loopOp.getLoopSteps(), steps) || found;
4513 assert(found &&
"unsupported host_eval use");
4516 llvm_unreachable(
"unsupported host_eval use");
4529 template <
typename OpTy>
4534 if (OpTy casted = dyn_cast<OpTy>(op))
4537 if (immediateParent)
4538 return dyn_cast_if_present<OpTy>(op->
getParentOp());
4547 return std::nullopt;
4550 dyn_cast_if_present<LLVM::ConstantOp>(value.
getDefiningOp()))
4551 if (
auto constAttr = dyn_cast<IntegerAttr>(constOp.getValue()))
4552 return constAttr.getInt();
4554 return std::nullopt;
4565 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &attrs,
4566 bool isTargetDevice) {
4569 Value numThreads, numTeamsLower, numTeamsUpper, threadLimit;
4570 if (!isTargetDevice) {
4577 if (
auto teamsOp = castOrGetParentOfType<omp::TeamsOp>(capturedOp)) {
4578 numTeamsLower = teamsOp.getNumTeamsLower();
4579 numTeamsUpper = teamsOp.getNumTeamsUpper();
4580 threadLimit = teamsOp.getThreadLimit();
4583 if (
auto parallelOp = castOrGetParentOfType<omp::ParallelOp>(capturedOp))
4584 numThreads = parallelOp.getNumThreads();
4589 int32_t minTeamsVal = 1, maxTeamsVal = -1;
4590 if (castOrGetParentOfType<omp::TeamsOp>(capturedOp)) {
4593 if (numTeamsUpper) {
4595 minTeamsVal = maxTeamsVal = *val;
4597 minTeamsVal = maxTeamsVal = 0;
4599 }
else if (castOrGetParentOfType<omp::ParallelOp>(capturedOp,
4601 castOrGetParentOfType<omp::SimdOp>(capturedOp,
4603 minTeamsVal = maxTeamsVal = 1;
4605 minTeamsVal = maxTeamsVal = -1;
4610 auto setMaxValueFromClause = [](
Value clauseValue, int32_t &result) {
4624 int32_t targetThreadLimitVal = -1, teamsThreadLimitVal = -1;
4625 setMaxValueFromClause(targetOp.getThreadLimit(), targetThreadLimitVal);
4626 setMaxValueFromClause(threadLimit, teamsThreadLimitVal);
4629 int32_t maxThreadsVal = -1;
4630 if (castOrGetParentOfType<omp::ParallelOp>(capturedOp))
4631 setMaxValueFromClause(numThreads, maxThreadsVal);
4632 else if (castOrGetParentOfType<omp::SimdOp>(capturedOp,
4639 int32_t combinedMaxThreadsVal = targetThreadLimitVal;
4640 if (combinedMaxThreadsVal < 0 ||
4641 (teamsThreadLimitVal >= 0 && teamsThreadLimitVal < combinedMaxThreadsVal))
4642 combinedMaxThreadsVal = teamsThreadLimitVal;
4644 if (combinedMaxThreadsVal < 0 ||
4645 (maxThreadsVal >= 0 && maxThreadsVal < combinedMaxThreadsVal))
4646 combinedMaxThreadsVal = maxThreadsVal;
4649 attrs.ExecFlags = targetOp.getKernelExecFlags(capturedOp);
4650 attrs.MinTeams = minTeamsVal;
4651 attrs.MaxTeams.front() = maxTeamsVal;
4652 attrs.MinThreads = 1;
4653 attrs.MaxThreads.front() = combinedMaxThreadsVal;
4665 omp::TargetOp targetOp,
Operation *capturedOp,
4666 llvm::OpenMPIRBuilder::TargetKernelRuntimeAttrs &attrs) {
4667 omp::LoopNestOp loopOp = castOrGetParentOfType<omp::LoopNestOp>(capturedOp);
4668 unsigned numLoops = loopOp ? loopOp.getNumLoops() : 0;
4670 Value numThreads, numTeamsLower, numTeamsUpper, teamsThreadLimit;
4674 teamsThreadLimit, &lowerBounds, &upperBounds, &steps);
4677 if (
Value targetThreadLimit = targetOp.getThreadLimit())
4678 attrs.TargetThreadLimit.front() =
4682 attrs.MinTeams = moduleTranslation.
lookupValue(numTeamsLower);
4685 attrs.MaxTeams.front() = moduleTranslation.
lookupValue(numTeamsUpper);
4687 if (teamsThreadLimit)
4688 attrs.TeamsThreadLimit.front() =
4692 attrs.MaxThreads = moduleTranslation.
lookupValue(numThreads);
4694 if (targetOp.getKernelExecFlags(capturedOp) !=
4695 llvm::omp::OMP_TGT_EXEC_MODE_GENERIC) {
4697 attrs.LoopTripCount =
nullptr;
4702 for (
auto [loopLower, loopUpper, loopStep] :
4703 llvm::zip_equal(lowerBounds, upperBounds, steps)) {
4704 llvm::Value *lowerBound = moduleTranslation.
lookupValue(loopLower);
4705 llvm::Value *upperBound = moduleTranslation.
lookupValue(loopUpper);
4706 llvm::Value *step = moduleTranslation.
lookupValue(loopStep);
4708 llvm::OpenMPIRBuilder::LocationDescription loc(builder);
4709 llvm::Value *tripCount = ompBuilder->calculateCanonicalLoopTripCount(
4710 loc, lowerBound, upperBound, step,
true,
4711 loopOp.getLoopInclusive());
4713 if (!attrs.LoopTripCount) {
4714 attrs.LoopTripCount = tripCount;
4719 attrs.LoopTripCount = builder.CreateMul(attrs.LoopTripCount, tripCount,
4725 static LogicalResult
4728 auto targetOp = cast<omp::TargetOp>(opInst);
4733 bool isTargetDevice = ompBuilder->Config.isTargetDevice();
4736 auto argIface = cast<omp::BlockArgOpenMPOpInterface>(opInst);
4737 auto &targetRegion = targetOp.getRegion();
4754 llvm::Function *llvmOutlinedFn =
nullptr;
4758 bool isOffloadEntry =
4759 isTargetDevice || !ompBuilder->Config.TargetTriples.empty();
4766 if (!targetOp.getPrivateVars().empty() && !targetOp.getMapVars().empty()) {
4768 std::optional<ArrayAttr> privateSyms = targetOp.getPrivateSyms();
4769 std::optional<DenseI64ArrayAttr> privateMapIndices =
4770 targetOp.getPrivateMapsAttr();
4772 for (
auto [privVarIdx, privVarSymPair] :
4774 auto privVar = std::get<0>(privVarSymPair);
4775 auto privSym = std::get<1>(privVarSymPair);
4777 SymbolRefAttr privatizerName = llvm::cast<SymbolRefAttr>(privSym);
4778 omp::PrivateClauseOp privatizer =
4781 if (!privatizer.needsMap())
4785 targetOp.getMappedValueForPrivateVar(privVarIdx);
4786 assert(mappedValue &&
"Expected to find mapped value for a privatized "
4787 "variable that needs mapping");
4792 auto mapInfoOp = mappedValue.
getDefiningOp<omp::MapInfoOp>();
4793 [[maybe_unused]]
Type varType = mapInfoOp.getVarType();
4797 if (!isa<LLVM::LLVMPointerType>(privVar.getType()))
4799 varType == privVar.getType() &&
4800 "Type of private var doesn't match the type of the mapped value");
4804 mappedPrivateVars.insert(
4806 targetRegion.getArgument(argIface.getMapBlockArgsStart() +
4807 (*privateMapIndices)[privVarIdx])});
4811 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4812 auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP)
4813 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
4814 llvm::IRBuilderBase::InsertPointGuard guard(builder);
4815 builder.SetCurrentDebugLocation(llvm::DebugLoc());
4818 llvm::Function *llvmParentFn =
4820 llvmOutlinedFn = codeGenIP.getBlock()->getParent();
4821 assert(llvmParentFn && llvmOutlinedFn &&
4822 "Both parent and outlined functions must exist at this point");
4824 if (
auto attr = llvmParentFn->getFnAttribute(
"target-cpu");
4825 attr.isStringAttribute())
4826 llvmOutlinedFn->addFnAttr(attr);
4828 if (
auto attr = llvmParentFn->getFnAttribute(
"target-features");
4829 attr.isStringAttribute())
4830 llvmOutlinedFn->addFnAttr(attr);
4832 for (
auto [arg, mapOp] : llvm::zip_equal(mapBlockArgs, mapVars)) {
4833 auto mapInfoOp = cast<omp::MapInfoOp>(mapOp.getDefiningOp());
4834 llvm::Value *mapOpValue =
4835 moduleTranslation.
lookupValue(mapInfoOp.getVarPtr());
4836 moduleTranslation.
mapValue(arg, mapOpValue);
4838 for (
auto [arg, mapOp] : llvm::zip_equal(hdaBlockArgs, hdaVars)) {
4839 auto mapInfoOp = cast<omp::MapInfoOp>(mapOp.getDefiningOp());
4840 llvm::Value *mapOpValue =
4841 moduleTranslation.
lookupValue(mapInfoOp.getVarPtr());
4842 moduleTranslation.
mapValue(arg, mapOpValue);
4851 allocaIP, &mappedPrivateVars);
4854 return llvm::make_error<PreviouslyReportedError>();
4856 builder.restoreIP(codeGenIP);
4858 &mappedPrivateVars),
4861 return llvm::make_error<PreviouslyReportedError>();
4865 std::back_inserter(privateCleanupRegions),
4866 [](omp::PrivateClauseOp privatizer) {
4867 return &privatizer.getDeallocRegion();
4871 targetRegion,
"omp.target", builder, moduleTranslation);
4874 return exitBlock.takeError();
4876 builder.SetInsertPoint(*exitBlock);
4877 if (!privateCleanupRegions.empty()) {
4879 privateCleanupRegions, privateVarsInfo.
llvmVars,
4880 moduleTranslation, builder,
"omp.targetop.private.cleanup",
4882 return llvm::createStringError(
4883 "failed to inline `dealloc` region of `omp.private` "
4884 "op in the target region");
4886 return builder.saveIP();
4889 return InsertPointTy(exitBlock.get(), exitBlock.get()->end());
4892 StringRef parentName = parentFn.getName();
4894 llvm::TargetRegionEntryInfo entryInfo;
4898 MapInfoData mapData;
4903 MapInfosTy combinedInfos;
4905 [&](llvm::OpenMPIRBuilder::InsertPointTy codeGenIP) -> MapInfosTy & {
4906 builder.restoreIP(codeGenIP);
4907 genMapInfos(builder, moduleTranslation, dl, combinedInfos, mapData,
true);
4908 return combinedInfos;
4911 auto argAccessorCB = [&](llvm::Argument &arg, llvm::Value *input,
4912 llvm::Value *&retVal, InsertPointTy allocaIP,
4913 InsertPointTy codeGenIP)
4914 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
4915 llvm::IRBuilderBase::InsertPointGuard guard(builder);
4916 builder.SetCurrentDebugLocation(llvm::DebugLoc());
4922 if (!isTargetDevice) {
4923 retVal = cast<llvm::Value>(&arg);
4928 *ompBuilder, moduleTranslation,
4929 allocaIP, codeGenIP);
4932 llvm::OpenMPIRBuilder::TargetKernelRuntimeAttrs runtimeAttrs;
4933 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs defaultAttrs;
4934 Operation *targetCapturedOp = targetOp.getInnermostCapturedOmpOp();
4940 if (!isTargetDevice)
4942 targetCapturedOp, runtimeAttrs);
4950 for (
auto [arg, var] : llvm::zip_equal(hostEvalBlockArgs, hostEvalVars)) {
4951 llvm::Value *value = moduleTranslation.
lookupValue(var);
4952 moduleTranslation.
mapValue(arg, value);
4954 if (!llvm::isa<llvm::Constant>(value))
4955 kernelInput.push_back(value);
4958 for (
size_t i = 0, e = mapData.OriginalValue.size(); i != e; ++i) {
4965 if (!mapData.IsDeclareTarget[i] && !mapData.IsAMember[i])
4966 kernelInput.push_back(mapData.OriginalValue[i]);
4971 moduleTranslation, dds);
4973 llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
4975 llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
4977 llvm::OpenMPIRBuilder::TargetDataInfo info(
4981 auto customMapperCB =
4983 if (!combinedInfos.Mappers[i])
4985 info.HasMapper =
true;
4990 llvm::Value *ifCond =
nullptr;
4991 if (
Value targetIfCond = targetOp.getIfExpr())
4992 ifCond = moduleTranslation.
lookupValue(targetIfCond);
4994 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
4996 ompLoc, isOffloadEntry, allocaIP, builder.saveIP(), info, entryInfo,
4997 defaultAttrs, runtimeAttrs, ifCond, kernelInput, genMapInfoCB, bodyCB,
4998 argAccessorCB, customMapperCB, dds, targetOp.getNowait());
5003 builder.restoreIP(*afterIP);
5014 static LogicalResult
5024 if (FunctionOpInterface funcOp = dyn_cast<FunctionOpInterface>(op)) {
5025 if (
auto offloadMod = dyn_cast<omp::OffloadModuleInterface>(
5027 if (!offloadMod.getIsTargetDevice())
5030 omp::DeclareTargetDeviceType declareType =
5031 attribute.getDeviceType().getValue();
5033 if (declareType == omp::DeclareTargetDeviceType::host) {
5034 llvm::Function *llvmFunc =
5036 llvmFunc->dropAllReferences();
5037 llvmFunc->eraseFromParent();
5043 if (LLVM::GlobalOp gOp = dyn_cast<LLVM::GlobalOp>(op)) {
5044 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
5045 if (
auto *gVal = llvmModule->getNamedValue(gOp.getSymName())) {
5047 bool isDeclaration = gOp.isDeclaration();
5048 bool isExternallyVisible =
5051 llvm::StringRef mangledName = gOp.getSymName();
5052 auto captureClause =
5058 std::vector<llvm::GlobalVariable *> generatedRefs;
5060 std::vector<llvm::Triple> targetTriple;
5061 auto targetTripleAttr = dyn_cast_or_null<mlir::StringAttr>(
5063 LLVM::LLVMDialect::getTargetTripleAttrName()));
5064 if (targetTripleAttr)
5065 targetTriple.emplace_back(targetTripleAttr.data());
5067 auto fileInfoCallBack = [&loc]() {
5068 std::string filename =
"";
5069 std::uint64_t lineNo = 0;
5072 filename = loc.getFilename().str();
5073 lineNo = loc.getLine();
5076 return std::pair<std::string, std::uint64_t>(llvm::StringRef(filename),
5080 ompBuilder->registerTargetGlobalVariable(
5081 captureClause, deviceClause, isDeclaration, isExternallyVisible,
5082 ompBuilder->getTargetEntryUniqueInfo(fileInfoCallBack), mangledName,
5083 generatedRefs,
false, targetTriple,
5085 gVal->getType(), gVal);
5087 if (ompBuilder->Config.isTargetDevice() &&
5088 (attribute.getCaptureClause().getValue() !=
5089 mlir::omp::DeclareTargetCaptureClause::to ||
5090 ompBuilder->Config.hasRequiresUnifiedSharedMemory())) {
5091 ompBuilder->getAddrOfDeclareTargetVar(
5092 captureClause, deviceClause, isDeclaration, isExternallyVisible,
5093 ompBuilder->getTargetEntryUniqueInfo(fileInfoCallBack), mangledName,
5094 generatedRefs,
false, targetTriple, gVal->getType(),
5116 if (mlir::isa<omp::ThreadprivateOp>(op))
5120 if (
auto declareTargetIface =
5121 llvm::dyn_cast<mlir::omp::DeclareTargetInterface>(
5122 parentFn.getOperation()))
5123 if (declareTargetIface.isDeclareTarget() &&
5124 declareTargetIface.getDeclareTargetDeviceType() !=
5125 mlir::omp::DeclareTargetDeviceType::host)
5133 static LogicalResult
5144 bool isOutermostLoopWrapper =
5145 isa_and_present<omp::LoopWrapperInterface>(op) &&
5146 !dyn_cast_if_present<omp::LoopWrapperInterface>(op->
getParentOp());
5148 if (isOutermostLoopWrapper)
5149 moduleTranslation.
stackPush<OpenMPLoopInfoStackFrame>();
5153 .Case([&](omp::BarrierOp op) -> LogicalResult {
5157 llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
5158 ompBuilder->createBarrier(builder.saveIP(),
5159 llvm::omp::OMPD_barrier);
5162 .Case([&](omp::TaskyieldOp op) {
5166 ompBuilder->createTaskyield(builder.saveIP());
5169 .Case([&](omp::FlushOp op) {
5181 ompBuilder->createFlush(builder.saveIP());
5184 .Case([&](omp::ParallelOp op) {
5187 .Case([&](omp::MaskedOp) {
5190 .Case([&](omp::MasterOp) {
5193 .Case([&](omp::CriticalOp) {
5196 .Case([&](omp::OrderedRegionOp) {
5199 .Case([&](omp::OrderedOp) {
5202 .Case([&](omp::WsloopOp) {
5205 .Case([&](omp::SimdOp) {
5208 .Case([&](omp::AtomicReadOp) {
5211 .Case([&](omp::AtomicWriteOp) {
5214 .Case([&](omp::AtomicUpdateOp op) {
5217 .Case([&](omp::AtomicCaptureOp op) {
5220 .Case([&](omp::SectionsOp) {
5223 .Case([&](omp::SingleOp op) {
5226 .Case([&](omp::TeamsOp op) {
5229 .Case([&](omp::TaskOp op) {
5232 .Case([&](omp::TaskgroupOp op) {
5235 .Case([&](omp::TaskwaitOp op) {
5238 .Case<omp::YieldOp, omp::TerminatorOp, omp::DeclareMapperOp,
5239 omp::DeclareMapperInfoOp, omp::DeclareReductionOp,
5240 omp::CriticalDeclareOp>([](
auto op) {
5253 .Case([&](omp::ThreadprivateOp) {
5256 .Case<omp::TargetDataOp, omp::TargetEnterDataOp,
5257 omp::TargetExitDataOp, omp::TargetUpdateOp>([&](
auto op) {
5260 .Case([&](omp::TargetOp) {
5263 .Case([&](omp::DistributeOp) {
5266 .Case([&](omp::LoopNestOp) {
5269 .Case<omp::MapInfoOp, omp::MapBoundsOp, omp::PrivateClauseOp>(
5278 <<
"not yet implemented: " << inst->
getName();
5281 if (isOutermostLoopWrapper)
5287 static LogicalResult
5293 static LogicalResult
5296 if (isa<omp::TargetOp>(op))
5298 if (isa<omp::TargetDataOp>(op))
5302 if (isa<omp::TargetOp>(oper)) {
5304 return WalkResult::interrupt();
5305 return WalkResult::skip();
5307 if (isa<omp::TargetDataOp>(oper)) {
5309 return WalkResult::interrupt();
5310 return WalkResult::skip();
5317 if (isa<omp::OpenMPDialect>(oper->getDialect()) &&
5318 oper->getParentOfType<LLVM::LLVMFuncOp>() &&
5319 !oper->getRegions().empty()) {
5320 if (
auto blockArgsIface =
5321 dyn_cast<omp::BlockArgOpenMPOpInterface>(oper))
5327 if (isa<mlir::omp::AtomicUpdateOp>(oper))
5328 for (
auto [operand, arg] :
5329 llvm::zip_equal(oper->getOperands(),
5330 oper->getRegion(0).getArguments())) {
5332 arg, builder.CreateLoad(
5338 if (
auto loopNest = dyn_cast<omp::LoopNestOp>(oper)) {
5339 assert(builder.GetInsertBlock() &&
5340 "No insert block is set for the builder");
5341 for (
auto iv : loopNest.getIVs()) {
5349 for (
Region ®ion : oper->getRegions()) {
5356 region, oper->getName().getStringRef().str() +
".fake.region",
5357 builder, moduleTranslation, &phis);
5359 return WalkResult::interrupt();
5361 builder.SetInsertPoint(result.get(), result.get()->end());
5364 return WalkResult::skip();
5367 return WalkResult::advance();
5368 }).wasInterrupted();
5369 return failure(interrupted);
5376 class OpenMPDialectLLVMIRTranslationInterface
5397 LogicalResult OpenMPDialectLLVMIRTranslationInterface::amendOperation(
5403 .Case(
"omp.is_target_device",
5405 if (
auto deviceAttr = dyn_cast<BoolAttr>(attr)) {
5406 llvm::OpenMPIRBuilderConfig &
config =
5408 config.setIsTargetDevice(deviceAttr.getValue());
5415 if (
auto gpuAttr = dyn_cast<BoolAttr>(attr)) {
5416 llvm::OpenMPIRBuilderConfig &
config =
5418 config.setIsGPU(gpuAttr.getValue());
5423 .Case(
"omp.host_ir_filepath",
5425 if (
auto filepathAttr = dyn_cast<StringAttr>(attr)) {
5426 llvm::OpenMPIRBuilder *ompBuilder =
5428 ompBuilder->loadOffloadInfoMetadata(filepathAttr.getValue());
5435 if (
auto rtlAttr = dyn_cast<omp::FlagsAttr>(attr))
5439 .Case(
"omp.version",
5441 if (
auto versionAttr = dyn_cast<omp::VersionAttr>(attr)) {
5442 llvm::OpenMPIRBuilder *ompBuilder =
5444 ompBuilder->M.addModuleFlag(llvm::Module::Max,
"openmp",
5445 versionAttr.getVersion());
5450 .Case(
"omp.declare_target",
5452 if (
auto declareTargetAttr =
5453 dyn_cast<omp::DeclareTargetAttr>(attr))
5458 .Case(
"omp.requires",
5460 if (
auto requiresAttr = dyn_cast<omp::ClauseRequiresAttr>(attr)) {
5461 using Requires = omp::ClauseRequires;
5462 Requires flags = requiresAttr.getValue();
5463 llvm::OpenMPIRBuilderConfig &
config =
5465 config.setHasRequiresReverseOffload(
5466 bitEnumContainsAll(flags, Requires::reverse_offload));
5467 config.setHasRequiresUnifiedAddress(
5468 bitEnumContainsAll(flags, Requires::unified_address));
5469 config.setHasRequiresUnifiedSharedMemory(
5470 bitEnumContainsAll(flags, Requires::unified_shared_memory));
5471 config.setHasRequiresDynamicAllocators(
5472 bitEnumContainsAll(flags, Requires::dynamic_allocators));
5477 .Case(
"omp.target_triples",
5479 if (
auto triplesAttr = dyn_cast<ArrayAttr>(attr)) {
5480 llvm::OpenMPIRBuilderConfig &
config =
5482 config.TargetTriples.clear();
5483 config.TargetTriples.reserve(triplesAttr.size());
5484 for (
Attribute tripleAttr : triplesAttr) {
5485 if (
auto tripleStrAttr = dyn_cast<StringAttr>(tripleAttr))
5486 config.TargetTriples.emplace_back(tripleStrAttr.getValue());
5504 LogicalResult OpenMPDialectLLVMIRTranslationInterface::convertOperation(
5505 Operation *op, llvm::IRBuilderBase &builder,
5509 if (ompBuilder->Config.isTargetDevice()) {
5520 registry.
insert<omp::OpenMPDialect>();
5522 dialect->addInterfaces<OpenMPDialectLLVMIRTranslationInterface>();
union mlir::linalg::@1183::ArityGroupAndKind::Kind kind
static llvm::Value * getRefPtrIfDeclareTarget(mlir::Value value, LLVM::ModuleTranslation &moduleTranslation)
static void handleDeclareTargetMapVar(MapInfoData &mapData, LLVM::ModuleTranslation &moduleTranslation, llvm::IRBuilderBase &builder, llvm::Function *func)
static LogicalResult convertOmpAtomicUpdate(omp::AtomicUpdateOp &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP atomic update operation using OpenMPIRBuilder.
static llvm::omp::OrderKind convertOrderKind(std::optional< omp::ClauseOrderKind > o)
Convert Order attribute to llvm::omp::OrderKind.
static llvm::Expected< llvm::Function * > emitUserDefinedMapper(Operation *declMapperOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, llvm::StringRef mapperFuncName)
static LogicalResult convertOmpAtomicCapture(omp::AtomicCaptureOp atomicCaptureOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static llvm::Expected< llvm::Value * > initPrivateVar(llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, omp::PrivateClauseOp &privDecl, Value mlirPrivVar, BlockArgument &blockArg, llvm::Value *llvmPrivateVar, llvm::BasicBlock *privInitBlock, llvm::DenseMap< Value, Value > *mappedPrivateVars=nullptr)
Initialize a single (first)private variable.
static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind convertToCaptureClauseKind(mlir::omp::DeclareTargetCaptureClause captureClause)
static omp::MapInfoOp getFirstOrLastMappedMemberPtr(omp::MapInfoOp mapInfo, bool first)
static OpTy castOrGetParentOfType(Operation *op, bool immediateParent=false)
If op is of the given type parameter, return it casted to that type.
static LogicalResult convertOmpOrderedRegion(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP 'ordered_region' operation into LLVM IR using OpenMPIRBuilder.
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 LogicalResult convertOmpWsloop(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP workshare loop into LLVM IR using OpenMPIRBuilder.
static LogicalResult convertOmpMaster(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP 'master' operation into LLVM IR using OpenMPIRBuilder.
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 LogicalResult convertOmpTaskwaitOp(omp::TaskwaitOp twOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static LogicalResult convertOmpLoopNest(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP loop nest into LLVM IR using OpenMPIRBuilder.
static LogicalResult cleanupPrivateVars(llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, Location loc, SmallVectorImpl< llvm::Value * > &llvmPrivateVars, SmallVectorImpl< omp::PrivateClauseOp > &privateDecls)
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 llvm::Expected< llvm::BasicBlock * > allocatePrivateVars(llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, PrivateVarsInfo &privateVarsInfo, const llvm::OpenMPIRBuilder::InsertPointTy &allocaIP, llvm::DenseMap< Value, Value > *mappedPrivateVars=nullptr)
Allocate and initialize delayed private variables.
llvm::AtomicRMWInst::BinOp convertBinOpToAtomic(Operation &op)
Converts an LLVM dialect binary operation to the corresponding enum value for atomicrmw supported bin...
static llvm::AtomicOrdering convertAtomicOrdering(std::optional< omp::ClauseMemoryOrderKind > ao)
Convert an Atomic Ordering attribute to llvm::AtomicOrdering.
static void setInsertPointForPossiblyEmptyBlock(llvm::IRBuilderBase &builder, llvm::BasicBlock *block=nullptr)
static LogicalResult convertOmpSections(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static LogicalResult convertOmpCritical(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP 'critical' operation into LLVM IR using OpenMPIRBuilder.
static LogicalResult convertOmpTargetData(Operation *op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static LogicalResult allocAndInitializeReductionVars(OP op, ArrayRef< BlockArgument > reductionArgs, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, llvm::OpenMPIRBuilder::InsertPointTy &allocaIP, SmallVectorImpl< omp::DeclareReductionOp > &reductionDecls, SmallVectorImpl< llvm::Value * > &privateReductionVariables, DenseMap< Value, llvm::Value * > &reductionVariableMap, llvm::ArrayRef< bool > isByRef)
static LogicalResult convertOmpSimd(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP simd loop into LLVM IR using OpenMPIRBuilder.
static LogicalResult convertOmpDistribute(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static void processIndividualMap(MapInfoData &mapData, size_t mapDataIdx, MapInfosTy &combinedInfo, bool isTargetParams, int mapDataParentIdx=-1)
static LogicalResult convertOmpOrdered(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP 'ordered' operation into LLVM IR using OpenMPIRBuilder.
static LogicalResult convertOmpMasked(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP 'masked' operation into LLVM IR using OpenMPIRBuilder.
static bool isTargetDeviceOp(Operation *op)
static 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 void mapInitializationArgs(T loop, LLVM::ModuleTranslation &moduleTranslation, SmallVectorImpl< omp::DeclareReductionOp > &reductionDecls, DenseMap< Value, llvm::Value * > &reductionVariableMap, unsigned i)
Map input arguments to reduction initialization region.
static LogicalResult initReductionVars(OP op, ArrayRef< BlockArgument > reductionArgs, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, llvm::BasicBlock *latestAllocaBlock, SmallVectorImpl< omp::DeclareReductionOp > &reductionDecls, SmallVectorImpl< llvm::Value * > &privateReductionVariables, DenseMap< Value, llvm::Value * > &reductionVariableMap, llvm::ArrayRef< bool > isByRef, SmallVectorImpl< DeferredStore > &deferredStores)
Inline reductions' init regions.
static int getMapDataMemberIdx(MapInfoData &mapData, omp::MapInfoOp memberOp)
static llvm::Error initPrivateVars(llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, PrivateVarsInfo &privateVarsInfo, llvm::DenseMap< Value, Value > *mappedPrivateVars=nullptr)
static llvm::SmallString< 64 > getDeclareTargetRefPtrSuffix(LLVM::GlobalOp globalOp, llvm::OpenMPIRBuilder &ompBuilder)
static OwningReductionGen makeReductionGen(omp::DeclareReductionOp decl, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Create an OpenMPIRBuilder-compatible reduction generator for the given reduction declaration.
static LogicalResult convertOmpParallel(omp::ParallelOp opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts the OpenMP parallel operation to LLVM IR.
static llvm::OpenMPIRBuilder::InsertPointTy findAllocaInsertPoint(llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Find the insertion point for allocas given the current insertion point for normal operations in the b...
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 LogicalResult convertOmpThreadprivate(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP Threadprivate operation into LLVM IR using OpenMPIRBuilder.
static omp::PrivateClauseOp findPrivatizer(Operation *from, SymbolRefAttr symbolName)
Looks up from the operation from and returns the PrivateClauseOp with name symbolName.
static LogicalResult convertDeclareTargetAttr(Operation *op, mlir::omp::DeclareTargetAttr attribute, LLVM::ModuleTranslation &moduleTranslation)
static void genMapInfos(llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, DataLayout &dl, MapInfosTy &combinedInfo, MapInfoData &mapData, bool isTargetParams=false)
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)
LogicalResult convertFlagsAttr(Operation *op, mlir::omp::FlagsAttr attribute, LLVM::ModuleTranslation &moduleTranslation)
Lowers the FlagsAttr which is applied to the module on the device pass when offloading,...
static void getTargetEntryUniqueInfo(llvm::TargetRegionEntryInfo &targetInfo, omp::TargetOp targetOp, llvm::StringRef parentName="")
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...
uint64_t getArrayElementSizeInBits(LLVM::LLVMArrayType arrTy, DataLayout &dl)
std::vector< llvm::Value * > calculateBoundsOffset(LLVM::ModuleTranslation &moduleTranslation, llvm::IRBuilderBase &builder, bool isArrayTy, OperandRange bounds)
This function calculates the array/pointer offset for map data provided with bounds operations,...
static llvm::omp::OpenMPOffloadMappingFlags mapParentWithMembers(LLVM::ModuleTranslation &moduleTranslation, llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder &ompBuilder, DataLayout &dl, MapInfosTy &combinedInfo, MapInfoData &mapData, uint64_t mapDataIndex, bool isTargetParams)
static llvm::Expected< llvm::Function * > getOrCreateUserDefinedMapperFunc(Operation *op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static void forwardArgs(LLVM::ModuleTranslation &moduleTranslation, omp::BlockArgOpenMPOpInterface blockArgIface)
Maps block arguments from blockArgIface (which are MLIR values) to the corresponding LLVM values of t...
static LogicalResult allocReductionVars(T loop, 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 ArrayRef< bool > getIsByRef(std::optional< ArrayRef< bool >> attr)
static llvm::IRBuilderBase::InsertPoint createDeviceArgumentAccessor(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)
static LogicalResult copyFirstPrivateVars(llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, SmallVectorImpl< mlir::Value > &mlirPrivateVars, ArrayRef< llvm::Value * > llvmPrivateVars, SmallVectorImpl< omp::PrivateClauseOp > &privateDecls)
static llvm::omp::ProcBindKind getProcBindKind(omp::ClauseProcBindKind kind)
Convert ProcBindKind from MLIR-generated enum to LLVM enum.
static LogicalResult convertTargetOpsInNest(Operation *op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static LogicalResult convertOmpSingle(omp::SingleOp &singleOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP single construct into LLVM IR using OpenMPIRBuilder.
static void processMapWithMembersOf(LLVM::ModuleTranslation &moduleTranslation, llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder &ompBuilder, DataLayout &dl, MapInfosTy &combinedInfo, MapInfoData &mapData, uint64_t mapDataIndex, bool isTargetParams)
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 void processMapMembersWithParent(LLVM::ModuleTranslation &moduleTranslation, llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder &ompBuilder, DataLayout &dl, MapInfosTy &combinedInfo, MapInfoData &mapData, uint64_t mapDataIndex, llvm::omp::OpenMPOffloadMappingFlags memberOfFlag)
static LogicalResult convertOmpTarget(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind convertToDeviceClauseKind(mlir::omp::DeclareTargetDeviceType deviceClause)
static LogicalResult checkImplementationStatus(Operation &op)
Check whether translation to LLVM IR for the given operation is currently supported.
static llvm::CanonicalLoopInfo * findCurrentLoopInfo(LLVM::ModuleTranslation &moduleTranslation)
Find the loop information structure for the loop nest being translated.
static LogicalResult convertOmpAtomicRead(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Convert omp.atomic.read operation to LLVM IR.
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 LogicalResult convertIgnoredWrapper(omp::LoopWrapperInterface opInst, LLVM::ModuleTranslation &moduleTranslation)
Helper function to map block arguments defined by ignored loop wrappers to LLVM values and prevent an...
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 void collectReductionInfo(T loop, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, SmallVectorImpl< omp::DeclareReductionOp > &reductionDecls, SmallVectorImpl< OwningReductionGen > &owningReductionGens, SmallVectorImpl< OwningAtomicReductionGen > &owningAtomicReductionGens, const ArrayRef< llvm::Value * > privateReductionVariables, SmallVectorImpl< llvm::OpenMPIRBuilder::ReductionInfo > &reductionInfos)
Collect reduction info.
static LogicalResult convertOmpTeams(omp::TeamsOp op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static void initTargetDefaultAttrs(omp::TargetOp targetOp, Operation *capturedOp, llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &attrs, bool isTargetDevice)
Populate default MinTeams, MaxTeams and MaxThreads to their default values as stated by the correspon...
static LogicalResult convertHostOrTargetOperation(Operation *op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Given an OpenMP MLIR operation, create the corresponding LLVM IR (including OpenMP runtime calls).
static bool checkIfPointerMap(omp::MapInfoOp mapOp)
static LogicalResult convertTargetDeviceOp(Operation *op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static void buildDependData(std::optional< ArrayAttr > dependKinds, OperandRange dependVars, LLVM::ModuleTranslation &moduleTranslation, SmallVectorImpl< llvm::OpenMPIRBuilder::DependData > &dds)
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 convertOmpTaskgroupOp(omp::TaskgroupOp tgOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Converts an OpenMP taskgroup construct into LLVM IR using OpenMPIRBuilder.
llvm::Value * getSizeInBytes(DataLayout &dl, const mlir::Type &type, Operation *clauseOp, llvm::Value *basePointer, llvm::Type *baseType, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
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 bool isDeclareTargetLink(mlir::Value value)
#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()
Operation * getTerminator()
Get the terminator operation of this block.
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 dialect interfaces providing translation to LLVM IR.
virtual LogicalResult amendOperation(Operation *op, ArrayRef< llvm::Instruction * > instructions, NamedAttribute attribute, LLVM::ModuleTranslation &moduleTranslation) const
Hook for derived dialect interface to act on an operation that has dialect attributes from the derive...
virtual LogicalResult convertOperation(Operation *op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation) const
Hook for derived dialect interface to provide translation of the operations to LLVM IR.
LLVMTranslationDialectInterface(Dialect *dialect)
Concrete CRTP base class for ModuleTranslation stack frames.
Implementation class for module translation.
llvm::Value * lookupValue(Value value) const
Finds an LLVM IR value corresponding to the given MLIR value.
WalkResult stackWalk(llvm::function_ref< WalkResult(T &)> callback)
Calls callback for every ModuleTranslation stack frame of type T starting from the top of the stack.
void stackPush(Args &&...args)
Creates a stack frame of type T on ModuleTranslation stack.
LogicalResult convertBlock(Block &bb, bool ignoreArguments, llvm::IRBuilderBase &builder)
Translates the contents of the given block to LLVM IR using this translator.
SmallVector< llvm::Value * > lookupValues(ValueRange values)
Looks up remapped a list of remapped values.
void mapFunction(StringRef name, llvm::Function *func)
Stores the mapping between a function name and its LLVM IR representation.
llvm::BasicBlock * lookupBlock(Block *block) const
Finds an LLVM IR basic block that corresponds to the given MLIR block.
SymbolTableCollection & symbolTable()
llvm::Type * convertType(Type type)
Converts the type from MLIR LLVM dialect to LLVM.
llvm::OpenMPIRBuilder * getOpenMPBuilder()
Returns the OpenMP IR builder associated with the LLVM IR module being constructed.
llvm::LLVMContext & getLLVMContext() const
Returns the LLVM context in which the IR is being constructed.
llvm::GlobalValue * lookupGlobal(Operation *op)
Finds an LLVM IR global value that corresponds to the given MLIR operation defining a global value.
llvm::Module * getLLVMModule()
Returns the LLVM module in which the IR is being constructed.
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.
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.
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.
NamedAttribute represents a combination of a name and an Attribute value.
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.
Operation is the basic unit of execution within MLIR.
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.
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),...
Location getLoc()
The source location the operation was defined or derived from.
unsigned getNumOperands()
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
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'.
Region & getRegion(unsigned index)
Returns the region held by this operation at position 'index'.
OperationName getName()
The name of an operation is the key identifier for it.
operand_range getOperands()
Returns an iterator on the underlying Value's.
user_range getUsers()
Returns a range of all users.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
BlockArgListType getArguments()
Operation * getParentOp()
Return the parent operation this region is attached to.
unsigned getNumArguments()
BlockListType & getBlocks()
@ Private
The symbol is private and may only be referenced by SymbolRefAttrs local to the operations within the...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
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:
bool wasInterrupted() const
Returns true if the walk was interrupted.
static WalkResult interrupt()
The OpAsmOpInterface, see OpAsmInterface.td for more details.
void connectPHINodes(Region ®ion, const ModuleTranslation &state)
For all blocks in the region that were converted to LLVM IR using the given ModuleTranslation,...
llvm::Constant * createMappingInformation(Location loc, llvm::OpenMPIRBuilder &builder)
Create a constant string representing the mapping information extracted from the MLIR location inform...
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
Runtime
Potential runtimes for AMD GPU kernels.
inline ::llvm::hash_code hash_value(const PolynomialBase< D, T > &arg)
Include the generated interface declarations.
SetVector< Block * > getBlocksSortedByDominance(Region ®ion)
Gets a list of blocks that is sorted according to dominance.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
const FrozenRewritePatternSet GreedyRewriteConfig config
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
void registerOpenMPDialectTranslation(DialectRegistry ®istry)
Register the OpenMP dialect and the translation from it to the LLVM IR in the given registry;.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
A util to collect info needed to convert delayed privatizers from MLIR to LLVM.
SmallVector< mlir::Value > mlirVars
SmallVector< omp::PrivateClauseOp > privatizers
MutableArrayRef< BlockArgument > blockArgs
SmallVector< llvm::Value * > llvmVars
RAII object calling stackPush/stackPop on construction/destruction.