MLIR 24.0.0git
OpenACCUtilsCG.h
Go to the documentation of this file.
1//===- OpenACCUtilsCG.h - OpenACC Code Generation Utilities -----*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines utility functions for OpenACC code generation, including
10// data layout and type-related utilities.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef MLIR_DIALECT_OPENACC_OPENACCUTILSCG_H_
15#define MLIR_DIALECT_OPENACC_OPENACCUTILSCG_H_
16
19#include "mlir/IR/Builders.h"
20#include "mlir/IR/IRMapping.h"
21#include "mlir/IR/Value.h"
24#include "llvm/ADT/SmallVector.h"
25#include <optional>
26
27namespace mlir {
28namespace acc {
29
30class OpenACCSupport;
31
32/// Get the data layout for an operation.
33///
34/// Attempts to get the data layout from the operation or its parent module.
35/// If `allowDefault` is true (default), a default data layout may be
36/// constructed when no explicit data layout spec is found.
37///
38/// \param op The operation to get the data layout for.
39/// \param allowDefault If true, allow returning a default data layout.
40/// \return The data layout if available, std::nullopt otherwise.
41std::optional<DataLayout> getDataLayout(Operation *op,
42 bool allowDefault = true);
43
44/// Build an `acc.compute_region` operation by cloning a source region.
45///
46/// Creates a new `acc.compute_region` with the given launch arguments and
47/// origin string, then clones the operations from `regionToClone` into its
48/// body. Launch operands should be `acc.par_width` results (`index`); the
49/// region entry block gets matching `index` block arguments first, then
50/// arguments for each `ins` operand. Multi-block regions are wrapped with
51/// `scf.execute_region`.
52///
53/// The `mapping` is used and updated during cloning, allowing callers to
54/// track value correspondences. Optional `output`, `kernelFuncName`,
55/// `kernelModuleName`, and `stream` arguments are forwarded to the op.
56///
57/// When `inputArgsToMap` is non-empty, it is used as the key set for the
58/// clone mapping (instead of `inputArgs`). Use this when cloning a region
59/// that references one set of values (e.g. the source function's args) while
60/// the op's operands are another set (e.g. the current block's args).
61/// `inputArgsToMap` must have the same size as `inputArgs` when provided.
62ComputeRegionOp buildComputeRegion(Location loc, ValueRange launchArgs,
63 ValueRange inputArgs, llvm::StringRef origin,
64 Region &regionToClone,
65 RewriterBase &rewriter, IRMapping &mapping,
66 ValueRange output = {},
67 FlatSymbolRefAttr kernelFuncName = {},
68 FlatSymbolRefAttr kernelModuleName = {},
69 Value stream = {},
70 ValueRange inputArgsToMap = {});
71
72/// Insert \p parDim into \p parDims while preserving dimension ordering. If the
73/// dimension is already present, this is a no-op.
74void insertParDim(llvm::SmallVector<GPUParallelDimAttr> &parDims,
75 GPUParallelDimAttr parDim);
76
77/// Remove \p parDim from \p parDims if present.
78void removeParDim(llvm::SmallVector<GPUParallelDimAttr> &parDims,
79 GPUParallelDimAttr parDim);
80
81/// Obtain the parallel dimensions carried by \p op, if any.
82GPUParallelDimsAttr getParDimsAttr(Operation *op);
83
84/// Return whether \p op carries parallel dimensions.
85bool hasParDimsAttr(Operation *op);
86
87/// Return whether \p op carries sequential parallel dimensions.
88bool hasSeqParDims(Operation *op);
89
90/// Set parallel dimensions on \p op.
91void setParDimsAttr(Operation *op, GPUParallelDimsAttr attr);
92
93/// Update parallel dimensions on \p op.
94void updateParDimsAttr(Operation *op, GPUParallelDimsAttr attr);
95
96/// Copy parallel dimensions from \p from to \p to.
97void copyParDimsAttr(Operation *from, Operation *to);
98
99/// Obtain the active parallel dimensions carried by \p op, if any.
100ActiveParDimsAttr getActiveParDimsAttr(Operation *op);
101
102/// Return whether \p op carries active parallel dimensions.
103bool hasActiveParDimsAttr(Operation *op);
104
105/// Set active parallel dimensions on \p op.
106void setActiveParDimsAttr(Operation *op, ActiveParDimsAttr attr);
107
108/// Set active parallel dimensions on \p op from a dimension list.
109void setActiveParDimsAttr(Operation *op, ArrayRef<GPUParallelDimAttr> dims);
110
111/// Return whether \p op is marked with the `acc.gpu_block_redundant` attribute,
112/// i.e. it executes redundantly across all thread blocks. Such an op must not
113/// be assigned block/grid-level work-sharing; only thread-level parallelism may
114/// apply, and its enclosing block dimensions are treated as active (not
115/// predicated).
116bool hasGPUBlockRedundantAttr(Operation *op);
117
118/// Mark \p op with the `acc.gpu_block_redundant` attribute.
119void setGPUBlockRedundantAttr(Operation *op);
120
121/// Create a gang dim 1 GPUParallelDimsAttr based on the mapping policy.
122inline GPUParallelDimsAttr
124 return GPUParallelDimsAttr::get(
125 ctx, {policy.gangDim(ctx, acc::ParLevel::gang_dim1)});
126}
127
128/// Create a sequential GPUParallelDimsAttr based on the mapping policy.
129inline GPUParallelDimsAttr getSeqParDimsAttr(MLIRContext *ctx,
130 ACCToGPUMappingPolicy &policy) {
131 return GPUParallelDimsAttr::get(ctx, {policy.seqDim(ctx)});
132}
133
134/// Tracks aligned byte consumption against a configurable shared memory cap.
136public:
137 /// Default allocation alignment (bytes).
138 static constexpr int64_t kDefaultAlignmentBytes = 16;
139
141 : bytesUsed_(initialBytesUsed), maxTotalBytes_(maxTotalBytes) {}
142
143 /// Reserve \p bytes, rounding the current offset up to \p alignment first.
144 /// Returns false without mutating state if the reservation would exceed the
145 /// cap. \p alignment must be a power of two.
146 bool tryAllocate(int64_t bytes, int64_t alignment = kDefaultAlignmentBytes);
147 int64_t bytesUsed() const { return bytesUsed_; }
148 int64_t maxTotalBytes() const { return maxTotalBytes_; }
150 maxTotalBytes_ = maxTotalBytes;
151 }
152
153 /// Round \p offset up to the next multiple of \p alignment, which must be a
154 /// power of two.
155 static int64_t alignOffset(int64_t offset,
156 int64_t alignment = kDefaultAlignmentBytes);
157
158private:
159 int64_t bytesUsed_ = 0;
160 int64_t maxTotalBytes_ = 0;
161};
162
163/// Sum aligned static_upper_bound_bytes for all acc.gpu_shared_memory in \p
164/// region.
166
167/// Resolve the acc.privatize operation associated with a private local.
168PrivatizeOp getPrivatizeOp(PrivateLocalOp privateLocal,
169 ComputeRegionOp computeRegion);
170
171/// Returns the ranked MemRef type used to allocate privatized storage.
172///
173/// \p baseTy is the `baseTy` parameter of `acc.private_type` (the privatized
174/// variable's type).
175MemRefType getPrivateBaseMemRefType(Type baseTy, ModuleOp module);
176
177/// Collect parallel dimensions that govern privatization of \p privateLocal.
179collectPrivateLocalParDims(PrivateLocalOp privateLocal,
180 ComputeRegionOp computeRegion);
181
182/// True when \p privateLocal may be placed in shared memory.
184 PrivateLocalOp privateLocal, ComputeRegionOp computeRegion, ModuleOp module,
185 const ACCToGPUMappingPolicy &policy, OpenACCSupport *support = nullptr);
186
187/// Upper-bound byte size for a shared-memory private_local candidate, or
188/// std::nullopt when not eligible or not statically computable.
189std::optional<int64_t> getPrivateLocalSharedMemoryUpperBoundBytes(
190 PrivateLocalOp privateLocal, ComputeRegionOp computeRegion, ModuleOp module,
191 const ACCToGPUMappingPolicy &policy, OpenACCSupport *support = nullptr);
192
193/// Returns true when `mapEntryOp` carries an attach point (`varPtrPtr`).
194bool hasAttachPoint(Operation *mapEntryOp);
195
196/// Returns descriptor kind from `acc.map_info`, or `none` for other ops.
197DataDescKind getDataDescKind(Operation *mapEntryOp);
198
199/// Returns descriptor value from `acc.map_info`. When `desc` is omitted and
200/// `descKind` is not `none`, returns `var` (the mapped object is the
201/// descriptor). Returns null for other ops.
202Value getDesc(Operation *mapEntryOp);
203
204/// Returns element size in bytes from `acc.map_info`, if present.
205std::optional<int64_t> getMapElementSize(Operation *mapEntryOp);
206
207/// Returns the optional `size` operand from `acc.map_info`, or null.
208Value getMapSize(Operation *mapEntryOp);
209
210/// Returns offload map-type flags from `acc.map_info`, if present.
211std::optional<MapFlags> getMapFlags(Operation *mapEntryOp);
212
213/// Compute the private and parallel-level map flags for privatized storage.
214/// Storage that names no parallel dimension is private without being
215/// replicated per level, so only the private flag is set.
216MapFlags computePrivatizeMapFlags(PrivatizeOp privatizeOp,
217 const ACCToGPUMappingPolicy &policy);
218
219/// Fold enter (+ paired exit) data-clause semantics into offload map flags.
220/// `ptrAndObj` is supplied by the caller from type-specific attach discovery.
221MapFlags computeDataClauseMapFlags(Operation *entryOp, bool ptrAndObj);
222
223/// True when another data clause of the same construct maps the same variable
224/// with a copy-back and no copy-in. One entry operation is emitted per clause,
225/// so a construct such as `create(a) copyout(a)` or `copyin(a) copyout(a)` maps
226/// `a` twice. The runtime keeps one mapping per variable and acts on it once,
227/// which makes the copy-back depend on whichever entry it processes: the entry
228/// that has no copy-back of its own must therefore carry `from` as well.
229bool hasCopyOutSibling(Operation *entryOp);
230
231/// Returns the data exit operations paired with the data entry result
232/// \p entryResult, which take it as their `accVar`.
234
235/// Compute total mapped byte size for `acc.map_info`.
236/// Returns 0 when bounds or a non-`none` descriptor kind carry size, the
237/// mappable size when statically known, and -1 when the size cannot be
238/// determined statically. \p support sizes the members of aggregate types that
239/// belong to a dialect, such as a tuple holding dialect-specific references.
240int64_t computeMapInfoSizeBytes(Value var, Type varType, DataDescKind descKind,
241 ValueRange bounds, const DataLayout &dataLayout,
242 OpenACCSupport *support = nullptr);
243
244/// Record known extents of the source array on bounds that may describe a
245/// section. Dynamic / unknown extents are left unset.
247 OpBuilder &builder);
248
249} // namespace acc
250} // namespace mlir
251
252#endif // MLIR_DIALECT_OPENACC_OPENACCUTILSCG_H_
The main mechanism for performing data layout queries.
MLIRContext is the top-level object for a collection of MLIR operations.
Definition MLIRContext.h:63
This class helps build Operations.
Definition Builders.h:210
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition Region.h:26
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
This class provides an abstraction over the different types of ranges over Values.
Definition ValueRange.h:389
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
ParDimAttrT seqDim(MLIRContext *ctx) const
ParDimAttrT gangDim(MLIRContext *ctx, ParLevel level) const
Convenience methods for specific parallelism levels.
SharedMemoryBudget(int64_t maxTotalBytes, int64_t initialBytesUsed=0)
bool tryAllocate(int64_t bytes, int64_t alignment=kDefaultAlignmentBytes)
Reserve bytes, rounding the current offset up to alignment first.
static constexpr int64_t kDefaultAlignmentBytes
Default allocation alignment (bytes).
void setMaxTotalBytes(int64_t maxTotalBytes)
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.
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.
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.
void setActiveParDimsAttr(Operation *op, ActiveParDimsAttr attr)
Set active parallel dimensions on op.
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.
bool hasParDimsAttr(Operation *op)
Return whether op carries parallel dimensions.
MapFlags computeDataClauseMapFlags(Operation *entryOp, bool ptrAndObj)
Fold enter (+ paired exit) data-clause semantics into offload map flags.
GPUParallelDimsAttr getGangDim1ParDimsAttr(MLIRContext *ctx, ACCToGPUMappingPolicy &policy)
Create a gang dim 1 GPUParallelDimsAttr based on the mapping policy.
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 &regionToClone, 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.
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 &region)
Sum aligned static_upper_bound_bytes for all acc.gpu_shared_memory in region.
GPUParallelDimsAttr getSeqParDimsAttr(MLIRContext *ctx, ACCToGPUMappingPolicy &policy)
Create a sequential GPUParallelDimsAttr based on the mapping policy.
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.
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.
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 ...
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.
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.
Include the generated interface declarations.