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()));
242 return attr.getChunkSize();
248 "expected parallel dimensions attribute to already be set");
254 ActiveParDimsAttr::name);
270 assert(alignment > 0 && llvm::isPowerOf2_64(alignment) &&
271 "alignment must be a power of two");
272 return (offset + alignment - 1) & ~(alignment - 1);
277 if (aligned + bytes > maxTotalBytes_) {
280 bytesUsed_ = aligned + bytes;
286 region.
walk([&](GPUSharedMemoryOp op) {
287 int64_t upperBound = op.getStaticUpperBoundBytes();
294 ComputeRegionOp computeRegion) {
295 Value value = privateLocal.getPrivatized();
296 if (
BlockArgument blockArg = dyn_cast<BlockArgument>(value)) {
297 auto owner = dyn_cast<ComputeRegionOp>(blockArg.getOwner()->getParentOp());
298 value = (owner ? owner : computeRegion).getOperand(blockArg);
300 PrivatizeOp privatizeOp = value.
getDefiningOp<PrivatizeOp>();
301 assert(privatizeOp &&
"expected privatize op to be the defining op");
306 if (GPUParallelDimsAttr parDimsAttr = privatize.getParDimsAttr())
307 return llvm::any_of(parDimsAttr.getArray(),
308 [](GPUParallelDimAttr d) { return d.isThreadX(); });
313 auto memrefTy = cast<PointerLikeType>(baseTy).getAsMemRefType(module);
314 assert(memrefTy &&
"private base type must be convertible to memref");
320 ComputeRegionOp computeRegion) {
325 auto parentLoop = privateLocal->getParentOfType<scf::ParallelOp>();
326 while (parentLoop && computeRegion->isProperAncestor(parentLoop)) {
328 for (GPUParallelDimAttr parDim : parDimsAttr.getArray())
330 parentLoop = parentLoop->getParentOfType<scf::ParallelOp>();
332 if (GPUParallelDimsAttr parDimsAttr =
getParDimsAttr(computeRegion))
333 for (GPUParallelDimAttr parDim : parDimsAttr.getArray())
335 if (parDims.empty()) {
336 for (GPUParallelDimAttr parDim : computeRegion.getLaunchParDims()) {
337 if (parDim.isAnyBlock())
343 if (
auto accumulateOp = dyn_cast<ReductionAccumulateOp>(user)) {
344 if (accumulateOp.getMemref() == privateLocal.getResult())
345 for (GPUParallelDimAttr parDim : accumulateOp.getParDims().getArray())
348 if (
auto combineOp = dyn_cast<ReductionCombineOp>(user)) {
349 if (combineOp.getSrcMemref() == privateLocal.getResult())
353 if (
auto combineRegionOp = dyn_cast<ReductionCombineRegionOp>(user)) {
354 if (combineRegionOp.getSrcVar() == privateLocal.getResult())
355 for (GPUParallelDimAttr parDim :
364 PrivateLocalOp privateLocal, ComputeRegionOp computeRegion,
366 if (!isWorkerPrivate)
367 return std::optional<int64_t>(1);
369 GPUParallelDimAttr threadY =
370 GPUParallelDimAttr::threadYDim(privateLocal.getContext());
371 std::optional<Value> workerArg = computeRegion.getKnownLaunchArg(threadY);
373 return std::optional<int64_t>();
377 return std::optional<int64_t>(workerArgConst.value());
379 FailureOr<int64_t> workerArgBound =
382 if (succeeded(workerArgBound))
383 return std::optional<int64_t>(*workerArgBound);
387 "worker-private variables in shared memory "
388 "require compile-time constant num_workers");
391 return std::optional<int64_t>();
400 PrivateLocalOp privateLocal, ComputeRegionOp computeRegion, ModuleOp module,
408 bool isReductionAccumulator =
409 llvm::any_of(privateLocal.getResult().getUsers(), [](
Operation *user) {
410 return isa<ReductionAccumulateOp>(user);
416 llvm::any_of(parDims, [&](
auto parDim) {
return policy.
isGang(parDim); });
417 bool isWorkerPrivate = llvm::any_of(
418 parDims, [&](
auto parDim) {
return policy.
isWorker(parDim); });
419 bool isVectorPrivate = llvm::any_of(
420 parDims, [&](
auto parDim) {
return policy.
isVector(parDim); });
423 cast<PrivateType>(privateLocal.getPrivatized().getType()).getBaseTy(),
426 bool isBlockLevelPrivate =
429 (isWorkerPrivate && baseTy.getRank() > 0 && !isReductionAccumulator));
430 if (!isBlockLevelPrivate)
433 for (
int64_t dim : baseTy.getShape())
434 if (dim == ShapedType::kDynamic)
437 auto resultMemRefTy = dyn_cast<MemRefType>(privateLocal.getType());
438 if (!resultMemRefTy || !resultMemRefTy.getLayout().isIdentity() ||
439 resultMemRefTy.getMemorySpace())
442 if (isGangPrivate && isWorkerPrivate && !isReductionAccumulator)
445 FailureOr<std::optional<int64_t>> numCopies =
447 isWorkerPrivate, support);
448 if (failed(numCopies))
450 return numCopies->has_value();
454 PrivateLocalOp privateLocal, ComputeRegionOp computeRegion, ModuleOp module,
457 privateLocal, computeRegion, module, policy);
458 if (failed(isCandidate) || !*isCandidate)
463 bool isWorkerPrivate = llvm::any_of(
464 parDims, [&](
auto parDim) {
return policy.
isWorker(parDim); });
466 FailureOr<std::optional<int64_t>> numCopies =
468 privateLocal, computeRegion, isWorkerPrivate,
nullptr);
469 if (failed(numCopies) || !numCopies->has_value())
473 cast<PrivateType>(privateLocal.getPrivatized().getType()).getBaseTy(),
475 std::optional<TypeSizeAndAlignment> elementSizeAndAlignment =
477 if (!elementSizeAndAlignment)
481 for (
int64_t dim : baseTy.getShape())
483 return elementSizeAndAlignment->first.getFixedValue() * numElements *
490 if (
auto mapInfo = dyn_cast<MapInfoOp>(mapEntryOp))
491 return mapInfo.getVarPtrPtr() !=
nullptr;
492 if (isa<AttachOp>(mapEntryOp))
494 if (std::optional<DataClause> clause =
getDataClause(mapEntryOp)) {
495 if (*clause == DataClause::acc_attach || *clause == DataClause::acc_detach)
502 if (
auto mapInfo = dyn_cast<MapInfoOp>(mapEntryOp))
503 return mapInfo.getDescKind();
504 return DataDescKind::none;
508 auto mapInfo = dyn_cast<MapInfoOp>(mapEntryOp);
511 if (
Value desc = mapInfo.getDesc())
515 if (mapInfo.getDescKind() != DataDescKind::none)
516 return mapInfo.getVar();
521 if (
auto mapInfo = dyn_cast<MapInfoOp>(mapEntryOp))
522 if (
auto attr = mapInfo.getElementSizeAttr())
523 return attr.getInt();
528 if (
auto mapInfo = dyn_cast<MapInfoOp>(mapEntryOp))
529 return mapInfo.getSize();
534 if (
auto mapInfo = dyn_cast<MapInfoOp>(mapEntryOp))
535 return mapInfo.getMapFlags();
543 if (!isa<ACC_DATA_EXIT_OPS>(op))
547 [&](
auto exit) { accVar = exit.getAccVar(); });
549 if (accVar == entryResult)
550 exitOps.push_back(op);
557 return exitOps.empty() ?
nullptr : exitOps.front();
562 if (std::optional<Location> exitLoc = mapInfo.getExitLoc())
565 return exitOp->getLoc();
570 for (
Value operand : dataClauseOperands)
578 .Case<ACC_DATA_EXIT_OPS>([&](
auto exit) {
return exit.getDataClause(); })
579 .Default([&](
Operation *) {
return std::nullopt; });
587 Value var = getMappedVar(entryOp);
591 auto copiesOutOnly = [&](
Value sibling) {
592 Operation *siblingOp = sibling.getDefiningOp();
593 if (!siblingOp || getMappedVar(siblingOp) != var)
595 if (std::optional<MapFlags> siblingFlags =
getMapFlags(siblingOp))
596 return bitEnumContainsAny(*siblingFlags, MapFlags::from) &&
597 !bitEnumContainsAny(*siblingFlags, MapFlags::to);
598 std::optional<DataClause> siblingClause =
getDataClause(siblingOp);
599 return siblingClause && (*siblingClause == DataClause::acc_copyout ||
600 *siblingClause == DataClause::acc_copyout_zero);
604 auto mapsSameVarOnConstruct = [&](
auto construct) {
605 return llvm::any_of(construct.getDataClauseOperands(), [&](
Value sibling) {
606 return sibling != entryResult && copiesOutOnly(sibling);
610 return llvm::TypeSwitch<Operation *, bool>(user)
611 .Case<KernelEnvironmentOp, KernelsOp, ParallelOp, SerialOp, DataOp>(
612 mapsSameVarOnConstruct)
620 [&](
auto entry) {
return entry.getModifiers(); })
621 .Default([&](
Operation *) {
return DataClauseModifier::none; });
626 MapFlags flags = MapFlags::private_;
630 GPUParallelDimsAttr parDims = privatizeOp.getParDimsAttr();
634 for (GPUParallelDimAttr parDim : parDims.getArray()) {
635 if (policy.
isGang(parDim))
636 flags = flags | MapFlags::gang_private;
638 flags = flags | MapFlags::worker_private;
640 flags = flags | MapFlags::vector_private;
646 MapFlags flags = MapFlags::none;
647 std::optional<DataClause> enterClause =
getDataClause(entryOp);
651 switch (*enterClause) {
652 case DataClause::acc_create:
653 case DataClause::acc_copyout:
654 case DataClause::acc_present:
655 case DataClause::acc_private:
656 case DataClause::acc_firstprivate:
657 case DataClause::acc_delete:
658 case DataClause::acc_update_host:
659 case DataClause::acc_update_self:
660 case DataClause::acc_declare_device_resident:
661 if (*enterClause == DataClause::acc_declare_device_resident)
662 flags = flags | MapFlags::device_resident;
663 if (*enterClause == DataClause::acc_present)
664 flags = flags | MapFlags::present;
665 if (*enterClause == DataClause::acc_private ||
666 *enterClause == DataClause::acc_firstprivate)
667 flags = flags | MapFlags::private_;
668 if (*enterClause == DataClause::acc_firstprivate)
669 flags = flags | MapFlags::to;
671 case DataClause::acc_deviceptr:
672 flags = flags | MapFlags::devptr;
674 case DataClause::acc_create_zero:
675 case DataClause::acc_copyout_zero:
676 flags = flags | MapFlags::init_zero;
678 case DataClause::acc_copy:
679 case DataClause::acc_copyin:
680 case DataClause::acc_copyin_readonly:
681 case DataClause::acc_reduction:
682 case DataClause::acc_update_device:
683 flags = flags | MapFlags::to;
685 case DataClause::acc_no_create:
686 flags = flags | MapFlags::no_create;
688 case DataClause::acc_attach:
689 flags = flags | MapFlags::attach;
691 case DataClause::acc_detach:
692 flags = flags | MapFlags::detach;
697 if (*enterClause == DataClause::acc_reduction)
698 flags = flags | MapFlags::reduction;
700 std::optional<DataClause> exitClause;
704 switch (*exitClause) {
705 case DataClause::acc_copy:
706 case DataClause::acc_reduction:
707 case DataClause::acc_copyout:
708 case DataClause::acc_copyout_zero:
709 case DataClause::acc_update_host:
710 case DataClause::acc_update_self:
711 flags = flags | MapFlags::from;
713 case DataClause::acc_declare_device_resident:
714 flags = flags | MapFlags::device_resident;
716 case DataClause::acc_present:
717 flags = flags | MapFlags::present;
723 case DataClause::acc_delete:
726 case DataClause::acc_create:
727 case DataClause::acc_create_zero:
728 case DataClause::acc_copyin:
729 case DataClause::acc_copyin_readonly:
731 flags = flags | MapFlags::from;
736 if (*exitClause == DataClause::acc_reduction)
737 flags = flags | MapFlags::reduction;
741 flags = flags | MapFlags::ptr_and_obj;
743 flags = flags | MapFlags::implicit;
745 flags = flags | MapFlags::init_zero;
748 if (
auto exitDataOp = dyn_cast<ExitDataOp>(use.getOwner())) {
749 if (exitDataOp.getFinalize())
750 flags = flags | MapFlags::delete_;
752 if (
auto updateOp = dyn_cast<UpdateOp>(use.getOwner())) {
753 if (updateOp.getIfPresent())
754 flags = flags | MapFlags::if_present;
764 return def->getParentOfType<ModuleOp>();
767 return parent->getParentOfType<ModuleOp>();
776 if (!bounds.empty() || descKind != DataDescKind::none)
783 auto tryUtilsSize = [&](
Type ty) -> std::optional<int64_t> {
784 std::optional<TypeSizeAndAlignment> sizeAndAlign =
786 if (!sizeAndAlign || sizeAndAlign->first.isScalable())
788 return static_cast<int64_t>(sizeAndAlign->first.getFixedValue());
790 if (std::optional<int64_t> size = tryUtilsSize(varType))
792 if (std::optional<int64_t> size = tryUtilsSize(var.
getType()))
803 std::optional<DataLayout> dataLayout =
getDataLayout(module);
812 if (
shape.size() != bounds.size())
814 for (
auto [boundValue, extent] : llvm::zip_equal(bounds,
shape)) {
815 auto bound = boundValue.getDefiningOp<DataBoundsOp>();
816 if (!bound || bound.getSourceExtent() || extent < 0)
822 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...
std::optional< int64_t > getChunkSize(Operation *op)
Return the chunk size carried by op, if any.
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.
std::optional< Location > getMappingExitLoc(ValueRange dataClauseOperands)
Returns where the mappings of dataClauseOperands end, taken from the first of them that says.
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.
ChunkSizeAttr getChunkSizeAttr(Operation *op)
Obtain the acc.chunk_size attribute carried by op, if any.
static ModuleOp getEnclosingModule(Value var)
Returns the module var lives in.
void setGPUBlockRedundantAttr(Operation *op)
Mark op with the acc.gpu_block_redundant attribute.
bool hasChunkSizeAttr(Operation *op)
Return whether op carries an acc.chunk_size attribute.
static FailureOr< std::optional< int64_t > > getWorkerPrivateSharedMemoryNumCopies(PrivateLocalOp privateLocal, ComputeRegionOp computeRegion, bool isWorkerPrivate, OpenACCSupport *support)
void setChunkSizeAttr(Operation *op, ChunkSizeAttr attr)
Set the acc.chunk_size attribute on op.
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.