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/// Obtain the `acc.chunk_size` attribute carried by \p op, if any.
122ChunkSizeAttr getChunkSizeAttr(Operation *op);
123
124/// Return whether \p op carries an `acc.chunk_size` attribute.
125bool hasChunkSizeAttr(Operation *op);
126
127/// Set the `acc.chunk_size` attribute on \p op.
128void setChunkSizeAttr(Operation *op, ChunkSizeAttr attr);
129
130/// Set the `acc.chunk_size` attribute on \p op from a constant size.
131void setChunkSizeAttr(Operation *op, int64_t chunkSize);
132
133/// Return the chunk size carried by \p op, if any.
134std::optional<int64_t> getChunkSize(Operation *op);
135
136/// Create a gang dim 1 GPUParallelDimsAttr based on the mapping policy.
137inline GPUParallelDimsAttr
139 return GPUParallelDimsAttr::get(
140 ctx, {policy.gangDim(ctx, acc::ParLevel::gang_dim1)});
141}
142
143/// Create a sequential GPUParallelDimsAttr based on the mapping policy.
144inline GPUParallelDimsAttr getSeqParDimsAttr(MLIRContext *ctx,
145 ACCToGPUMappingPolicy &policy) {
146 return GPUParallelDimsAttr::get(ctx, {policy.seqDim(ctx)});
147}
148
149/// Tracks aligned byte consumption against a configurable shared memory cap.
151public:
152 /// Default allocation alignment (bytes).
153 static constexpr int64_t kDefaultAlignmentBytes = 16;
154
156 : bytesUsed_(initialBytesUsed), maxTotalBytes_(maxTotalBytes) {}
157
158 /// Reserve \p bytes, rounding the current offset up to \p alignment first.
159 /// Returns false without mutating state if the reservation would exceed the
160 /// cap. \p alignment must be a power of two.
161 bool tryAllocate(int64_t bytes, int64_t alignment = kDefaultAlignmentBytes);
162 int64_t bytesUsed() const { return bytesUsed_; }
163 int64_t maxTotalBytes() const { return maxTotalBytes_; }
165 maxTotalBytes_ = maxTotalBytes;
166 }
167
168 /// Round \p offset up to the next multiple of \p alignment, which must be a
169 /// power of two.
170 static int64_t alignOffset(int64_t offset,
171 int64_t alignment = kDefaultAlignmentBytes);
172
173private:
174 int64_t bytesUsed_ = 0;
175 int64_t maxTotalBytes_ = 0;
176};
177
178/// Sum aligned static_upper_bound_bytes for all acc.gpu_shared_memory in \p
179/// region.
181
182/// Resolve the acc.privatize operation associated with a private local.
183PrivatizeOp getPrivatizeOp(PrivateLocalOp privateLocal,
184 ComputeRegionOp computeRegion);
185
186/// Returns the ranked MemRef type used to allocate privatized storage.
187///
188/// \p baseTy is the `baseTy` parameter of `acc.private_type` (the privatized
189/// variable's type).
190MemRefType getPrivateBaseMemRefType(Type baseTy, ModuleOp module);
191
192/// Collect parallel dimensions that govern privatization of \p privateLocal.
194collectPrivateLocalParDims(PrivateLocalOp privateLocal,
195 ComputeRegionOp computeRegion);
196
197/// True when \p privateLocal may be placed in shared memory.
199 PrivateLocalOp privateLocal, ComputeRegionOp computeRegion, ModuleOp module,
200 const ACCToGPUMappingPolicy &policy, OpenACCSupport *support = nullptr);
201
202/// Upper-bound byte size for a shared-memory private_local candidate, or
203/// std::nullopt when not eligible or not statically computable.
204std::optional<int64_t> getPrivateLocalSharedMemoryUpperBoundBytes(
205 PrivateLocalOp privateLocal, ComputeRegionOp computeRegion, ModuleOp module,
206 const ACCToGPUMappingPolicy &policy, OpenACCSupport *support = nullptr);
207
208/// Returns true when `mapEntryOp` carries an attach point (`varPtrPtr`).
209bool hasAttachPoint(Operation *mapEntryOp);
210
211/// Returns descriptor kind from `acc.map_info`, or `none` for other ops.
212DataDescKind getDataDescKind(Operation *mapEntryOp);
213
214/// Returns descriptor value from `acc.map_info`. When `desc` is omitted and
215/// `descKind` is not `none`, returns `var` (the mapped object is the
216/// descriptor). Returns null for other ops.
217Value getDesc(Operation *mapEntryOp);
218
219/// Returns element size in bytes from `acc.map_info`, if present.
220std::optional<int64_t> getMapElementSize(Operation *mapEntryOp);
221
222/// Returns the optional `size` operand from `acc.map_info`, or null.
223Value getMapSize(Operation *mapEntryOp);
224
225/// Returns offload map-type flags from `acc.map_info`, if present.
226std::optional<MapFlags> getMapFlags(Operation *mapEntryOp);
227
228/// Compute the private and parallel-level map flags for privatized storage.
229/// Storage that names no parallel dimension is private without being
230/// replicated per level, so only the private flag is set.
231MapFlags computePrivatizeMapFlags(PrivatizeOp privatizeOp,
232 const ACCToGPUMappingPolicy &policy);
233
234/// Fold enter (+ paired exit) data-clause semantics into offload map flags.
235/// `ptrAndObj` is supplied by the caller from type-specific attach discovery.
236MapFlags computeDataClauseMapFlags(Operation *entryOp, bool ptrAndObj);
237
238/// True when another data clause of the same construct maps the same variable
239/// with a copy-back and no copy-in. One entry operation is emitted per clause,
240/// so a construct such as `create(a) copyout(a)` or `copyin(a) copyout(a)` maps
241/// `a` twice. The runtime keeps one mapping per variable and acts on it once,
242/// which makes the copy-back depend on whichever entry it processes: the entry
243/// that has no copy-back of its own must therefore carry `from` as well.
244bool hasCopyOutSibling(Operation *entryOp);
245
246/// Returns the data exit operations paired with the data entry result
247/// \p entryResult, which take it as their `accVar`.
249
250/// Returns where the mappings of \p dataClauseOperands end, taken from the
251/// first of them that says. This is where a structured construct tears its
252/// mappings down, which is past the end of its region and therefore not a
253/// position the construct itself carries. A mapping that is never closed has
254/// none.
255std::optional<Location> getMappingExitLoc(ValueRange dataClauseOperands);
256
257/// Compute total mapped byte size for `acc.map_info`.
258/// Returns 0 when bounds or a non-`none` descriptor kind carry size, the
259/// mappable size when statically known, and -1 when the size cannot be
260/// determined statically. \p support sizes the members of aggregate types that
261/// belong to a dialect, such as a tuple holding dialect-specific references.
262int64_t computeMapInfoSizeBytes(Value var, Type varType, DataDescKind descKind,
263 ValueRange bounds, const DataLayout &dataLayout,
264 OpenACCSupport *support = nullptr);
265
266/// Same as above, obtaining \p dataLayout from the module \p var lives in.
267int64_t computeMapInfoSizeBytes(Value var, Type varType, DataDescKind descKind,
268 ValueRange bounds,
269 OpenACCSupport *support = nullptr);
270
271/// Record known extents of the source array on bounds that may describe a
272/// section. Dynamic / unknown extents are left unset.
274 OpBuilder &builder);
275
276} // namespace acc
277} // namespace mlir
278
279#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...
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.
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.
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.
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.
ChunkSizeAttr getChunkSizeAttr(Operation *op)
Obtain the acc.chunk_size attribute carried by op, if any.
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.
void setChunkSizeAttr(Operation *op, ChunkSizeAttr attr)
Set the acc.chunk_size attribute on 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 &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.