26#include "llvm/ADT/STLExtras.h"
27#include "llvm/ADT/SmallVector.h"
28#include "llvm/ADT/TypeSwitch.h"
29#include "llvm/Support/MathExtras.h"
44 if (
auto mod = llvm::dyn_cast<ModuleOp>(current)) {
45 if (mod.getDataLayoutSpec())
47 }
else if (
auto dataLayoutOp =
48 llvm::dyn_cast<DataLayoutOpInterface>(current)) {
50 if (dataLayoutOp.getDataLayoutSpec())
59 if (
auto mod = llvm::dyn_cast<ModuleOp>(op))
78 for (
auto val : output)
79 resultTypes.push_back(val.getType());
81 ComputeRegionOp::create(rewriter, loc, resultTypes, launchArgs, inputArgs,
82 stream, origin, kernelFuncName, kernelModuleName);
84 assert(!regionToClone.
getBlocks().empty() &&
85 "empty region for acc.compute_region");
88 ValueRange mapKeys = inputArgsToMap.empty() ? inputArgs : inputArgsToMap;
89 assert(mapKeys.size() == inputArgs.size() &&
90 "inputArgsToMap must have same size as inputArgs when provided");
94 for (
size_t i = 0; i < launchArgs.size(); ++i)
96 for (
Value input : inputArgs)
98 for (
size_t i = 0; i < inputArgs.size(); ++i)
99 mapping.
map(mapKeys[i], entryBlock->
getArgument(launchArgs.size() + i));
101 if (regionToClone.
getBlocks().size() == 1) {
105 rewriter.
clone(op, mapping);
108 for (
auto val : output)
109 yieldOperands.push_back(mapping.
lookup(val));
111 YieldOp::create(rewriter, loc, yieldOperands);
114 regionToClone, mapping, loc, rewriter);
116 rewriter.
eraseOp(computeRegion);
120 llvm::to_vector(exeRegion.getOps<scf::YieldOp>()));
121 assert(!yieldOps.empty() &&
122 "multi-block region must contain at least one scf.yield");
123 assert(llvm::all_of(yieldOps,
124 [&output](scf::YieldOp yieldOp) {
125 return yieldOp.getNumOperands() ==
126 static_cast<int64_t>(output.size()) &&
128 llvm::zip(yieldOp.getOperands(), output),
130 return std::get<0>(pair).getType() ==
131 std::get<1>(pair).getType();
134 "each scf.yield operand count and types must match output");
136 YieldOp::create(rewriter, loc, exeRegion.getResults());
139 return computeRegion;
144 GPUParallelDimAttr parDim) {
145 return llvm::lower_bound(
147 [](
const GPUParallelDimAttr &lhs,
const GPUParallelDimAttr &rhs) {
148 return lhs.getOrder() > rhs.getOrder();
153 GPUParallelDimAttr parDim) {
155 if (lb == parDims.end() || *lb != parDim)
156 parDims.insert(lb, parDim);
160 GPUParallelDimAttr parDim) {
162 if (lb != parDims.end() && *lb == parDim)
166#define ACC_OP_WITH_PAR_DIMS_LIST \
167 PrivatizeOp, ReductionAccumulateOp, ReductionAccumulateArrayOp, \
173 [](
auto parOp) {
return parOp.getParDimsAttr(); })
174 .Default([](
Operation *op) -> GPUParallelDimsAttr {
177 GPUParallelDimsAttr parDimsAttr = dyn_cast<GPUParallelDimsAttr>(attr);
178 assert(parDimsAttr &&
"acc.par_dims must be a GPUParallelDimsAttr");
189 return parDimsAttr.isSeq();
194 assert(!
hasParDimsAttr(op) &&
"parallel dimensions attribute is already set");
197 [&](
auto parOp) { parOp.setParDimsAttr(attr); })
205 "expected parallel dimensions attribute to already be set");
208 [&](
auto parOp) { parOp.setParDimsAttr(attr); })
214#undef ACC_OP_WITH_PAR_DIMS_LIST
218 GPUBlockRedundantAttr::name);
223 GPUBlockRedundantAttr::get(op->
getContext()));
228 "expected parallel dimensions attribute to already be set");
234 ActiveParDimsAttr::name);
250 assert(alignment > 0 && llvm::isPowerOf2_64(alignment) &&
251 "alignment must be a power of two");
252 return (offset + alignment - 1) & ~(alignment - 1);
257 if (aligned + bytes > maxTotalBytes_) {
260 bytesUsed_ = aligned + bytes;
266 region.
walk([&](GPUSharedMemoryOp op) {
267 int64_t upperBound = op.getStaticUpperBoundBytes();
274 ComputeRegionOp computeRegion) {
275 Value value = privateLocal.getPrivatized();
276 if (
BlockArgument blockArg = dyn_cast<BlockArgument>(value)) {
277 auto owner = dyn_cast<ComputeRegionOp>(blockArg.getOwner()->getParentOp());
278 value = (owner ? owner : computeRegion).getOperand(blockArg);
280 PrivatizeOp privatizeOp = value.
getDefiningOp<PrivatizeOp>();
281 assert(privatizeOp &&
"expected privatize op to be the defining op");
286 if (GPUParallelDimsAttr parDimsAttr = privatize.getParDimsAttr())
287 return llvm::any_of(parDimsAttr.getArray(),
288 [](GPUParallelDimAttr d) { return d.isThreadX(); });
293 auto memrefTy = cast<PointerLikeType>(baseTy).getAsMemRefType(module);
294 assert(memrefTy &&
"private base type must be convertible to memref");
300 ComputeRegionOp computeRegion) {
305 auto parentLoop = privateLocal->getParentOfType<scf::ParallelOp>();
306 while (parentLoop && computeRegion->isProperAncestor(parentLoop)) {
308 for (GPUParallelDimAttr parDim : parDimsAttr.getArray())
310 parentLoop = parentLoop->getParentOfType<scf::ParallelOp>();
312 if (GPUParallelDimsAttr parDimsAttr =
getParDimsAttr(computeRegion))
313 for (GPUParallelDimAttr parDim : parDimsAttr.getArray())
315 if (parDims.empty()) {
316 for (GPUParallelDimAttr parDim : computeRegion.getLaunchParDims()) {
317 if (parDim.isAnyBlock())
323 if (
auto accumulateOp = dyn_cast<ReductionAccumulateOp>(user)) {
324 if (accumulateOp.getMemref() == privateLocal.getResult())
325 for (GPUParallelDimAttr parDim : accumulateOp.getParDims().getArray())
328 if (
auto combineOp = dyn_cast<ReductionCombineOp>(user)) {
329 if (combineOp.getSrcMemref() == privateLocal.getResult())
333 if (
auto combineRegionOp = dyn_cast<ReductionCombineRegionOp>(user)) {
334 if (combineRegionOp.getSrcVar() == privateLocal.getResult())
335 for (GPUParallelDimAttr parDim :
344 PrivateLocalOp privateLocal, ComputeRegionOp computeRegion,
346 if (!isWorkerPrivate)
347 return std::optional<int64_t>(1);
349 GPUParallelDimAttr threadY =
350 GPUParallelDimAttr::threadYDim(privateLocal.getContext());
351 std::optional<Value> workerArg = computeRegion.getKnownLaunchArg(threadY);
353 return std::optional<int64_t>();
357 return std::optional<int64_t>(workerArgConst.value());
359 FailureOr<int64_t> workerArgBound =
362 if (succeeded(workerArgBound))
363 return std::optional<int64_t>(*workerArgBound);
367 "worker-private variables in shared memory "
368 "require compile-time constant num_workers");
371 return std::optional<int64_t>();
380 PrivateLocalOp privateLocal, ComputeRegionOp computeRegion, ModuleOp module,
388 bool isReductionAccumulator =
389 llvm::any_of(privateLocal.getResult().getUsers(), [](
Operation *user) {
390 return isa<ReductionAccumulateOp>(user);
396 llvm::any_of(parDims, [&](
auto parDim) {
return policy.
isGang(parDim); });
397 bool isWorkerPrivate = llvm::any_of(
398 parDims, [&](
auto parDim) {
return policy.
isWorker(parDim); });
399 bool isVectorPrivate = llvm::any_of(
400 parDims, [&](
auto parDim) {
return policy.
isVector(parDim); });
403 cast<PrivateType>(privateLocal.getPrivatized().getType()).getBaseTy(),
406 bool isBlockLevelPrivate =
409 (isWorkerPrivate && baseTy.getRank() > 0 && !isReductionAccumulator));
410 if (!isBlockLevelPrivate)
413 for (
int64_t dim : baseTy.getShape())
414 if (dim == ShapedType::kDynamic)
417 auto resultMemRefTy = dyn_cast<MemRefType>(privateLocal.getType());
418 if (!resultMemRefTy || !resultMemRefTy.getLayout().isIdentity() ||
419 resultMemRefTy.getMemorySpace())
422 if (isGangPrivate && isWorkerPrivate && !isReductionAccumulator)
425 FailureOr<std::optional<int64_t>> numCopies =
427 isWorkerPrivate, support);
428 if (failed(numCopies))
430 return numCopies->has_value();
434 PrivateLocalOp privateLocal, ComputeRegionOp computeRegion, ModuleOp module,
437 privateLocal, computeRegion, module, policy);
438 if (failed(isCandidate) || !*isCandidate)
443 bool isWorkerPrivate = llvm::any_of(
444 parDims, [&](
auto parDim) {
return policy.
isWorker(parDim); });
446 FailureOr<std::optional<int64_t>> numCopies =
448 privateLocal, computeRegion, isWorkerPrivate,
nullptr);
449 if (failed(numCopies) || !numCopies->has_value())
453 cast<PrivateType>(privateLocal.getPrivatized().getType()).getBaseTy(),
455 std::optional<TypeSizeAndAlignment> elementSizeAndAlignment =
457 if (!elementSizeAndAlignment)
461 for (
int64_t dim : baseTy.getShape())
463 return elementSizeAndAlignment->first.getFixedValue() * numElements *
470 if (
auto mapInfo = dyn_cast<MapInfoOp>(mapEntryOp))
471 return mapInfo.getVarPtrPtr() !=
nullptr;
472 if (isa<AttachOp>(mapEntryOp))
474 if (std::optional<DataClause> clause =
getDataClause(mapEntryOp)) {
475 if (*clause == DataClause::acc_attach || *clause == DataClause::acc_detach)
482 if (
auto mapInfo = dyn_cast<MapInfoOp>(mapEntryOp))
483 return mapInfo.getDescKind();
484 return DataDescKind::none;
488 auto mapInfo = dyn_cast<MapInfoOp>(mapEntryOp);
491 if (
Value desc = mapInfo.getDesc())
495 if (mapInfo.getDescKind() != DataDescKind::none)
496 return mapInfo.getVar();
501 if (
auto mapInfo = dyn_cast<MapInfoOp>(mapEntryOp))
502 if (
auto attr = mapInfo.getElementSizeAttr())
503 return attr.getInt();
508 if (
auto mapInfo = dyn_cast<MapInfoOp>(mapEntryOp))
509 return mapInfo.getSize();
514 if (
auto mapInfo = dyn_cast<MapInfoOp>(mapEntryOp))
515 return mapInfo.getMapFlags();
523 if (!isa<ACC_DATA_EXIT_OPS>(op))
527 [&](
auto exit) { accVar = exit.getAccVar(); });
529 if (accVar == entryResult)
530 exitOps.push_back(op);
537 return exitOps.empty() ?
nullptr : exitOps.front();
542 .Case<ACC_DATA_EXIT_OPS>([&](
auto exit) {
return exit.getDataClause(); })
543 .Default([&](
Operation *) {
return std::nullopt; });
551 Value var = getMappedVar(entryOp);
555 auto copiesOutOnly = [&](
Value sibling) {
556 Operation *siblingOp = sibling.getDefiningOp();
557 if (!siblingOp || getMappedVar(siblingOp) != var)
559 if (std::optional<MapFlags> siblingFlags =
getMapFlags(siblingOp))
560 return bitEnumContainsAny(*siblingFlags, MapFlags::from) &&
561 !bitEnumContainsAny(*siblingFlags, MapFlags::to);
562 std::optional<DataClause> siblingClause =
getDataClause(siblingOp);
563 return siblingClause && (*siblingClause == DataClause::acc_copyout ||
564 *siblingClause == DataClause::acc_copyout_zero);
568 auto mapsSameVarOnConstruct = [&](
auto construct) {
569 return llvm::any_of(construct.getDataClauseOperands(), [&](
Value sibling) {
570 return sibling != entryResult && copiesOutOnly(sibling);
574 return llvm::TypeSwitch<Operation *, bool>(user)
575 .Case<KernelEnvironmentOp, KernelsOp, ParallelOp, SerialOp, DataOp>(
576 mapsSameVarOnConstruct)
584 [&](
auto entry) {
return entry.getModifiers(); })
585 .Default([&](
Operation *) {
return DataClauseModifier::none; });
590 MapFlags flags = MapFlags::private_;
594 GPUParallelDimsAttr parDims = privatizeOp.getParDimsAttr();
598 for (GPUParallelDimAttr parDim : parDims.getArray()) {
599 if (policy.
isGang(parDim))
600 flags = flags | MapFlags::gang_private;
602 flags = flags | MapFlags::worker_private;
604 flags = flags | MapFlags::vector_private;
610 MapFlags flags = MapFlags::none;
611 std::optional<DataClause> enterClause =
getDataClause(entryOp);
615 switch (*enterClause) {
616 case DataClause::acc_create:
617 case DataClause::acc_copyout:
618 case DataClause::acc_present:
619 case DataClause::acc_private:
620 case DataClause::acc_firstprivate:
621 case DataClause::acc_delete:
622 case DataClause::acc_update_host:
623 case DataClause::acc_update_self:
624 case DataClause::acc_declare_device_resident:
625 if (*enterClause == DataClause::acc_declare_device_resident)
626 flags = flags | MapFlags::device_resident;
627 if (*enterClause == DataClause::acc_present)
628 flags = flags | MapFlags::present;
629 if (*enterClause == DataClause::acc_private ||
630 *enterClause == DataClause::acc_firstprivate)
631 flags = flags | MapFlags::private_;
632 if (*enterClause == DataClause::acc_firstprivate)
633 flags = flags | MapFlags::to;
635 case DataClause::acc_deviceptr:
636 flags = flags | MapFlags::devptr;
638 case DataClause::acc_create_zero:
639 case DataClause::acc_copyout_zero:
640 flags = flags | MapFlags::init_zero;
642 case DataClause::acc_copy:
643 case DataClause::acc_copyin:
644 case DataClause::acc_copyin_readonly:
645 case DataClause::acc_reduction:
646 case DataClause::acc_update_device:
647 flags = flags | MapFlags::to;
649 case DataClause::acc_no_create:
650 flags = flags | MapFlags::no_create;
652 case DataClause::acc_attach:
657 if (*enterClause == DataClause::acc_reduction)
658 flags = flags | MapFlags::reduction;
660 std::optional<DataClause> exitClause;
664 switch (*exitClause) {
665 case DataClause::acc_copy:
666 case DataClause::acc_reduction:
667 case DataClause::acc_copyout:
668 case DataClause::acc_copyout_zero:
669 case DataClause::acc_update_host:
670 case DataClause::acc_update_self:
671 flags = flags | MapFlags::from;
673 case DataClause::acc_declare_device_resident:
674 flags = flags | MapFlags::device_resident;
676 case DataClause::acc_present:
677 flags = flags | MapFlags::present;
683 case DataClause::acc_delete:
686 case DataClause::acc_create:
687 case DataClause::acc_create_zero:
688 case DataClause::acc_copyin:
689 case DataClause::acc_copyin_readonly:
691 flags = flags | MapFlags::from;
696 if (*exitClause == DataClause::acc_reduction)
697 flags = flags | MapFlags::reduction;
701 flags = flags | MapFlags::ptr_and_obj;
703 flags = flags | MapFlags::implicit;
705 flags = flags | MapFlags::init_zero;
708 if (
auto exitDataOp = dyn_cast<ExitDataOp>(use.getOwner())) {
709 if (exitDataOp.getFinalize())
710 flags = flags | MapFlags::delete_;
712 if (
auto updateOp = dyn_cast<UpdateOp>(use.getOwner())) {
713 if (updateOp.getIfPresent())
714 flags = flags | MapFlags::if_present;
726 if (!bounds.empty() || descKind != DataDescKind::none)
731 module = def->getParentOfType<ModuleOp>();
734 module = parent->getParentOfType<ModuleOp>();
738 auto tryUtilsSize = [&](
Type ty) -> std::optional<int64_t> {
739 std::optional<TypeSizeAndAlignment> sizeAndAlign =
741 if (!sizeAndAlign || sizeAndAlign->first.isScalable())
743 return static_cast<int64_t>(sizeAndAlign->first.getFixedValue());
745 if (std::optional<int64_t> size = tryUtilsSize(varType))
747 if (std::optional<int64_t> size = tryUtilsSize(var.
getType()))
755 if (
shape.size() != bounds.size())
757 for (
auto [boundValue, extent] : llvm::zip_equal(bounds,
shape)) {
758 auto bound = boundValue.getDefiningOp<DataBoundsOp>();
759 if (!bound || bound.getSourceExtent() || extent < 0)
765 bound.getSourceExtentMutable().assign(sourceExtent);
#define ACC_OP_WITH_PAR_DIMS_LIST
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)
OpListType & getOperations()
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
The main mechanism for performing data layout queries.
A symbol reference with a reference path containing a single element.
This is a utility class for mapping one set of IR entities to another.
auto lookup(T from) const
Lookup a mapped value within the map.
void map(Value from, Value to)
Inserts a new mapping for 'from' to 'to'.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
RAII guard to reset the insertion point of the builder when destroyed.
This class helps build Operations.
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes={}, ArrayRef< Location > locs={})
Add new block with 'argTypes' arguments and set the insertion point to the end of it.
Operation * clone(Operation &op, IRMapping &mapper)
Creates a deep copy of the specified operation, remapping any operands that use values outside of the...
void setInsertionPointToStart(Block *block)
Sets the insertion point to the start of the specified block.
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
void setInsertionPointToEnd(Block *block)
Sets the insertion point to the end of the specified block.
This class represents an operand of an operation.
This class provides the API for ops that are known to be terminators.
Operation is the basic unit of execution within MLIR.
bool hasDiscardableAttrOfType(NameT &&name)
Attribute getDiscardableAttr(StringRef name)
Access a discardable attribute by name, returns a null Attribute if the discardable attribute does no...
void setDiscardableAttr(StringAttr name, Attribute value)
Set a discardable attribute by name.
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
AttrClass getDiscardableAttrOfType(StringRef name)
Access a discardable attribute by name and cast it to AttrClass.
MLIRContext * getContext()
Return the context this operation is associated with.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
BlockListType & getBlocks()
RetT walk(FnT &&callback)
Walk all nested operations, blocks or regions (including this region), depending on the type of callb...
This class coordinates the application of a rewrite on a set of IR, providing a way for clients to tr...
virtual void eraseOp(Operation *op)
This method erases an operation that is known to have no uses.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
static FailureOr< int64_t > computeConstantBound(presburger::BoundType type, const Variable &var, const StopConditionFn &stopCondition=nullptr, ValueBoundsOptions options={})
Compute a constant bound for the given variable.
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
use_range getUses() const
Returns a range of all uses, which is useful for iterating over all uses.
user_range getUsers() const
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
Region * getParentRegion()
Return the Region in which this Value is defined.
virtual bool isWorker(ParDimAttrT attr) const =0
Check if the attribute represents worker parallelism.
virtual bool isVector(ParDimAttrT attr) const =0
Check if the attribute represents vector parallelism.
virtual bool isGang(ParDimAttrT attr) const =0
Check if the attribute represents gang parallelism (any gang dimension).
InFlightDiagnostic emitNYI(Location loc, const Twine &message)
Report a case that is not yet supported by the implementation.
bool tryAllocate(int64_t bytes, int64_t alignment=kDefaultAlignmentBytes)
Reserve bytes, rounding the current offset up to alignment first.
static int64_t alignOffset(int64_t offset, int64_t alignment=kDefaultAlignmentBytes)
Round offset up to the next multiple of alignment, which must be a power of two.
Specialization of arith.constant op that returns an integer of index type.
static ConstantIndexOp create(OpBuilder &builder, Location location, int64_t value)
#define ACC_DATA_ENTRY_OPS
#define ACC_DATA_EXIT_OPS
MapFlags computePrivatizeMapFlags(PrivatizeOp privatizeOp, const ACCToGPUMappingPolicy &policy)
Compute the private and parallel-level map flags for privatized storage.
SmallVector< Operation * > getPairedDataExitOps(Value entryResult)
Returns the data exit operations paired with the data entry result entryResult, which take it as thei...
GPUParallelDimsAttr getParDimsAttr(Operation *op)
Obtain the parallel dimensions carried by op, if any.
static std::optional< DataClause > getExitDataClause(Operation *exitOp)
std::optional< DataLayout > getDataLayout(Operation *op, bool allowDefault=true)
Get the data layout for an operation.
std::optional< int64_t > getMapElementSize(Operation *mapEntryOp)
Returns element size in bytes from acc.map_info, if present.
MemRefType getPrivateBaseMemRefType(Type baseTy, ModuleOp module)
Returns the ranked MemRef type used to allocate privatized storage.
SmallVector< GPUParallelDimAttr > getReductionCombineParDims(ReductionCombineOp op)
Returns the parallel dimensions that participate in op's combine step.
void setActiveParDimsAttr(Operation *op, ActiveParDimsAttr attr)
Set active parallel dimensions on op.
mlir::Value getVar(mlir::Operation *accDataClauseOp)
Used to obtain the var from a data clause operation.
void insertParDim(llvm::SmallVector< GPUParallelDimAttr > &parDims, GPUParallelDimAttr parDim)
Insert parDim into parDims while preserving dimension ordering.
bool hasActiveParDimsAttr(Operation *op)
Return whether op carries active parallel dimensions.
std::optional< mlir::acc::DataClause > getDataClause(mlir::Operation *accDataEntryOp)
Used to obtain the dataClause from a data entry operation.
bool hasParDimsAttr(Operation *op)
Return whether op carries parallel dimensions.
static Operation * findCorrespondingDataExit(Value entryResult)
MapFlags computeDataClauseMapFlags(Operation *entryOp, bool ptrAndObj)
Fold enter (+ paired exit) data-clause semantics into offload map flags.
bool hasCopyOutSibling(Operation *entryOp)
True when another data clause of the same construct maps the same variable with a copy-back and no co...
Value getMapSize(Operation *mapEntryOp)
Returns the optional size operand from acc.map_info, or null.
ComputeRegionOp buildComputeRegion(Location loc, ValueRange launchArgs, ValueRange inputArgs, llvm::StringRef origin, Region ®ionToClone, RewriterBase &rewriter, IRMapping &mapping, ValueRange output={}, FlatSymbolRefAttr kernelFuncName={}, FlatSymbolRefAttr kernelModuleName={}, Value stream={}, ValueRange inputArgsToMap={})
Build an acc.compute_region operation by cloning a source region.
void setGPUBlockRedundantAttr(Operation *op)
Mark op with the acc.gpu_block_redundant attribute.
static FailureOr< std::optional< int64_t > > getWorkerPrivateSharedMemoryNumCopies(PrivateLocalOp privateLocal, ComputeRegionOp computeRegion, bool isWorkerPrivate, OpenACCSupport *support)
bool isSpecializedAccRoutine(mlir::Operation *op)
Used to check whether this is a specialized accelerator version of acc routine function.
static bool isInsideACCSpecializedRoutine(Operation *op)
FailureOr< bool > isPrivateLocalSharedMemoryCandidate(PrivateLocalOp privateLocal, ComputeRegionOp computeRegion, ModuleOp module, const ACCToGPUMappingPolicy &policy, OpenACCSupport *support=nullptr)
True when privateLocal may be placed in shared memory.
int64_t sumExistingSharedMemoryBytes(Region ®ion)
Sum aligned static_upper_bound_bytes for all acc.gpu_shared_memory in region.
scf::ExecuteRegionOp wrapMultiBlockRegionWithSCFExecuteRegion(Region ®ion, IRMapping &mapping, Location loc, RewriterBase &rewriter)
Wrap a multi-block region in an scf.execute_region.
void updateParDimsAttr(Operation *op, GPUParallelDimsAttr attr)
Update parallel dimensions on op.
DataDescKind getDataDescKind(Operation *mapEntryOp)
Returns descriptor kind from acc.map_info, or none for other ops.
bool getImplicitFlag(mlir::Operation *accDataEntryOp)
Used to find out whether data operation is implicit.
Value getDesc(Operation *mapEntryOp)
Returns descriptor value from acc.map_info.
void populateSourceExtents(ValueRange bounds, ArrayRef< int64_t > shape, OpBuilder &builder)
Record known extents of the source array on bounds that may describe a section.
mlir::Value getVarPtrPtr(mlir::Operation *accDataClauseOp)
Used to obtain the varPtrPtr from a data clause operation.
PrivatizeOp getPrivatizeOp(PrivateLocalOp privateLocal, ComputeRegionOp computeRegion)
Resolve the acc.privatize operation associated with a private local.
bool hasSeqParDims(Operation *op)
Return whether op carries sequential parallel dimensions.
void copyParDimsAttr(Operation *from, Operation *to)
Copy parallel dimensions from from to to.
bool hasGPUBlockRedundantAttr(Operation *op)
Return whether op is marked with the acc.gpu_block_redundant attribute, i.e.
void removeParDim(llvm::SmallVector< GPUParallelDimAttr > &parDims, GPUParallelDimAttr parDim)
Remove parDim from parDims if present.
void setParDimsAttr(Operation *op, GPUParallelDimsAttr attr)
Set parallel dimensions on op.
ActiveParDimsAttr getActiveParDimsAttr(Operation *op)
Obtain the active parallel dimensions carried by op, if any.
std::optional< int64_t > getPrivateLocalSharedMemoryUpperBoundBytes(PrivateLocalOp privateLocal, ComputeRegionOp computeRegion, ModuleOp module, const ACCToGPUMappingPolicy &policy, OpenACCSupport *support=nullptr)
Upper-bound byte size for a shared-memory private_local candidate, or std::nullopt when not eligible ...
static bool isThreadXPrivatize(PrivatizeOp privatize)
std::optional< MapFlags > getMapFlags(Operation *mapEntryOp)
Returns offload map-type flags from acc.map_info, if present.
int64_t computeMapInfoSizeBytes(Value var, Type varType, DataDescKind descKind, ValueRange bounds, const DataLayout &dataLayout, OpenACCSupport *support=nullptr)
Compute total mapped byte size for acc.map_info.
static SmallVector< GPUParallelDimAttr >::iterator findParDim(SmallVector< GPUParallelDimAttr > &parDims, GPUParallelDimAttr parDim)
mlir::TypedValue< mlir::acc::PointerLikeType > getVarPtr(mlir::Operation *accDataClauseOp)
Used to obtain the var from a data clause operation if it implements PointerLikeType.
SmallVector< GPUParallelDimAttr > collectPrivateLocalParDims(PrivateLocalOp privateLocal, ComputeRegionOp computeRegion)
Collect parallel dimensions that govern privatization of privateLocal.
bool hasAttachPoint(Operation *mapEntryOp)
Returns true when mapEntryOp carries an attach point (varPtrPtr).
ACCParMappingPolicy< mlir::acc::GPUParallelDimAttr > ACCToGPUMappingPolicy
Type alias for the GPU-specific mapping policy.
static DataClauseModifier getEntryModifiers(Operation *entryOp)
std::optional< TypeSizeAndAlignment > getTypeSizeAndAlignment(Type ty, ModuleOp module, const DataLayout &dl, OpenACCSupport *support=nullptr, Value var={})
Returns the size and ABI alignment in bytes.
Include the generated interface declarations.