blob: 9690b148edd7004975e212de48cd3db83b46fa97 [file]
// Copyright 2021 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/Util/Transforms/Passes.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Pass/PassManager.h"
namespace mlir::iree_compiler::IREE::Util {
#define GEN_PASS_DEF_FIXEDPOINTITERATORPASS
#include "iree/compiler/Dialect/Util/Transforms/Passes.h.inc"
namespace {
// Dynamic pass which runs a sub-pipeline to a fixed point or a maximum
// iteration count.
//
// There is no direct coupling between this iterator and the contained passes.
// Indirectly, at the start of each iteration, this pass will set the
// "iree.fixedpoint.converged" unit attribute on the root operation. If it is
// still there when the sub-pipeline is complete, it will be removed and
// iteration terminates. If a sub-pass removes it, then iteration will
// continue.
class FixedPointIteratorPass
: public impl::FixedPointIteratorPassBase<FixedPointIteratorPass> {
public:
using Base::Base;
FixedPointIteratorPass() = default;
FixedPointIteratorPass(const FixedPointIteratorPass &other)
: impl::FixedPointIteratorPassBase<FixedPointIteratorPass>(other) {}
FixedPointIteratorPass(OpPassManager pipeline);
private:
LogicalResult initializeOptions(
StringRef options,
function_ref<LogicalResult(const Twine &)> errorHandler) override;
void getDependentDialects(DialectRegistry &registry) const override;
void runOnOperation() override;
std::optional<OpPassManager> pipeline;
// Serialized form of the body pipeline.
Option<std::string> pipelineStr{
*this, "pipeline", llvm::cl::desc("Pipeline to run to a fixed point")};
Option<int> maxIterations{*this, "max-iterations",
llvm::cl::desc("Maximum number of iterations"),
llvm::cl::init(10)};
};
FixedPointIteratorPass::FixedPointIteratorPass(OpPassManager pipeline)
: pipeline(std::move(pipeline)) {
llvm::raw_string_ostream ss(pipelineStr);
this->pipeline->printAsTextualPipeline(ss);
ss.flush();
}
LogicalResult FixedPointIteratorPass::initializeOptions(
StringRef options,
function_ref<LogicalResult(const Twine &)> errorHandler) {
if (failed(Pass::initializeOptions(options, errorHandler)))
return failure();
if (pipeline)
return success();
// Pipelines are expected to be of the form `<op-name>(<pipeline>)`.
// TODO: This was lifted from the Inliner pass. We should provide a parse
// entry point that is the direct inverse of printAsTextualPipeline() and
// at least keep this internal to the upstream implementation.
// See: https://github.com/llvm/llvm-project/issues/52813
StringRef pipelineSr = pipelineStr;
size_t pipelineStart = pipelineSr.find_first_of('(');
if (pipelineStart == StringRef::npos || !pipelineSr.consume_back(")"))
return failure();
StringRef opName = pipelineSr.take_front(pipelineStart);
OpPassManager pm(opName);
if (failed(parsePassPipeline(pipelineSr.drop_front(1 + pipelineStart), pm)))
return failure();
pipeline = std::move(pm);
return success();
}
void FixedPointIteratorPass::getDependentDialects(
DialectRegistry &registry) const {
pipeline->getDependentDialects(registry);
}
void FixedPointIteratorPass::runOnOperation() {
MLIRContext *context = &getContext();
StringAttr markerName = StringAttr::get(context, "iree.fixedpoint.iteration");
StringAttr modifiedName =
StringAttr::get(context, "iree.fixedpoint.modified");
if (getOperation()->hasAttr(markerName)) {
emitError(getOperation()->getLoc())
<< "nested fixed point pipelines not supported";
return signalPassFailure();
}
for (int i = 0; i < maxIterations; ++i) {
getOperation()->setAttr(markerName,
IntegerAttr::get(IndexType::get(context), i));
getOperation()->removeAttr(modifiedName);
if (failed(runPipeline(*pipeline, getOperation()))) {
return signalPassFailure();
}
if (!getOperation()->hasAttr(modifiedName)) {
// Normal exit.
getOperation()->removeAttr(markerName);
return;
}
}
// Abnormal exit - iteration count exceeded.
emitError(getOperation()->getLoc())
<< "maximum iteration count exceeded in fixed point pipeline";
return signalPassFailure();
}
} // namespace
std::unique_ptr<OperationPass<void>>
createFixedPointIteratorPass(OpPassManager pipeline) {
return std::make_unique<FixedPointIteratorPass>(std::move(pipeline));
}
} // namespace mlir::iree_compiler::IREE::Util