MLIR 24.0.0git
XeGPUUtils.h
Go to the documentation of this file.
1//===- XeGPUUtils.h - Vector 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#ifndef MLIR_DIALECT_XEGPU_UTILS_XEGPUUTILS_H_
10#define MLIR_DIALECT_XEGPU_UTILS_XEGPUUTILS_H_
11
15#include "llvm/ADT/SetVector.h"
16#include <functional>
17#include <optional>
18
19namespace mlir {
20class UnrealizedConversionCastOp;
21class VectorType;
22class OpOperand;
23class OpResult;
24class OpBuilder;
25class ValueRange;
26class TypeConverter;
27class OpFoldResult;
28
29namespace xegpu {
30class DistributeLayoutAttr;
31class LayoutAttr;
32class TensorDescType;
33
34namespace uArch {
35struct uArch;
36} // namespace uArch
37} // namespace xegpu
38
39namespace xegpu {
40/// Flatten a set of ValueRange into a single SmallVector<Value>
41SmallVector<Value> flattenValues(ArrayRef<ValueRange> values);
42
43/// If tensor descriptor has a layout attribute it is used in SIMT mode.
44/// In this mode, the distributed vector shape is determined as follows:
45/// Definitions:
46/// lane_data_size = lane_data[0] × lane_data[1]
47/// subgroup_size = lane_layout[0] × lane_layout[1]
48/// distribution_unit_size = subgroup_size × lane_data_size
49///
50/// Case 1: Regular loads/stores.
51/// The following conditions must be met:
52/// * tensor_desc[0] == lane_layout[0]
53/// Distributed vector is a 1D vector with shape:
54/// [chunk_size]
55///
56/// Case 2: Block loads/stores
57/// Additional definitions:
58/// tensor_size = tensor_desc[0] * .. * tensor_desc[r-1] * array_length
59/// n_distribution_units = tensor_size / distribution_unit_size
60/// fragment_size = n_distribution_units * lane_data_size
61/// Given above definitions, the following conditions must be met:
62/// * tensor_desc[0] % (lane_layout[0] × lane_data[0]) == 0
63/// * tensor_desc[1] % (lane_layout[1] × lane_data[1]) == 0
64/// Distributed vector is a 1D vector with shape:
65/// [fragment_size]
66FailureOr<VectorType> getDistributedVectorType(xegpu::TensorDescType tdescTy);
67
68/// Helper to get the distributed vector type for a given vector type according
69/// to a given LayoutAttr.
70FailureOr<VectorType> getDistributedVectorType(VectorType originalType,
71 LayoutAttr layout);
72
73/// Helper function to get distributed vector type for a source vector type
74/// according to the lane_layout. We simply divide each dimension of tensor
75/// descriptor shape by corresponding lane_layout dimension. If
76/// array_length > 1, that is appended to the front of the distributed shape.
77///
78/// Examples:
79/// | original vector shape | lane_layout | distributed vector shape |
80/// |-----------------------|-------------|--------------------------|
81/// | 32x16 | [1, 16] | 32x1 |
82/// | 32x16 | [2, 8] | 16x2 |
83/// | 2x32x16 | [1, 16] | 2x32x1 |
84FailureOr<VectorType>
85getDistVecTypeBasedOnLaneLayout(DistributeLayoutAttr layout,
86 VectorType originalType);
87
88/// Extract a set of small vectors from a value with a given shape using
89/// vector.extract_stride_slice
91 Location loc, Value value,
93
94/// Create a vector of shape from a set of values using
95/// vector.insert_stride_slice.
97 ValueRange values,
99
100/// Retrieves the chip string from the XeVM target attribute of the parent
101/// GPU module operation. Returns the chip identifier if found, or nullopt
102/// if no GPU module parent or XeVM target attribute exists.
103std::optional<std::string> getChipStr(Operation *op);
104
105/// Returns the number of subgroups the kernel enclosing `op` runs, derived from
106/// the `known_block_size` of its parent `gpu.func`. Fails when there is no such
107/// parent, when the attribute is absent, when a block dimension is not a
108/// positive power of two, or when the block does not cover a whole subgroup.
109FailureOr<int64_t> getNumSubgroupsFromBlockSize(Operation *op,
110 int64_t subgroupSize);
111
112/// Generates element-wise addition ops of two arrays with same length.
116
117/// Generates element-wise addition ops of two arrays with automatic alignment.
118/// When the input arrays have different sizes, the shorter array is
119/// right-aligned with the longer array, and the unmatched leading elements from
120/// the longer array are preserved unchanged. This is commonly used for offset
121/// computation where higher-dimensional offsets need to be added to
122/// lower-dimensional adjustments.
123///
124/// Example:
125/// lhs = [l1, l2, l3], rhs = [r1, r2]
126/// Result: [11, l2+r1, l3+r2]
130
131/// Given an `input` value representing per-lane data, this function returns the
132/// result after performing a reduction on the input over all lanes (number of
133/// lanes given by `size`). This uses butterfly shuffles to perform the
134/// reduction in a log2(size) number of steps.
135/// NOTE: Implementation taken from TestVectorTransforms.cpp
136Value subgroupReduction(Location loc, OpBuilder &builder, Value input,
137 vector::CombiningKind kind, uint32_t size);
138
139/// Given a `src` and an `acc` argumments from a vector::MultiDimReductionOp,
140/// lower to a set of vector::ReductionOp ops over 1D slices extracted from
141/// `src`. The reduction is performed along `reductionDim`. The result is a
142/// vector with the same shape as `acc`.
143/// TODO: Only 2D to 1D reduction is supported for now.
146 vector::CombiningKind kind, int64_t reductionDim,
147 Location loc, PatternRewriter &rewriter);
148
149/// Creates a constant filled with the neutral (identity) value for the
150/// given reduction kind. For example: 0 for ADD/OR/XOR, 1 for MUL/AND,
151/// max/min signed/unsigned int for MINSI/MINUI/MAXSI/MAXUI, and +/-infinity
152/// for float min/max operations. If \p type is a VectorType, returns a splat
153/// vector constant; otherwise returns a scalar constant. Returns nullptr if
154/// the element type is incompatible with the requested reduction kind.
156 vector::CombiningKind kind);
157
158/// Lowers cross-lane reductions to shuffle operations on a 2D vector.
159/// Extracts slices along the reduction dimension, performs subgroup reductions
160/// with shuffles across reductionSize work-items, and inserts the results back
161/// into an accumulator vector.
164 vector::CombiningKind kind,
165 int64_t reductionDim,
166 int64_t reductionSize, Location loc,
167 PatternRewriter &rewriter);
168
169/// Helper Function to find a proper instruction multiple for the user-supplied
170/// sg-level data shape (diven by `dim`). `candidates` are uArch allowed shapes.
171/// `candidateMultiples` are uArch multiples of such shapes (i.e. block count or
172/// array length).
173template <typename T>
174int getLargestDivisor(T dim, ArrayRef<T> candidates,
175 ArrayRef<T> candidateMultiples = {});
176
177/// Retrieves the DistributeLayoutAttr associated with a given Value, or nullptr
178/// if none is found. For TensorDescType values it is extracted from the
179/// TensorDescType itself; for an op result, from the attributes of the defining
180/// operation.
181///
182/// A block argument carries no attribute of its own, so it is resolved through
183/// the operand that feeds it:
184/// - an iter_arg of a loop, including scf.while's "before" arguments, resolves
185/// through its tied init operand;
186/// - an scf.while "after" argument is fed by scf.condition rather than by an
187/// init operand. Only a pass-through before region is handled: the forwarded
188/// value must be a "before" argument, and the layout comes from that
189/// argument's tied init operand. If the before region forwards anything
190/// computed, nullptr is returned.
191DistributeLayoutAttr getDistributeLayoutAttr(const Value value);
192
193/// Retrieves the DistributeLayoutAttr associated with a given OpOperand. It
194/// will first check the operand_layout_{id} of the owner operation. If not
195/// found, it will check the operand itself and its defining op.
196DistributeLayoutAttr getDistributeLayoutAttr(const OpOperand &opr);
197
198/// [to-be-deprecated] Sets the DistributeLayoutAttr for a given OpResult
199/// user should use setAnchorLayout instead
201 const DistributeLayoutAttr layout);
202
203/// [to-be-deprecated] Sets the DistributeLayoutAttr for a given OpOperand
204/// user should use setAnchorLayout instead
205void setDistributeLayoutAttr(const OpOperand &opr,
206 const DistributeLayoutAttr layout);
207
208/// Return the attribute name for the OpOperand to attach DistributeLayoutAttr
209std::string getTemporaryLayoutName(const OpOperand &operand);
210
211/// Return the attribute name for the OpResult to attach DistributeLayoutAttr
212std::string getTemporaryLayoutName(const OpResult result);
213
214/// get and set distribute layout attribute for non-anchor operations
215/// (and offsets/masks of load/store ops before we get rid of their temp attrs)
216template <typename T,
217 typename = std::enable_if_t<std::is_same_v<T, OpOperand> ||
218 std::is_same_v<T, OpResult>>>
219DistributeLayoutAttr getTemporaryLayout(const T &operandOrResult);
220
221template <typename T,
222 typename = std::enable_if_t<std::is_same_v<T, OpOperand> ||
223 std::is_same_v<T, OpResult>>>
224void setTemporaryLayout(const T &operandOrResult,
225 const DistributeLayoutAttr layout);
226
227/// Returns the innermost 2 entries of `vals` if it is at least 2D and all of
228/// its leading entries are unit; std::nullopt otherwise.
229std::optional<SmallVector<int64_t>>
231
232/// Helper function to check if the layout is packed. Layout is packed if
233/// lane_data[rank-2] != 1 (data packed from col dimension).
234/// TODO: Move to target info.
235bool requirePacked(const DistributeLayoutAttr layout);
236
237/// Helper function to check if the layout requires a transpose effect.
238bool requireTranspose(const DistributeLayoutAttr layout,
239 const uArch::uArch *uArch);
240
241/// Returns true if `type` has a static shape and static strides.
242bool hasStaticShapeAndStrides(MemRefType type);
243
244// Check if dst shape is an expansion of src shape by inserting unit dimensions.
246 SmallVector<int64_t> &expandedUnitDims);
247
248// Checks if dst shape is a non-unit expansion of src shape where each
249// dimension in src is split into one or more consecutive dimensions in dst.
251 SmallVector<SmallVector<int64_t>> &splitDimGroups);
252
253/// Callback type for computing sub-shape and count for 1:N (or 1:1
254/// shape-changing) VectorType conversion. Given a VectorType and its
255/// DistributeLayoutAttr, returns (subShape, count). A count <= 0 signals
256/// "no conversion needed"; count == 1 is a 1:1 shape-changing conversion;
257/// count > 1 produces `count` copies of `subShape`.
258using SubShapeAndCountFn = std::function<std::pair<SmallVector<int64_t>, int>(
259 VectorType, DistributeLayoutAttr)>;
260
261/// Pre-computes distributed VectorType mappings for every value carried
262/// through an SCF loop under `topLevelOp` (1:1 shape-changing or 1:N): the
263/// region block args (`scf.while` before/after args, `scf.for` iter_args), the
264/// loop results, and the terminator operands feeding them. Each is derived from
265/// a single source -- the layout of the feeding value (loop init or
266/// `scf.condition` operand) -- and keyed by `Value`, because the SCF converters
267/// detach/replace the loop body mid-conversion, after which a layout query on a
268/// block arg returns null. Recording results and terminator operands lets a 1:N
269/// pass resolve them from the map after stripping the loop op's transient
270/// layout attrs. `scf.if` has no loop-carried block args and needs no entry.
273 SubShapeAndCountFn getSubShapeAndCount);
274
275/// Adds a context-aware VectorType conversion to `converter` (1:1
276/// shape-changing or 1:N, depending on `getSubShapeAndCount`'s returned
277/// count). `getSubShapeAndCount` computes (subShape, count) for a VectorType
278/// and its layout; count <= 0 means no conversion needed. `loopArgTypes`
279/// (typically obtained from `precomputeLoopBlockArgTypes`) provides the
280/// pre-computed types for SCF loop block arguments (`scf.while`,
281/// `scf.for`); pass an empty map if the IR has no such loops.
283 SubShapeAndCountFn getSubShapeAndCount,
284 DenseMap<Value, SmallVector<Type>> loopArgTypes);
285
286/// Cleans up UnrealizedConversionCastOps inserted during SCF structural type
287/// conversion and/or XeGPU unrolling. Folds cancelling N:1->1:N and 1:N->N:1
288/// cast chains (inserting vector.shape_cast when shapes differ but element
289/// counts match). Unpaired pack (1:N) and unpack (N:1) casts between a single
290/// large VectorType and N identically-typed smaller VectorTypes are lowered
291/// to vector.extract_strided_slice / vector.insert_strided_slice. Dead casts
292/// are erased. Casts in `existingCasts` are preserved.
294 Operation *root,
295 const llvm::SmallSetVector<UnrealizedConversionCastOp, 8> &existingCasts);
296
297// Checks if dst shape is a collapse of src shape where each dimension in dst is
298// produced by one or more consecutive dimensions in src whose product equals
299// the dst dimension. Populates collapseDims with groups of src indices that are
300// collapsed into each dst dimension. Leading or trailing unit dst dimensions
301// (with no backing src dim) result in empty groups. Example: src=[8,16,32],
302// dst=[1,4096] -> true, collapseDims=[[],[0,1,2]].
304 SmallVector<SmallVector<int64_t>> &collapseDims);
305} // namespace xegpu
306} // namespace mlir
307
308#endif // MLIR_DIALECT_XEGPU_UTILS_XEGPUUTILS_H_
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition Location.h:76
This class helps build Operations.
Definition Builders.h:210
This class represents a single result from folding an operation.
This class represents an operand of an operation.
Definition Value.h:254
This is a value defined by a result of an operation.
Definition Value.h:454
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
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
bool matchDimCollapse(ArrayRef< int64_t > src, ArrayRef< int64_t > dst, SmallVector< SmallVector< int64_t > > &collapseDims)
Value createVectorWithShapeFromValues(OpBuilder &builder, Location loc, ValueRange values, ArrayRef< int64_t > shape)
Create a vector of shape from a set of values using vector.insert_stride_slice.
bool requirePacked(const DistributeLayoutAttr layout)
Helper function to check if the layout is packed.
void setTemporaryLayout(const T &operandOrResult, const DistributeLayoutAttr layout)
Value createReductionNeutralValue(OpBuilder &builder, Location loc, Type type, vector::CombiningKind kind)
Creates a constant filled with the neutral (identity) value for the given reduction kind.
void setDistributeLayoutAttr(const OpResult &Result, const DistributeLayoutAttr layout)
[to-be-deprecated] Sets the DistributeLayoutAttr for a given OpResult user should use setAnchorLayout...
Value subgroupReduction(Location loc, OpBuilder &builder, Value input, vector::CombiningKind kind, uint32_t size)
Given an input value representing per-lane data, this function returns the result after performing a ...
bool matchUnitDimExpansion(ArrayRef< int64_t > src, ArrayRef< int64_t > dst, SmallVector< int64_t > &expandedUnitDims)
std::optional< SmallVector< int64_t > > getInner2DIfUnitLeadingDims(ArrayRef< int64_t > vals)
Returns the innermost 2 entries of vals if it is at least 2D and all of its leading entries are unit;...
int getLargestDivisor(T dim, ArrayRef< T > candidates, ArrayRef< T > candidateMultiples={})
Helper Function to find a proper instruction multiple for the user-supplied sg-level data shape (dive...
FailureOr< int64_t > getNumSubgroupsFromBlockSize(Operation *op, int64_t subgroupSize)
Returns the number of subgroups the kernel enclosing op runs, derived from the known_block_size of it...
bool hasStaticShapeAndStrides(MemRefType type)
Returns true if type has a static shape and static strides.
FailureOr< VectorType > getDistVecTypeBasedOnLaneLayout(DistributeLayoutAttr layout, VectorType originalType)
Helper function to get distributed vector type for a source vector type according to the lane_layout.
Value lowerToVectorReductions(TypedValue< VectorType > src, TypedValue< VectorType > acc, vector::CombiningKind kind, int64_t reductionDim, Location loc, PatternRewriter &rewriter)
Given a src and an acc argumments from a vector::MultiDimReductionOp, lower to a set of vector::Reduc...
bool requireTranspose(const DistributeLayoutAttr layout, const uArch::uArch *uArch)
Helper function to check if the layout requires a transpose effect.
bool matchSplitDimExpansion(ArrayRef< int64_t > src, ArrayRef< int64_t > dst, SmallVector< SmallVector< int64_t > > &splitDimGroups)
DistributeLayoutAttr getDistributeLayoutAttr(const Value value)
Retrieves the DistributeLayoutAttr associated with a given Value, or nullptr if none is found.
DenseMap< Value, SmallVector< Type > > precomputeLoopBlockArgTypes(Operation *topLevelOp, SubShapeAndCountFn getSubShapeAndCount)
Pre-computes distributed VectorType mappings for every value carried through an SCF loop under topLev...
std::string getTemporaryLayoutName(const OpOperand &operand)
Return the attribute name for the OpOperand to attach DistributeLayoutAttr.
std::optional< std::string > getChipStr(Operation *op)
Retrieves the chip string from the XeVM target attribute of the parent GPU module operation.
void addVectorTypeConversion(TypeConverter &converter, SubShapeAndCountFn getSubShapeAndCount, DenseMap< Value, SmallVector< Type > > loopArgTypes)
Adds a context-aware VectorType conversion to converter (1:1 shape-changing or 1:N,...
SmallVector< Value > extractVectorsWithShapeFromValue(OpBuilder &builder, Location loc, Value value, ArrayRef< int64_t > shape)
Extract a set of small vectors from a value with a given shape using vector.extract_stride_slice.
DistributeLayoutAttr getTemporaryLayout(const T &operandOrResult)
get and set distribute layout attribute for non-anchor operations (and offsets/masks of load/store op...
Value lowerCrossLaneReductionToShuffles(TypedValue< VectorType > src, TypedValue< VectorType > acc, vector::CombiningKind kind, int64_t reductionDim, int64_t reductionSize, Location loc, PatternRewriter &rewriter)
Lowers cross-lane reductions to shuffle operations on a 2D vector.
std::function< std::pair< SmallVector< int64_t >, int >( VectorType, DistributeLayoutAttr)> SubShapeAndCountFn
Callback type for computing sub-shape and count for 1:N (or 1:1 shape-changing) VectorType conversion...
Definition XeGPUUtils.h:258
void cleanupUnrealizedConversionCasts(Operation *root, const llvm::SmallSetVector< UnrealizedConversionCastOp, 8 > &existingCasts)
Cleans up UnrealizedConversionCastOps inserted during SCF structural type conversion and/or XeGPU unr...
SmallVector< Value > flattenValues(ArrayRef< ValueRange > values)
Flatten a set of ValueRange into a single SmallVector<Value>
SmallVector< OpFoldResult > addWithRightAligned(OpBuilder &builder, Location loc, ArrayRef< OpFoldResult > lhs, ArrayRef< OpFoldResult > rhs)
Generates element-wise addition ops of two arrays with automatic alignment.
SmallVector< OpFoldResult > addElementwise(OpBuilder &builder, Location loc, ArrayRef< OpFoldResult > lhs, ArrayRef< OpFoldResult > rhs)
Generates element-wise addition ops of two arrays with same length.
FailureOr< VectorType > getDistributedVectorType(xegpu::TensorDescType tdescTy)
If tensor descriptor has a layout attribute it is used in SIMT mode.
Include the generated interface declarations.
std::conditional_t< std::is_same_v< Ty, mlir::Type >, mlir::Value, detail::TypedValue< Ty > > TypedValue
If Ty is mlir::Type this will select Value instead of having a wrapper around it.
Definition Value.h:494
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
Definition LLVM.h:123