mirror of
https://github.com/intel/llvm.git
synced 2026-01-16 05:32:28 +08:00
[mlir] Add a parsePassPipeline overload that returns a new pass manager
This overload parses a pipeline string that contains the anchor operation type, and returns an OpPassManager corresponding to the provided pipeline. This is useful for various situations, such as dynamic pass pipelines which are not anchored within a parent pass pipeline. fixes #52813 Differential Revision: https://reviews.llvm.org/D116525
This commit is contained in:
@@ -197,13 +197,21 @@ template <> struct PassPipelineRegistration<EmptyPipelineOptions> {
|
||||
}
|
||||
};
|
||||
|
||||
/// This function parses the textual representation of a pass pipeline, and adds
|
||||
/// the result to 'pm' on success. This function returns failure if the given
|
||||
/// pipeline was invalid. 'errorStream' is the output stream used to emit errors
|
||||
/// found during parsing.
|
||||
/// Parse the textual representation of a pass pipeline, adding the result to
|
||||
/// 'pm' on success. Returns failure if the given pipeline was invalid.
|
||||
/// 'errorStream' is the output stream used to emit errors found during parsing.
|
||||
LogicalResult parsePassPipeline(StringRef pipeline, OpPassManager &pm,
|
||||
raw_ostream &errorStream = llvm::errs());
|
||||
|
||||
/// Parse the given textual representation of a pass pipeline, and return the
|
||||
/// parsed pipeline on success. The given pipeline string should be wrapped with
|
||||
/// the desired type of operation to root the created operation, i.e.
|
||||
/// `builtin.module(cse)` over `cse`. Returns failure if the given pipeline was
|
||||
/// invalid. 'errorStream' is the output stream used to emit errors found during
|
||||
/// parsing.
|
||||
FailureOr<OpPassManager>
|
||||
parsePassPipeline(StringRef pipeline, raw_ostream &errorStream = llvm::errs());
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PassPipelineCLParser
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -482,10 +482,6 @@ LogicalResult TextualPipeline::addToPipeline(
|
||||
return success();
|
||||
}
|
||||
|
||||
/// This function parses the textual representation of a pass pipeline, and adds
|
||||
/// the result to 'pm' on success. This function returns failure if the given
|
||||
/// pipeline was invalid. 'errorStream' is an optional parameter that, if
|
||||
/// non-null, will be used to emit errors found during parsing.
|
||||
LogicalResult mlir::parsePassPipeline(StringRef pipeline, OpPassManager &pm,
|
||||
raw_ostream &errorStream) {
|
||||
TextualPipeline pipelineParser;
|
||||
@@ -500,6 +496,24 @@ LogicalResult mlir::parsePassPipeline(StringRef pipeline, OpPassManager &pm,
|
||||
return success();
|
||||
}
|
||||
|
||||
FailureOr<OpPassManager> mlir::parsePassPipeline(StringRef pipeline,
|
||||
raw_ostream &errorStream) {
|
||||
// Pipelines are expected to be of the form `<op-name>(<pipeline>)`.
|
||||
size_t pipelineStart = pipeline.find_first_of('(');
|
||||
if (pipelineStart == 0 || pipelineStart == StringRef::npos ||
|
||||
!pipeline.consume_back(")")) {
|
||||
errorStream << "expected pass pipeline to be wrapped with the anchor "
|
||||
"operation type, e.g. `builtin.module(...)";
|
||||
return failure();
|
||||
}
|
||||
|
||||
StringRef opName = pipeline.take_front(pipelineStart);
|
||||
OpPassManager pm(opName);
|
||||
if (failed(parsePassPipeline(pipeline.drop_front(1 + pipelineStart), pm)))
|
||||
return failure();
|
||||
return pm;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PassNameParser
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -754,16 +754,10 @@ LogicalResult InlinerPass::initializeOptions(StringRef options) {
|
||||
// Skip empty pipelines.
|
||||
if (pipeline.empty())
|
||||
continue;
|
||||
|
||||
// Pipelines are expected to be of the form `<op-name>(<pipeline>)`.
|
||||
size_t pipelineStart = pipeline.find_first_of('(');
|
||||
if (pipelineStart == StringRef::npos || !pipeline.consume_back(")"))
|
||||
FailureOr<OpPassManager> pm = parsePassPipeline(pipeline);
|
||||
if (failed(pm))
|
||||
return failure();
|
||||
StringRef opName = pipeline.take_front(pipelineStart);
|
||||
OpPassManager pm(opName);
|
||||
if (failed(parsePassPipeline(pipeline.drop_front(1 + pipelineStart), pm)))
|
||||
return failure();
|
||||
pipelines.try_emplace(opName, std::move(pm));
|
||||
pipelines.try_emplace(pm->getOpName(), std::move(*pm));
|
||||
}
|
||||
opPipelines.assign({std::move(pipelines)});
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
add_mlir_unittest(MLIRPassTests
|
||||
AnalysisManagerTest.cpp
|
||||
PassManagerTest.cpp
|
||||
PassPipelineParserTest.cpp
|
||||
)
|
||||
target_link_libraries(MLIRPassTests
|
||||
PRIVATE
|
||||
|
||||
45
mlir/unittests/Pass/PassPipelineParserTest.cpp
Normal file
45
mlir/unittests/Pass/PassPipelineParserTest.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
//===- PassPipelineParserTest.cpp - Pass Parser unit tests ----------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "mlir/IR/Builders.h"
|
||||
#include "mlir/IR/BuiltinOps.h"
|
||||
#include "mlir/Pass/Pass.h"
|
||||
#include "mlir/Pass/PassManager.h"
|
||||
#include "mlir/Pass/PassRegistry.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
using namespace mlir;
|
||||
using namespace mlir::detail;
|
||||
|
||||
namespace {
|
||||
TEST(PassPipelineParserTest, InvalidOpAnchor) {
|
||||
// Helper functor used to parse a pipeline and check that it results in the
|
||||
// provided error message.
|
||||
auto checkParseFailure = [](StringRef pipeline, StringRef expectedErrorMsg) {
|
||||
std::string errorMsg;
|
||||
{
|
||||
llvm::raw_string_ostream os(errorMsg);
|
||||
FailureOr<OpPassManager> result = parsePassPipeline(pipeline, os);
|
||||
EXPECT_TRUE(failed(result));
|
||||
}
|
||||
EXPECT_TRUE(StringRef(errorMsg).contains(expectedErrorMsg));
|
||||
};
|
||||
|
||||
// Handle parse errors when the anchor is incorrectly structured.
|
||||
StringRef anchorErrorMsg =
|
||||
"expected pass pipeline to be wrapped with the anchor operation type";
|
||||
checkParseFailure("module", anchorErrorMsg);
|
||||
checkParseFailure("()", anchorErrorMsg);
|
||||
checkParseFailure("module(", anchorErrorMsg);
|
||||
checkParseFailure("module)", anchorErrorMsg);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
Reference in New Issue
Block a user