Skip to content

Commit ad5d0a8

Browse files
committed
rename getLayoutAttr util
1 parent 68d6866 commit ad5d0a8

File tree

8 files changed

+132
-65
lines changed

8 files changed

+132
-65
lines changed

mlir/include/mlir/Dialect/XeGPU/IR/XeGPUAttrs.td

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,9 @@ def DistributeLayoutAttr: AttrInterface<"DistributeLayoutAttr"> {
185185
InterfaceMethod<"Check the availability of workgroup level layouts",
186186
"bool",
187187
"isForWorkgroup">,
188+
InterfaceMethod<"Check the availability of subgroup level layouts",
189+
"bool",
190+
"isForSubgroup">,
188191
InterfaceMethod<"Get the rank of attribute",
189192
"int64_t",
190193
"getRank">,
@@ -202,6 +205,15 @@ def DistributeLayoutAttr: AttrInterface<"DistributeLayoutAttr"> {
202205
InterfaceMethod<"Get the SgData field of the attribute as integer array",
203206
"std::optional<SmallVector<int64_t>>",
204207
"getSgDataAsInt">,
208+
InterfaceMethod<"Get the InstData field of the attribute as integer array",
209+
"std::optional<SmallVector<int64_t>>",
210+
"getInstDataAsInt">,
211+
InterfaceMethod<"Get the LaneLayout field of the attribute as integer array",
212+
"std::optional<SmallVector<int64_t>>",
213+
"getLaneLayoutAsInt">,
214+
InterfaceMethod<"Get the LaneData field of the attribute as integer array",
215+
"std::optional<SmallVector<int64_t>>",
216+
"getLaneDataAsInt">,
205217
InterfaceMethod<"Derive a new layout by dropping sgLayout and sgData",
206218
"xegpu::DistributeLayoutAttr",
207219
"dropSgLayoutAndData">,
@@ -388,6 +400,24 @@ def XeGPU_LayoutAttr : XeGPUAttr<"Layout", "layout", [DistributeLayoutAttr]> {
388400
return std::nullopt;
389401
}
390402

403+
std::optional<SmallVector<int64_t>> getInstDataAsInt() const {
404+
if (DenseI32ArrayAttr inst = getInstData())
405+
return llvm::to_vector_of<int64_t>(inst.asArrayRef());
406+
return std::nullopt;
407+
}
408+
409+
std::optional<SmallVector<int64_t>> getLaneLayoutAsInt() const {
410+
if (DenseI32ArrayAttr layout = getLaneLayout())
411+
return llvm::to_vector_of<int64_t>(layout.asArrayRef());
412+
return std::nullopt;
413+
}
414+
415+
std::optional<SmallVector<int64_t>> getLaneDataAsInt() const {
416+
if (DenseI32ArrayAttr data = getLaneData())
417+
return llvm::to_vector_of<int64_t>(data.asArrayRef());
418+
return std::nullopt;
419+
}
420+
391421
/// Delinearizes a linear subgroup ID into its multidimensional indices
392422
/// based on the effective subgroup layout.
393423
FailureOr<SmallVector<Value>>
@@ -488,6 +518,42 @@ def XeGPU_SliceAttr : XeGPUAttr<"Slice", "slice", [DistributeLayoutAttr]> {
488518
return std::nullopt;
489519
}
490520

521+
/// Returns the InstData of the attribute, computed by applying
522+
/// the slice dimensions to the underlying LayoutAttr.
523+
std::optional<SmallVector<int64_t>> getInstDataAsInt() const {
524+
SliceAttr attr = flatten();
525+
auto parent = dyn_cast<LayoutAttr>(attr.getParent());
526+
if (auto inst = parent.getInstDataAsInt()) {
527+
ArrayRef<int64_t> dims = attr.getDims().asArrayRef();
528+
return XeGPUDialect::slice(llvm::ArrayRef<int64_t>(*inst), dims);
529+
}
530+
return std::nullopt;
531+
}
532+
533+
/// Returns the LaneLayout of the attribute, computed by applying
534+
/// the slice dimensions to the underlying LayoutAttr.
535+
std::optional<SmallVector<int64_t>> getLaneLayoutAsInt() const {
536+
SliceAttr attr = flatten();
537+
auto parent = dyn_cast<LayoutAttr>(attr.getParent());
538+
if (auto layout = parent.getLaneLayoutAsInt()) {
539+
ArrayRef<int64_t> dims = attr.getDims().asArrayRef();
540+
return XeGPUDialect::slice(llvm::ArrayRef<int64_t>(*layout), dims);
541+
}
542+
return std::nullopt;
543+
}
544+
545+
/// Returns the LaneData of the attribute, computed by applying
546+
/// the slice dimensions to the underlying LayoutAttr.
547+
std::optional<SmallVector<int64_t>> getLaneDataAsInt() const {
548+
SliceAttr attr = flatten();
549+
auto parent = dyn_cast<LayoutAttr>(attr.getParent());
550+
if (auto data = parent.getLaneDataAsInt()) {
551+
ArrayRef<int64_t> dims = attr.getDims().asArrayRef();
552+
return XeGPUDialect::slice(llvm::ArrayRef<int64_t>(*data), dims);
553+
}
554+
return std::nullopt;
555+
}
556+
491557
SliceAttr dropSgLayoutAndData() {
492558
SliceAttr attr = flatten();
493559
auto parent = dyn_cast<LayoutAttr>(attr.getParent());

mlir/include/mlir/Dialect/XeGPU/IR/XeGPUDialect.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def XeGPU_Dialect : Dialect {
4040
let extraClassDeclaration = [{
4141
/// Checks if the given shape can be evenly distributed based on the layout
4242
/// and data factors provided by the LayoutAttr.
43-
static bool isEvenlyDistributable(llvm::ArrayRef<int64_t> shape, xegpu::LayoutAttr attr);
43+
static bool isEvenlyDistributable(llvm::ArrayRef<int64_t> shape, xegpu::DistributeLayoutAttr attr);
4444

4545
/// drops/slices the shape in the specified dims, and return the rest. e.g.,
4646
/// for shape = [32, 64, 8], dims = [0, 2], it will return [64]

mlir/include/mlir/Dialect/XeGPU/Utils/XeGPUUtils.h

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class ValueRange;
2121
class TypeConverter;
2222

2323
namespace xegpu {
24+
class DistributeLayoutAttr;
2425
class LayoutAttr;
2526
class TensorDescType;
2627
} // namespace xegpu
@@ -60,46 +61,46 @@ FailureOr<VectorType> getDistributedVectorType(xegpu::TensorDescType tdescTy);
6061
FailureOr<VectorType> getDistributedVectorType(VectorType originalType,
6162
LayoutAttr layout);
6263

63-
/// Return the attribute name for the OpOperand to attach LayoutAttr
64+
/// Return the attribute name for the OpOperand to attach DistributeLayoutAttr
6465
std::string getLayoutName(const OpOperand &operand);
6566

66-
/// Return the attribute name for the OpResult to attach LayoutAttr
67+
/// Return the attribute name for the OpResult to attach DistributeLayoutAttr
6768
std::string getLayoutName(const OpResult result);
6869

69-
/// Retrieves the LayoutAttr associated with a given Value. For TensorDescType
70-
/// values, the LayoutAttr is extracted from the TensorDescType itself. For
70+
/// Retrieves the DistributeLayoutAttr associated with a given Value. For TensorDescType
71+
/// values, the DistributeLayoutAttr is extracted from the TensorDescType itself. For
7172
/// other values, it is obtained from the attributes of the defining operation.
72-
/// Returns nullptr if no LayoutAttr is found.
73-
LayoutAttr getLayoutAttr(const Value value);
73+
/// Returns nullptr if no DistributeLayoutAttr is found.
74+
DistributeLayoutAttr getDistributeLayoutAttr(const Value value);
7475

75-
/// Retrieves the LayoutAttr associated with a given OpOperand. It will
76+
/// Retrieves the DistributeLayoutAttr associated with a given OpOperand. It will
7677
/// first check the operand_layout_{id} of the owner operation. If not found,
7778
/// it will check the operand itself and its defining op.
78-
LayoutAttr getLayoutAttr(const OpOperand &opr);
79+
DistributeLayoutAttr getDistributeLayoutAttr(const OpOperand &opr);
7980

8081
/// Removes the LayoutAttr for a given OpOperand or OpResult if it exists.
8182
template <typename T,
8283
typename = std::enable_if_t<std::is_same_v<T, OpOperand> ||
8384
std::is_same_v<T, OpResult>>>
8485
void removeLayoutAttr(const T &operandOrResult);
8586

86-
/// Removes the LayoutAttr for each OpOperand and OpResult of the given
87+
/// Removes the DistributeLayoutAttr for each OpOperand and OpResult of the given
8788
/// operation if they exist. If the operation contains regions, it is also
8889
/// applied recursively to the contained operations
8990
void removeLayoutAttrs(Operation *op);
9091

91-
/// Sets the LayoutAttr for a given OpOperand or OpResult by attaching
92+
/// Sets the DistributeLayoutAttr for a given OpOperand or OpResult by attaching
9293
/// it to the owner's dictionary attributes
9394
template <typename T,
9495
typename = std::enable_if_t<std::is_same_v<T, OpOperand> ||
9596
std::is_same_v<T, OpResult>>>
96-
void setLayoutAttr(const T &operandOrResult, const LayoutAttr layout);
97+
void setLayoutAttr(const T &operandOrResult, const DistributeLayoutAttr layout);
9798

98-
/// Set the LayoutAttr for each OpOperand and OpResult of the given operation.
99+
/// Set the DistributeLayoutAttr for each OpOperand and OpResult of the given operation.
99100
/// If the operation contains regions, it is also applied recursively to the
100101
/// contained operations
101102
void setLayoutAttrs(Operation *op,
102-
function_ref<LayoutAttr(Value)> getLayoutImpl);
103+
function_ref<DistributeLayoutAttr(Value)> getLayoutImpl);
103104

104105
/// Extract a set of small vectors from a value with a given shape using
105106
/// vector.extract_stride_slice

mlir/lib/Dialect/XeGPU/IR/XeGPUDialect.cpp

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ genOffsetsComputingInsts(OpBuilder &builder, Location loc,
9191
// Checks if the given shape can be evenly distributed based on the layout
9292
// and data factors provided by the LayoutAttr.
9393
bool XeGPUDialect::isEvenlyDistributable(llvm::ArrayRef<int64_t> shape,
94-
xegpu::LayoutAttr attr) {
94+
xegpu::DistributeLayoutAttr attr) {
9595
assert(attr && "Layout attribute is missing.");
9696

9797
// Checks whether the given shape can be evenly distributed using the
@@ -104,52 +104,51 @@ bool XeGPUDialect::isEvenlyDistributable(llvm::ArrayRef<int64_t> shape,
104104
// smaller than `layout[i] * data[i]`, allowing multiple compute units to
105105
// share the data.
106106
auto tryDistribute = [&](llvm::ArrayRef<int64_t> shape,
107-
DenseI32ArrayAttr layout, DenseI32ArrayAttr data,
107+
std::optional<SmallVector<int64_t>> layout,
108+
std::optional<SmallVector<int64_t>> data,
108109
bool rr = true) -> optional<SmallVector<int64_t>> {
109110
llvm::SmallVector<int64_t> newShape(shape);
110111
if (layout) {
111-
auto vec = llvm::to_vector_of<int64_t>(layout.asArrayRef());
112-
if (vec.size() != shape.size())
112+
if ((*layout).size() != shape.size())
113113
return std::nullopt;
114-
auto ratio = computeShapeRatio(shape, vec);
114+
auto ratio = computeShapeRatio(shape, *layout);
115115
if (!ratio.has_value())
116116
return std::nullopt;
117117
newShape = ratio.value();
118118
}
119119

120120
if (data) {
121-
auto vec = llvm::to_vector_of<int64_t>(data.asArrayRef());
122-
if (vec.size() != shape.size())
121+
if ((*data).size() != shape.size())
123122
return std::nullopt;
124-
auto ratio = computeShapeRatio(newShape, vec);
123+
auto ratio = computeShapeRatio(newShape, *data);
125124
if (!ratio.has_value() && rr)
126-
ratio = computeShapeRatio(vec, newShape);
125+
ratio = computeShapeRatio(*data, newShape);
127126
if (!ratio.has_value())
128127
return std::nullopt;
129128

130129
// if data is not null, we always return it for next phase.
131-
newShape = vec;
130+
newShape = *data;
132131
}
133132
return newShape;
134133
};
135134

136135
// check the sgLayout and sgData
137136
auto maybeSgShape =
138-
tryDistribute(shape, attr.getSgLayout(), attr.getSgData());
137+
tryDistribute(shape, attr.getSgLayoutAsInt(), attr.getSgDataAsInt());
139138
if (!maybeSgShape)
140139
return false;
141140
auto sgShape = maybeSgShape.value();
142141

143142
// check InstData, it neither have layout nor need round-robin
144143
auto maybeInstShape =
145-
tryDistribute(sgShape, nullptr, attr.getInstData(), false);
144+
tryDistribute(sgShape, std::nullopt, attr.getInstDataAsInt(), false);
146145
if (!maybeInstShape)
147146
return false;
148147
auto instShape = maybeInstShape.value();
149148

150149
// check LaneLayout and LaneData
151150
auto maybeLaneShape =
152-
tryDistribute(instShape, attr.getLaneLayout(), attr.getLaneData(), false);
151+
tryDistribute(instShape, attr.getLaneLayoutAsInt(), attr.getLaneDataAsInt(), false);
153152
return maybeLaneShape.has_value();
154153
}
155154

mlir/lib/Dialect/XeGPU/Transforms/XeGPUBlocking.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,10 @@ XeGPUBlockingPass::getTileShape(const T &operandOrResult) const {
140140
else
141141
value = (Value)operandOrResult;
142142

143-
xegpu::LayoutAttr layout = xegpu::getLayoutAttr(operandOrResult);
143+
xegpu::DistributeLayoutAttr layout = xegpu::getDistributeLayoutAttr(operandOrResult);
144144
if (layout && layout.isForSubgroup()) {
145-
if (auto inst_data = layout.getInstData())
146-
return llvm::to_vector_of<int64_t>(inst_data.asArrayRef());
145+
if (auto inst_data = layout.getInstDataAsInt())
146+
return inst_data.value();
147147

148148
if (auto type = dyn_cast<ShapedType>(value.getType()))
149149
return llvm::to_vector(type.getShape());
@@ -204,12 +204,12 @@ bool XeGPUBlockingPass::needsUnroll(Operation *op) const {
204204
// skip the op if any of its operands or results has workgroup level layouts
205205
bool hasWgLayoutOperands =
206206
llvm::any_of(op->getOpOperands(), [](OpOperand &opr) {
207-
xegpu::LayoutAttr layout = xegpu::getLayoutAttr(opr);
207+
xegpu::DistributeLayoutAttr layout = xegpu::getDistributeLayoutAttr(opr);
208208
return layout && layout.isForWorkgroup();
209209
});
210210
bool hasWgLayoutResults =
211211
llvm::any_of(op->getOpResults(), [](OpResult result) {
212-
xegpu::LayoutAttr layout = xegpu::getLayoutAttr(result);
212+
xegpu::DistributeLayoutAttr layout = xegpu::getDistributeLayoutAttr(result);
213213
return layout && layout.isForWorkgroup();
214214
});
215215
if (hasWgLayoutOperands || hasWgLayoutResults) {
@@ -220,8 +220,8 @@ bool XeGPUBlockingPass::needsUnroll(Operation *op) const {
220220
auto isUnrollable = [](Value value, ArrayRef<int64_t> tileShape) {
221221
Type valTy = value.getType();
222222
if (auto tdescTy = dyn_cast<xegpu::TensorDescType>(valTy)) {
223-
xegpu::LayoutAttr layout = tdescTy.getLayoutAttr();
224-
return layout && layout.getInstData();
223+
xegpu::DistributeLayoutAttr layout = tdescTy.getLayoutAttr();
224+
return layout && layout.getInstDataAsInt();
225225
}
226226
auto shapedType = dyn_cast<ShapedType>(valTy);
227227
return shapedType && !llvm::equal(tileShape, shapedType.getShape());
@@ -247,7 +247,7 @@ void XeGPUBlockingPass::runOnOperation() {
247247
// Preserve the LayoutAttr for each operand to the owner's DictionaryAttr.
248248
// This ensures that the LayoutAttr remains accessible even if the defining
249249
// operation is replaced.
250-
xegpu::setLayoutAttrs(op, [](Value v) { return xegpu::getLayoutAttr(v); });
250+
xegpu::setLayoutAttrs(op, [](Value v) { return xegpu::getDistributeLayoutAttr(v); });
251251

252252
auto getTileShapeAndCount = [](llvm::ArrayRef<int64_t> shape,
253253
xegpu::LayoutAttr layout) {

mlir/lib/Dialect/XeGPU/Transforms/XeGPUSubgroupDistribute.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -841,7 +841,7 @@ void XeGPUSubgroupDistributePass::runOnOperation() {
841841
if (!isa<VectorType>(operand.get().getType()))
842842
continue;
843843

844-
xegpu::LayoutAttr layout = xegpu::getLayoutAttr(operand);
844+
auto layout = dyn_cast<xegpu::LayoutAttr>(xegpu::getDistributeLayoutAttr(operand));
845845
if (!layout) {
846846
op->emitError("Could not find layout attribute for operand ")
847847
<< operand.getOperandNumber() << " of operation " << op->getName();
@@ -882,7 +882,8 @@ void XeGPUSubgroupDistributePass::runOnOperation() {
882882
if (vecRank == 0)
883883
return AffineMap::get(val.getContext());
884884
// Get the layout of the vector type.
885-
xegpu::LayoutAttr layout = xegpu::getLayoutAttr(val);
885+
// TODO: support more layout types
886+
auto layout = dyn_cast<xegpu::LayoutAttr>(xegpu::getDistributeLayoutAttr(val));
886887
// If no layout is specified, assume the inner most dimension is distributed
887888
// for now.
888889
if (!layout)

mlir/lib/Dialect/XeGPU/Transforms/XeGPUWgToSgDistribute.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ struct WgToSgDpasOp : public OpConversionPattern<xegpu::DpasOp> {
406406
if (resultTy.getRank() != 2)
407407
return failure();
408408

409-
auto originalLayout = xegpu::getLayoutAttr(op.getResult());
409+
auto originalLayout = xegpu::getDistributeLayoutAttr(op.getResult());
410410
if (!originalLayout)
411411
return failure();
412412

@@ -470,8 +470,8 @@ struct WgToSgVectorBroadcastOp
470470
VectorType resultType = op.getResult().getType();
471471
ArrayRef<int64_t> wgShape = resultType.getShape();
472472

473-
xegpu::LayoutAttr layout = xegpu::getLayoutAttr(op.getResult());
474-
if (!layout || !layout.getSgLayout())
473+
xegpu::DistributeLayoutAttr layout = xegpu::getDistributeLayoutAttr(op.getResult());
474+
if (!layout || !layout.isForWorkgroup())
475475
return failure();
476476

477477
// TODO: Currently only supports cases where the source and result ranks
@@ -487,8 +487,8 @@ struct WgToSgVectorBroadcastOp
487487

488488
// Check if the output layout is distributable
489489
SmallVector<int64_t> sgLayout;
490-
if (auto sgLayoutAttr = layout.getSgLayout())
491-
sgLayout = llvm::to_vector_of<int64_t>(sgLayoutAttr.asArrayRef());
490+
if (auto maybeSgLayout = layout.getSgLayoutAsInt())
491+
sgLayout = *maybeSgLayout;
492492
else
493493
return failure();
494494

@@ -535,8 +535,8 @@ struct WgToSgElementwiseOp : public ConversionPattern {
535535

536536
ArrayRef<int64_t> wgShape = resultType.getShape();
537537

538-
xegpu::LayoutAttr layout = xegpu::getLayoutAttr(op->getResult(0));
539-
if (!layout || !layout.getSgLayout())
538+
xegpu::DistributeLayoutAttr layout = xegpu::getDistributeLayoutAttr(op->getResult(0));
539+
if (!layout || !layout.isForWorkgroup())
540540
return failure();
541541

542542
SmallVector<int64_t> sgShape = getSgShapeAndCount(wgShape, layout).first;
@@ -737,8 +737,8 @@ struct WgToSgArithConstantOp : public OpConversionPattern<arith::ConstantOp> {
737737
if (!vecAttr || !vecAttr.isSplat() || !vecType)
738738
return failure();
739739

740-
xegpu::LayoutAttr layout = xegpu::getLayoutAttr(op.getResult());
741-
if (!layout || !layout.getSgLayout())
740+
xegpu::DistributeLayoutAttr layout = xegpu::getDistributeLayoutAttr(op.getResult());
741+
if (!layout || !layout.isForWorkgroup())
742742
return failure();
743743

744744
ArrayRef<int64_t> wgShape = vecType.getShape();
@@ -928,7 +928,7 @@ void XeGPUWgToSgDistributePass::runOnOperation() {
928928
});
929929

930930
target.addDynamicallyLegalOp<xegpu::DpasOp>([=](xegpu::DpasOp op) -> bool {
931-
auto layout = xegpu::getLayoutAttr(op.getResult());
931+
auto layout = xegpu::getDistributeLayoutAttr(op.getResult());
932932
return isLegal(layout);
933933
});
934934

@@ -947,12 +947,12 @@ void XeGPUWgToSgDistributePass::runOnOperation() {
947947
auto vecType = dyn_cast<VectorType>(op.getType());
948948
if (!vecType)
949949
return true;
950-
return isLegal(xegpu::getLayoutAttr(op.getResult()));
950+
return isLegal(xegpu::getDistributeLayoutAttr(op.getResult()));
951951
});
952952

953953
target.addDynamicallyLegalOp<vector::BroadcastOp>(
954954
[=](vector::BroadcastOp op) -> bool {
955-
return isLegal(xegpu::getLayoutAttr(op.getResult()));
955+
return isLegal(xegpu::getDistributeLayoutAttr(op.getResult()));
956956
});
957957

958958
target.addDynamicallyLegalOp<xegpu::ConvertLayoutOp>(
@@ -980,7 +980,7 @@ void XeGPUWgToSgDistributePass::runOnOperation() {
980980
}
981981
}
982982

983-
xegpu::LayoutAttr layout = xegpu::getLayoutAttr(op->getResult(0));
983+
xegpu::DistributeLayoutAttr layout = xegpu::getDistributeLayoutAttr(op->getResult(0));
984984
return isLegal(layout);
985985
});
986986

0 commit comments

Comments
 (0)