Files
clang-p2996/mlir/lib/Dialect/SPIRV/Transforms/RewriteInsertsPass.cpp
Hsiangkai Wang 9f1da90d6f [mlir][SPIRV] Do not rewrite CompositeInsert for coopmatrix (#137837)
When rewriting multiple CompositeInserts to CompositeConstruct, we need
to know the number of elements of the result type. However, we cannot
query the number of elements for cooperative matrix types.
2025-05-21 08:12:24 +01:00

121 lines
3.8 KiB
C++

//===- RewriteInsertsPass.cpp - MLIR conversion pass ----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements a pass to rewrite sequential chains of
// `spirv::CompositeInsert` operations into `spirv::CompositeConstruct`
// operations.
//
//===----------------------------------------------------------------------===//
#include "mlir/Dialect/SPIRV/Transforms/Passes.h"
#include "mlir/Dialect/SPIRV/IR/SPIRVOps.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinOps.h"
namespace mlir {
namespace spirv {
#define GEN_PASS_DEF_SPIRVREWRITEINSERTSPASS
#include "mlir/Dialect/SPIRV/Transforms/Passes.h.inc"
} // namespace spirv
} // namespace mlir
using namespace mlir;
namespace {
/// Replaces sequential chains of `spirv::CompositeInsertOp` operation into
/// `spirv::CompositeConstructOp` operation if possible.
class RewriteInsertsPass
: public spirv::impl::SPIRVRewriteInsertsPassBase<RewriteInsertsPass> {
public:
void runOnOperation() override;
private:
/// Collects a sequential insertion chain by the given
/// `spirv::CompositeInsertOp` operation, if the given operation is the last
/// in the chain.
LogicalResult
collectInsertionChain(spirv::CompositeInsertOp op,
SmallVectorImpl<spirv::CompositeInsertOp> &insertions);
};
} // namespace
void RewriteInsertsPass::runOnOperation() {
SmallVector<SmallVector<spirv::CompositeInsertOp, 4>, 4> workList;
getOperation().walk([this, &workList](spirv::CompositeInsertOp op) {
SmallVector<spirv::CompositeInsertOp, 4> insertions;
if (succeeded(collectInsertionChain(op, insertions)))
workList.push_back(insertions);
});
for (const auto &insertions : workList) {
auto lastCompositeInsertOp = insertions.back();
auto compositeType = lastCompositeInsertOp.getType();
auto location = lastCompositeInsertOp.getLoc();
SmallVector<Value, 4> operands;
// Collect inserted objects.
for (auto insertionOp : insertions)
operands.push_back(insertionOp.getObject());
OpBuilder builder(lastCompositeInsertOp);
auto compositeConstructOp = builder.create<spirv::CompositeConstructOp>(
location, compositeType, operands);
lastCompositeInsertOp.replaceAllUsesWith(
compositeConstructOp->getResult(0));
// Erase ops.
for (auto insertOp : llvm::reverse(insertions)) {
auto *op = insertOp.getOperation();
if (op->use_empty())
insertOp.erase();
}
}
}
LogicalResult RewriteInsertsPass::collectInsertionChain(
spirv::CompositeInsertOp op,
SmallVectorImpl<spirv::CompositeInsertOp> &insertions) {
if (isa<spirv::CooperativeMatrixType>(op.getComposite().getType()))
return failure();
auto indicesArrayAttr = cast<ArrayAttr>(op.getIndices());
// TODO: handle nested composite object.
if (indicesArrayAttr.size() == 1) {
auto numElements = cast<spirv::CompositeType>(op.getComposite().getType())
.getNumElements();
auto index = cast<IntegerAttr>(indicesArrayAttr[0]).getInt();
// Need a last index to collect a sequential chain.
if (index + 1 != numElements)
return failure();
insertions.resize(numElements);
while (true) {
insertions[index] = op;
if (index == 0)
return success();
op = op.getComposite().getDefiningOp<spirv::CompositeInsertOp>();
if (!op)
return failure();
--index;
indicesArrayAttr = cast<ArrayAttr>(op.getIndices());
if ((indicesArrayAttr.size() != 1) ||
(cast<IntegerAttr>(indicesArrayAttr[0]).getInt() != index))
return failure();
}
}
return failure();
}