Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
eaaca7f
save
charithaintc Aug 19, 2025
56c3441
save
charithaintc Aug 19, 2025
8da99e4
Merge branch 'main' into vector_multi_reduction_distr
charithaintc Aug 19, 2025
01880b5
save
charithaintc Aug 19, 2025
53da992
save
charithaintc Aug 19, 2025
affd4aa
save
charithaintc Aug 19, 2025
df59c20
save
charithaintc Aug 20, 2025
70a5a49
Merge branch 'main' into vector_multi_reduction_distr
charithaintc Aug 20, 2025
5579731
save
charithaintc Aug 20, 2025
07c0364
save
charithaintc Aug 20, 2025
4b031de
save work
charithaintc Aug 28, 2025
4ed74d8
save work
charithaintc Aug 28, 2025
66e105f
Merge branch 'main' into vector_multi_reduction_distr
charithaintc Sep 2, 2025
116e4bc
save work
charithaintc Sep 2, 2025
360543e
Merge branch 'main' into vector_multi_reduction_distr
charithaintc Sep 3, 2025
a78aec5
move work
charithaintc Sep 3, 2025
2ba43fc
save work
charithaintc Sep 3, 2025
3dea80c
save test
charithaintc Sep 4, 2025
3c06f28
save work
charithaintc Sep 5, 2025
8728eee
save work
charithaintc Sep 8, 2025
9b72ac0
save work
charithaintc Sep 8, 2025
ce9dd27
Merge branch 'main' into vector_multi_reduction_distr_refactor
charithaintc Sep 8, 2025
1854713
save work
charithaintc Sep 8, 2025
797aa3e
save work
charithaintc Sep 8, 2025
017e12b
Merge branch 'main' into vector_multi_reduction_distr_refactor
charithaintc Sep 9, 2025
232808e
save work
charithaintc Sep 9, 2025
be1c00c
add transpose function
charithaintc Sep 10, 2025
2ebe31e
fix test
charithaintc Sep 10, 2025
f9b3933
Merge branch 'main' into vector_multi_reduction_distr_refactor
charithaintc Sep 10, 2025
82486fa
Merge branch 'main' into slice_utils
charithaintc Sep 10, 2025
916c75f
add slice attribute utils
charithaintc Sep 10, 2025
77e8a94
fix name
charithaintc Sep 10, 2025
0550d4b
Merge branch 'slice_utils' into vector_multi_reduction_distr_refactor
charithaintc Sep 11, 2025
6e2f420
fix func naming
charithaintc Sep 11, 2025
1c4f06f
fix func naming
charithaintc Sep 11, 2025
c7114c8
Merge branch 'main' into vector_multi_reduction_distr_refactor
charithaintc Sep 11, 2025
8febca8
remove header
charithaintc Sep 12, 2025
72be293
Merge branch 'main' into vector_multi_reduction_distr_refactor
charithaintc Sep 12, 2025
3cf382c
Merge branch 'main' into vector_multi_reduction_distr_refactor
charithaintc Sep 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 40 additions & 27 deletions mlir/include/mlir/Dialect/XeGPU/IR/XeGPUAttrs.td
Original file line number Diff line number Diff line change
Expand Up @@ -194,26 +194,29 @@ def DistributeLayoutAttr: AttrInterface<"DistributeLayoutAttr"> {
InterfaceMethod<"Get the num of effective subgroups",
"int64_t",
"getNumSubgroups", (ins), [{
std::optional<SmallVector<int64_t>> sgLayout = llvm::cast<ConcreteAttr>(tablegen_opaque_val).getSgLayoutAsInt();
std::optional<SmallVector<int64_t>> sgLayout = llvm::cast<ConcreteAttr>(tablegen_opaque_val).getEffectiveSgLayoutAsInt();
if (sgLayout.has_value())
return computeProduct(*sgLayout);
return 0;
}], [{}]>,
InterfaceMethod<"Get the SgLayout field of the attribute as integer array",
InterfaceMethod<"Get the order of the layout attribute",
"DenseI32ArrayAttr",
"getOrder">,
InterfaceMethod<"Get the effective SgLayout of the layout attribute as integer array",
"SmallVector<int64_t>",
"getSgLayoutAsInt">,
InterfaceMethod<"Get the SgData field of the attribute as integer array",
"getEffectiveSgLayoutAsInt">,
InterfaceMethod<"Get the effective SgData of the layout attribute as integer array",
"SmallVector<int64_t>",
"getSgDataAsInt">,
InterfaceMethod<"Get the InstData field of the attribute as integer array",
"getEffectiveSgDataAsInt">,
InterfaceMethod<"Get the effective InstData of the layout attribute as integer array",
"SmallVector<int64_t>",
"getInstDataAsInt">,
InterfaceMethod<"Get the LaneLayout field of the attribute as integer array",
"getEffectiveInstDataAsInt">,
InterfaceMethod<"Get the effective LaneLayout of the layout attribute as integer array",
"SmallVector<int64_t>",
"getLaneLayoutAsInt">,
InterfaceMethod<"Get the LaneData field of the attribute as integer array",
"getEffectiveLaneLayoutAsInt">,
InterfaceMethod<"Get the effective LaneData of the layout attribute as integer array",
"SmallVector<int64_t>",
"getLaneDataAsInt">,
"getEffectiveLaneDataAsInt">,
InterfaceMethod<"Derive a new layout by dropping sgLayout and sgData",
"xegpu::DistributeLayoutAttr",
"dropSgLayoutAndData">,
Expand All @@ -231,7 +234,11 @@ def DistributeLayoutAttr: AttrInterface<"DistributeLayoutAttr"> {
multiple blocks according to round-robin distribution rules.}],
"FailureOr<SmallVector<SmallVector<Value>>>",
"getOffsets",
(ins "OpBuilder &": $builder, "Location":$loc, "Value":$linearId, "ArrayRef<int64_t>":$shape)>
(ins "OpBuilder &": $builder, "Location":$loc, "Value":$linearId, "ArrayRef<int64_t>":$shape)>,
InterfaceMethod</*desc=*/[{Check if this layout is a slice of some other layout.}],
/*retTy=*/"bool",
/*methodName=*/"isSliceOf",
/*args=*/(ins "const xegpu::DistributeLayoutAttr&": $other)>
];
}

Expand Down Expand Up @@ -391,31 +398,31 @@ def XeGPU_LayoutAttr : XeGPUAttr<"Layout", "layout", [DistributeLayoutAttr]> {
getLaneLayout(), getLaneData(), getOrder());
}

SmallVector<int64_t> getSgLayoutAsInt() const {
SmallVector<int64_t> getEffectiveSgLayoutAsInt() const {
if (DenseI32ArrayAttr layout = getSgLayout())
return llvm::to_vector_of<int64_t>(layout.asArrayRef());
return {};
}

SmallVector<int64_t> getSgDataAsInt() const {
SmallVector<int64_t> getEffectiveSgDataAsInt() const {
if (DenseI32ArrayAttr data = getSgData())
return llvm::to_vector_of<int64_t>(data.asArrayRef());
return {};
}

SmallVector<int64_t> getInstDataAsInt() const {
SmallVector<int64_t> getEffectiveInstDataAsInt() const {
if (DenseI32ArrayAttr inst = getInstData())
return llvm::to_vector_of<int64_t>(inst.asArrayRef());
return {};
}

SmallVector<int64_t> getLaneLayoutAsInt() const {
SmallVector<int64_t> getEffectiveLaneLayoutAsInt() const {
if (DenseI32ArrayAttr layout = getLaneLayout())
return llvm::to_vector_of<int64_t>(layout.asArrayRef());
return {};
}

SmallVector<int64_t> getLaneDataAsInt() const {
SmallVector<int64_t> getEffectiveLaneDataAsInt() const {
if (DenseI32ArrayAttr data = getLaneData())
return llvm::to_vector_of<int64_t>(data.asArrayRef());
return {};
Expand All @@ -433,6 +440,9 @@ def XeGPU_LayoutAttr : XeGPUAttr<"Layout", "layout", [DistributeLayoutAttr]> {
FailureOr<SmallVector<SmallVector<Value>>>
getOffsets(OpBuilder &builder, Location loc, Value linearId, ArrayRef<int64_t> shape);

/// Check if this is slice of some other layout.
bool isSliceOf(const xegpu::DistributeLayoutAttr &other) { return false; }

}];

let assemblyFormat = "`<` struct(params) `>`";
Expand Down Expand Up @@ -499,10 +509,10 @@ def XeGPU_SliceAttr : XeGPUAttr<"Slice", "slice", [DistributeLayoutAttr]> {

/// Returns the SgLayout of the attribute, computed by applying
/// the slice dimensions to the underlying LayoutAttr.
SmallVector<int64_t> getSgLayoutAsInt() const {
SmallVector<int64_t> getEffectiveSgLayoutAsInt() const {
SliceAttr attr = flatten();
auto parent = dyn_cast<LayoutAttr>(attr.getParent());
auto layout = parent.getSgLayoutAsInt();
auto layout = parent.getEffectiveSgLayoutAsInt();
if (layout.size()) {
ArrayRef<int64_t> dims = attr.getDims().asArrayRef();
return XeGPUDialect::slice(ArrayRef<int64_t>(layout), dims);
Expand All @@ -512,10 +522,10 @@ def XeGPU_SliceAttr : XeGPUAttr<"Slice", "slice", [DistributeLayoutAttr]> {

/// Returns the SgData of the attribute, computed by applying
/// the slice dimensions to the underlying LayoutAttr.
SmallVector<int64_t> getSgDataAsInt() const {
SmallVector<int64_t> getEffectiveSgDataAsInt() const {
SliceAttr attr = flatten();
auto parent = dyn_cast<LayoutAttr>(attr.getParent());
auto data = parent.getSgDataAsInt();
auto data = parent.getEffectiveSgDataAsInt();
if (data.size()) {
ArrayRef<int64_t> dims = attr.getDims().asArrayRef();
return XeGPUDialect::slice(ArrayRef<int64_t>(data), dims);
Expand All @@ -525,10 +535,10 @@ def XeGPU_SliceAttr : XeGPUAttr<"Slice", "slice", [DistributeLayoutAttr]> {

/// Returns the InstData of the attribute, computed by applying
/// the slice dimensions to the underlying LayoutAttr.
SmallVector<int64_t> getInstDataAsInt() const {
SmallVector<int64_t> getEffectiveInstDataAsInt() const {
SliceAttr attr = flatten();
auto parent = dyn_cast<LayoutAttr>(attr.getParent());
auto inst = parent.getInstDataAsInt();
auto inst = parent.getEffectiveInstDataAsInt();
if (inst.size()) {
ArrayRef<int64_t> dims = attr.getDims().asArrayRef();
return XeGPUDialect::slice(llvm::ArrayRef<int64_t>(inst), dims);
Expand All @@ -538,10 +548,10 @@ def XeGPU_SliceAttr : XeGPUAttr<"Slice", "slice", [DistributeLayoutAttr]> {

/// Returns the LaneLayout of the attribute, computed by applying
/// the slice dimensions to the underlying LayoutAttr.
SmallVector<int64_t> getLaneLayoutAsInt() const {
SmallVector<int64_t> getEffectiveLaneLayoutAsInt() const {
SliceAttr attr = flatten();
auto parent = dyn_cast<LayoutAttr>(attr.getParent());
auto layout = parent.getLaneLayoutAsInt();
auto layout = parent.getEffectiveLaneLayoutAsInt();
if (layout.size()) {
ArrayRef<int64_t> dims = attr.getDims().asArrayRef();
return XeGPUDialect::slice(llvm::ArrayRef<int64_t>(layout), dims);
Expand All @@ -551,10 +561,10 @@ def XeGPU_SliceAttr : XeGPUAttr<"Slice", "slice", [DistributeLayoutAttr]> {

/// Returns the LaneData of the attribute, computed by applying
/// the slice dimensions to the underlying LayoutAttr.
SmallVector<int64_t> getLaneDataAsInt() const {
SmallVector<int64_t> getEffectiveLaneDataAsInt() const {
SliceAttr attr = flatten();
auto parent = dyn_cast<LayoutAttr>(attr.getParent());
auto data = parent.getLaneDataAsInt();
auto data = parent.getEffectiveLaneDataAsInt();
if (data.size()) {
ArrayRef<int64_t> dims = attr.getDims().asArrayRef();
return XeGPUDialect::slice(llvm::ArrayRef<int64_t>(data), dims);
Expand Down Expand Up @@ -594,6 +604,9 @@ def XeGPU_SliceAttr : XeGPUAttr<"Slice", "slice", [DistributeLayoutAttr]> {
FailureOr<SmallVector<SmallVector<Value>>>
getOffsets(OpBuilder &builder, Location loc, Value linearId, ArrayRef<int64_t> shape);

/// Check if this is slice of some other layout.
bool isSliceOf(const xegpu::DistributeLayoutAttr &other);

}];

let assemblyFormat = "`<` qualified($parent) `,` `dims` `=` $dims `>`";
Expand Down
4 changes: 4 additions & 0 deletions mlir/include/mlir/Dialect/XeGPU/Transforms/Passes.td
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ def XeGPUSubgroupDistribute : Pass<"xegpu-subgroup-distribute"> {
}];
let dependentDialects = ["memref::MemRefDialect", "xegpu::XeGPUDialect",
"vector::VectorDialect"];
let options = [Option<
"enableSGReductions", "enable-sg-reductions", "bool",
/*default=*/"true",
"Enable subgroup reductions using subgroup shuffles.">];
}

def XeGPUPropagateLayout : Pass<"xegpu-propagate-layout"> {
Expand Down
46 changes: 34 additions & 12 deletions mlir/lib/Dialect/XeGPU/IR/XeGPUDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,22 +133,23 @@ bool XeGPUDialect::isEvenlyDistributable(llvm::ArrayRef<int64_t> shape,
};

// check the sgLayout and sgData
auto maybeSgShape =
tryDistribute(shape, attr.getSgLayoutAsInt(), attr.getSgDataAsInt());
auto maybeSgShape = tryDistribute(shape, attr.getEffectiveSgLayoutAsInt(),
attr.getEffectiveSgDataAsInt());
if (!maybeSgShape)
return false;
auto sgShape = maybeSgShape.value();

// check InstData, it neither have layout nor need round-robin
auto maybeInstShape =
tryDistribute(sgShape, {}, attr.getInstDataAsInt(), false);
tryDistribute(sgShape, {}, attr.getEffectiveInstDataAsInt(), false);
if (!maybeInstShape)
return false;
auto instShape = maybeInstShape.value();

// check LaneLayout and LaneData
auto maybeLaneShape = tryDistribute(instShape, attr.getLaneLayoutAsInt(),
attr.getLaneDataAsInt(), false);
auto maybeLaneShape =
tryDistribute(instShape, attr.getEffectiveLaneLayoutAsInt(),
attr.getEffectiveLaneDataAsInt(), false);
return maybeLaneShape.has_value();
}

Expand Down Expand Up @@ -282,9 +283,10 @@ LayoutAttr::delinearizeSubgroupId(OpBuilder &builder, Location loc,
if (!hasDefaultOrder())
return mlir::emitError(loc, "order attribute is currently not supported.");

auto dims = llvm::map_to_vector(getSgLayoutAsInt(), [&](int64_t d) -> Value {
return builder.createOrFold<arith::ConstantIndexOp>(loc, d);
});
auto dims =
llvm::map_to_vector(getEffectiveSgLayoutAsInt(), [&](int64_t d) -> Value {
return builder.createOrFold<arith::ConstantIndexOp>(loc, d);
});

return affine::delinearizeIndex(builder, loc, linearId, dims);
}
Expand All @@ -298,8 +300,8 @@ LayoutAttr::getOffsets(OpBuilder &builder, Location loc, Value linearId,
if (!isForWorkgroup())
return failure();

SmallVector<int64_t> sgLayout = getSgLayoutAsInt();
SmallVector<int64_t> sgShape = getSgDataAsInt();
SmallVector<int64_t> sgLayout = getEffectiveSgLayoutAsInt();
SmallVector<int64_t> sgShape = getEffectiveSgDataAsInt();
if (sgShape.empty()) {
if (auto derivedShape = computeShapeRatio(shape, sgLayout))
sgShape = derivedShape.value();
Expand Down Expand Up @@ -385,8 +387,8 @@ SliceAttr::getOffsets(OpBuilder &builder, Location loc, Value linearId,
if (!isForWorkgroup())
return failure();

SmallVector<int64_t> sgLayout = getSgLayoutAsInt();
SmallVector<int64_t> sgShape = getSgDataAsInt();
SmallVector<int64_t> sgLayout = getEffectiveSgLayoutAsInt();
SmallVector<int64_t> sgShape = getEffectiveSgDataAsInt();
if (sgShape.empty()) {
if (auto derivedShape = computeShapeRatio(shape, sgLayout))
sgShape = derivedShape.value();
Expand All @@ -409,6 +411,26 @@ SliceAttr::getOffsets(OpBuilder &builder, Location loc, Value linearId,
shape);
}

bool SliceAttr::isSliceOf(const xegpu::DistributeLayoutAttr &other) {
auto flattenedThis = flatten();
// If other is a LayoutAttr, just compare directly with parent of
// flattenedThis.
if (auto otherLayout = dyn_cast<xegpu::LayoutAttr>(other))
return flattenedThis.getParent() == otherLayout;
// If other is a SliceAttr, flatten it first before comparing.
auto flattenedOther = dyn_cast<xegpu::SliceAttr>(other).flatten();
// Both must have common parent LayoutAttr.
if (flattenedThis.getParent() != flattenedOther.getParent())
return false;
// otherFlattened's sliced dims must be a subset of flattenedThis's sliced
// dims.
llvm::SmallDenseSet<int64_t> thisDims(
flattenedThis.getDims().asArrayRef().begin(),
flattenedThis.getDims().asArrayRef().end());
return llvm::all_of(flattenedOther.getDims().asArrayRef(),
[&](int64_t dim) { return thisDims.contains(dim); });
}

//===----------------------------------------------------------------------===//
// XeGPU_RangeAttr
//===----------------------------------------------------------------------===//
Expand Down
20 changes: 10 additions & 10 deletions mlir/lib/Dialect/XeGPU/Transforms/XeGPUBlocking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,16 +85,16 @@ struct ConvertLayoutOpPattern
using OpRewritePattern::OpRewritePattern;
LogicalResult matchAndRewrite(xegpu::ConvertLayoutOp op,
PatternRewriter &rewriter) const override {
xegpu::DistributeLayoutAttr input_layout = op.getInputLayoutAttr();
xegpu::DistributeLayoutAttr target_layout = op.getTargetLayoutAttr();
if (input_layout.getInstDataAsInt().empty() ||
target_layout.getInstDataAsInt().empty())
xegpu::DistributeLayoutAttr inputLayout = op.getInputLayoutAttr();
xegpu::DistributeLayoutAttr targetLayout = op.getTargetLayoutAttr();
if (inputLayout.getEffectiveInstDataAsInt().empty() ||
targetLayout.getEffectiveInstDataAsInt().empty())
return rewriter.notifyMatchFailure(op, "Not a target ConvertLayoutOp.");

input_layout = input_layout.dropInstData();
target_layout = target_layout.dropInstData();
inputLayout = inputLayout.dropInstData();
targetLayout = targetLayout.dropInstData();
auto newOp = rewriter.createOrFold<xegpu::ConvertLayoutOp>(
op.getLoc(), op.getType(), op.getSource(), input_layout, target_layout);
op.getLoc(), op.getType(), op.getSource(), inputLayout, targetLayout);
rewriter.replaceOp(op, newOp);
return success();
}
Expand Down Expand Up @@ -145,8 +145,8 @@ XeGPUBlockingPass::getTileShape(const T &operandOrResult) const {
xegpu::DistributeLayoutAttr layout =
xegpu::getDistributeLayoutAttr(operandOrResult);
if (layout && layout.isForSubgroup()) {
if (!layout.getInstDataAsInt().empty())
return layout.getInstDataAsInt();
if (!layout.getEffectiveInstDataAsInt().empty())
return layout.getEffectiveInstDataAsInt();

if (auto type = dyn_cast<ShapedType>(value.getType()))
return llvm::to_vector(type.getShape());
Expand Down Expand Up @@ -226,7 +226,7 @@ bool XeGPUBlockingPass::needsUnroll(Operation *op) const {
Type valTy = value.getType();
if (auto tdescTy = dyn_cast<xegpu::TensorDescType>(valTy)) {
xegpu::DistributeLayoutAttr layout = tdescTy.getLayoutAttr();
return layout && !layout.getInstDataAsInt().empty();
return layout && !layout.getEffectiveInstDataAsInt().empty();
}
auto shapedType = dyn_cast<ShapedType>(valTy);
return shapedType && !llvm::equal(tileShape, shapedType.getShape());
Expand Down
Loading
Loading