Skip to content

Commit 0998637

Browse files
committed
[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 llvm#52813 Differential Revision: https://reviews.llvm.org/D116525
1 parent 04e8c8f commit 0998637

File tree

5 files changed

+79
-17
lines changed

5 files changed

+79
-17
lines changed

mlir/include/mlir/Pass/PassRegistry.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -197,13 +197,21 @@ template <> struct PassPipelineRegistration<EmptyPipelineOptions> {
197197
}
198198
};
199199

200-
/// This function parses the textual representation of a pass pipeline, and adds
201-
/// the result to 'pm' on success. This function returns failure if the given
202-
/// pipeline was invalid. 'errorStream' is the output stream used to emit errors
203-
/// found during parsing.
200+
/// Parse the textual representation of a pass pipeline, adding the result to
201+
/// 'pm' on success. Returns failure if the given pipeline was invalid.
202+
/// 'errorStream' is the output stream used to emit errors found during parsing.
204203
LogicalResult parsePassPipeline(StringRef pipeline, OpPassManager &pm,
205204
raw_ostream &errorStream = llvm::errs());
206205

206+
/// Parse the given textual representation of a pass pipeline, and return the
207+
/// parsed pipeline on success. The given pipeline string should be wrapped with
208+
/// the desired type of operation to root the created operation, i.e.
209+
/// `builtin.module(cse)` over `cse`. Returns failure if the given pipeline was
210+
/// invalid. 'errorStream' is the output stream used to emit errors found during
211+
/// parsing.
212+
FailureOr<OpPassManager>
213+
parsePassPipeline(StringRef pipeline, raw_ostream &errorStream = llvm::errs());
214+
207215
//===----------------------------------------------------------------------===//
208216
// PassPipelineCLParser
209217
//===----------------------------------------------------------------------===//

mlir/lib/Pass/PassRegistry.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -482,10 +482,6 @@ LogicalResult TextualPipeline::addToPipeline(
482482
return success();
483483
}
484484

485-
/// This function parses the textual representation of a pass pipeline, and adds
486-
/// the result to 'pm' on success. This function returns failure if the given
487-
/// pipeline was invalid. 'errorStream' is an optional parameter that, if
488-
/// non-null, will be used to emit errors found during parsing.
489485
LogicalResult mlir::parsePassPipeline(StringRef pipeline, OpPassManager &pm,
490486
raw_ostream &errorStream) {
491487
TextualPipeline pipelineParser;
@@ -500,6 +496,24 @@ LogicalResult mlir::parsePassPipeline(StringRef pipeline, OpPassManager &pm,
500496
return success();
501497
}
502498

499+
FailureOr<OpPassManager> mlir::parsePassPipeline(StringRef pipeline,
500+
raw_ostream &errorStream) {
501+
// Pipelines are expected to be of the form `<op-name>(<pipeline>)`.
502+
size_t pipelineStart = pipeline.find_first_of('(');
503+
if (pipelineStart == 0 || pipelineStart == StringRef::npos ||
504+
!pipeline.consume_back(")")) {
505+
errorStream << "expected pass pipeline to be wrapped with the anchor "
506+
"operation type, e.g. `builtin.module(...)";
507+
return failure();
508+
}
509+
510+
StringRef opName = pipeline.take_front(pipelineStart);
511+
OpPassManager pm(opName);
512+
if (failed(parsePassPipeline(pipeline.drop_front(1 + pipelineStart), pm)))
513+
return failure();
514+
return pm;
515+
}
516+
503517
//===----------------------------------------------------------------------===//
504518
// PassNameParser
505519
//===----------------------------------------------------------------------===//

mlir/lib/Transforms/Inliner.cpp

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -754,16 +754,10 @@ LogicalResult InlinerPass::initializeOptions(StringRef options) {
754754
// Skip empty pipelines.
755755
if (pipeline.empty())
756756
continue;
757-
758-
// Pipelines are expected to be of the form `<op-name>(<pipeline>)`.
759-
size_t pipelineStart = pipeline.find_first_of('(');
760-
if (pipelineStart == StringRef::npos || !pipeline.consume_back(")"))
761-
return failure();
762-
StringRef opName = pipeline.take_front(pipelineStart);
763-
OpPassManager pm(opName);
764-
if (failed(parsePassPipeline(pipeline.drop_front(1 + pipelineStart), pm)))
757+
FailureOr<OpPassManager> pm = parsePassPipeline(pipeline);
758+
if (failed(pm))
765759
return failure();
766-
pipelines.try_emplace(opName, std::move(pm));
760+
pipelines.try_emplace(pm->getOpName(), std::move(*pm));
767761
}
768762
opPipelines.assign({std::move(pipelines)});
769763

mlir/unittests/Pass/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
add_mlir_unittest(MLIRPassTests
22
AnalysisManagerTest.cpp
33
PassManagerTest.cpp
4+
PassPipelineParserTest.cpp
45
)
56
target_link_libraries(MLIRPassTests
67
PRIVATE
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//===- PassPipelineParserTest.cpp - Pass Parser unit tests ----------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "mlir/IR/Builders.h"
10+
#include "mlir/IR/BuiltinOps.h"
11+
#include "mlir/Pass/Pass.h"
12+
#include "mlir/Pass/PassManager.h"
13+
#include "mlir/Pass/PassRegistry.h"
14+
#include "llvm/Support/raw_ostream.h"
15+
#include "gtest/gtest.h"
16+
17+
#include <memory>
18+
19+
using namespace mlir;
20+
using namespace mlir::detail;
21+
22+
namespace {
23+
TEST(PassPipelineParserTest, InvalidOpAnchor) {
24+
// Helper functor used to parse a pipeline and check that it results in the
25+
// provided error message.
26+
auto checkParseFailure = [](StringRef pipeline, StringRef expectedErrorMsg) {
27+
std::string errorMsg;
28+
{
29+
llvm::raw_string_ostream os(errorMsg);
30+
FailureOr<OpPassManager> result = parsePassPipeline(pipeline, os);
31+
EXPECT_TRUE(failed(result));
32+
}
33+
EXPECT_TRUE(StringRef(errorMsg).contains(expectedErrorMsg));
34+
};
35+
36+
// Handle parse errors when the anchor is incorrectly structured.
37+
StringRef anchorErrorMsg =
38+
"expected pass pipeline to be wrapped with the anchor operation type";
39+
checkParseFailure("module", anchorErrorMsg);
40+
checkParseFailure("()", anchorErrorMsg);
41+
checkParseFailure("module(", anchorErrorMsg);
42+
checkParseFailure("module)", anchorErrorMsg);
43+
}
44+
45+
} // namespace

0 commit comments

Comments
 (0)