blob: 3dbc95149068606c8cf576fc3fae19b046cbfad7 [file]
// Copyright 2022 The IREE Authors
//
// Licensed 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
#include "iree/compiler/Dialect/Flow/Transforms/FormDispatchRegions.h"
#include "iree/compiler/Dialect/Flow/Transforms/ConvertRegionToWorkgroups.h"
#include "iree/compiler/Dialect/Flow/Transforms/RegionOpUtils.h"
#include "llvm/Support/Casting.h"
#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/Dialect/Tensor/IR/Tensor.h"
#include "mlir/Dialect/Utils/StructuredOpsUtils.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/Dominance.h"
#include "mlir/IR/Operation.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/Support/LLVM.h"
//===----------------------------------------------------------------------===//
// Definition of TensorDimTrackingRewriter
//===----------------------------------------------------------------------===//
namespace mlir {
TensorDimTrackingRewriter::TensorDimTrackingRewriter(Operation *op)
: IRRewriter(op->getContext()) {
setListener(this);
op->walk([&](tensor::DimOp dimOp) { dimOps.insert(dimOp.getOperation()); });
}
SmallVector<tensor::DimOp> TensorDimTrackingRewriter::getTensorDimOps() {
SmallVector<tensor::DimOp> result;
for (Operation *op : dimOps)
result.push_back(cast<tensor::DimOp>(op));
return result;
}
void TensorDimTrackingRewriter::notifyOperationErased(Operation *op) {
IRRewriter::Listener::notifyOperationErased(op);
if (isa<tensor::DimOp>(op))
dimOps.erase(op);
}
void TensorDimTrackingRewriter::notifyOperationInserted(Operation *op,
InsertPoint previous) {
IRRewriter::Listener::notifyOperationInserted(op, previous);
if (isa<tensor::DimOp>(op))
dimOps.insert(op);
}
} // namespace mlir
namespace mlir::iree_compiler::IREE::Flow {
LogicalResult simplifyDimOps(RewriterBase &rewriter,
const SmallVector<tensor::DimOp> &dimOps) {
for (tensor::DimOp dimOp : dimOps) {
// Only DimOps with static indices are supported.
std::optional<int64_t> idx = dimOp.getConstantIndex();
if (!idx.has_value())
continue;
// Only DimOps with ranked tensors are supported.
auto tensorType =
llvm::dyn_cast<RankedTensorType>(dimOp.getSource().getType());
if (!tensorType)
continue;
if (!tensorType.isDynamicDim(*idx)) {
// Rewrite static dimension with constant.
OpBuilder::InsertionGuard g(rewriter);
rewriter.setInsertionPoint(dimOp);
int64_t size = tensorType.getShape()[*idx];
rewriter.replaceOpWithNewOp<arith::ConstantIndexOp>(dimOp, size);
continue;
}
// Try to simplify dynamic dims.
SmallVector<Value> dynamicDims;
if (succeeded(IREE::Flow::getOptimizedDynamicResultDims(
rewriter, dimOp.getSource(), dynamicDims))) {
unsigned ctr = 0;
for (int64_t i = 0; i < *dimOp.getConstantIndex(); ++i)
if (tensorType.isDynamicDim(i))
++ctr;
rewriter.replaceOp(dimOp, dynamicDims[ctr]);
}
}
return success();
}
} // namespace mlir::iree_compiler::IREE::Flow