Skip to content

Commit 52c5f72

Browse files
committed
[passmanager] Change SIL pass pipeline plan to use an LLVM YAML representation.
This eliminates a bunch of code and will make it significantly easier to maintain/add to this code/use this code.
1 parent c584ebd commit 52c5f72

File tree

4 files changed

+85
-88
lines changed

4 files changed

+85
-88
lines changed

lib/SILOptimizer/PassManager/PassPipeline.cpp

Lines changed: 64 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -755,82 +755,82 @@ SILPassPipelinePlan::getPassPipelineForKinds(const SILOptions &Options,
755755
// Dumping And Loading Pass Pipelines from Yaml
756756
//===----------------------------------------------------------------------===//
757757

758+
namespace {
759+
760+
struct YAMLPassPipeline {
761+
std::string name;
762+
std::vector<PassKind> passes;
763+
764+
YAMLPassPipeline() {}
765+
YAMLPassPipeline(const SILPassPipeline &pipeline,
766+
SILPassPipelinePlan::PipelineKindRange pipelineKinds)
767+
: name(pipeline.Name), passes() {
768+
llvm::copy(pipelineKinds, std::back_inserter(passes));
769+
}
770+
};
771+
772+
} // end anonymous namespace
773+
774+
namespace llvm {
775+
namespace yaml {
776+
777+
template <> struct ScalarEnumerationTraits<PassKind> {
778+
static void enumeration(IO &io, PassKind &value) {
779+
#define PASS(ID, TAG, NAME) io.enumCase(value, #TAG, PassKind::ID);
780+
#include "swift/SILOptimizer/PassManager/Passes.def"
781+
}
782+
};
783+
784+
template <> struct MappingTraits<YAMLPassPipeline> {
785+
static void mapping(IO &io, YAMLPassPipeline &info) {
786+
io.mapRequired("name", info.name);
787+
io.mapRequired("passes", info.passes);
788+
}
789+
};
790+
791+
} // namespace yaml
792+
} // namespace llvm
793+
794+
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(PassKind)
795+
LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(YAMLPassPipeline)
796+
758797
void SILPassPipelinePlan::dump() {
759798
print(llvm::errs());
760799
llvm::errs() << '\n';
761800
}
762801

763802
void SILPassPipelinePlan::print(llvm::raw_ostream &os) {
764-
// Our pipelines yaml representation is simple, we just output it ourselves
765-
// rather than use the yaml writer interface. We want to use the yaml reader
766-
// interface to be resilient against slightly different forms of yaml.
767-
os << "[\n";
768-
interleave(getPipelines(),
769-
[&](const SILPassPipeline &Pipeline) {
770-
os << " [\n";
771-
772-
os << " \"" << Pipeline.Name << "\"";
773-
for (PassKind Kind : getPipelinePasses(Pipeline)) {
774-
os << ",\n [\"" << PassKindID(Kind) << "\","
775-
<< "\"" << PassKindTag(Kind) << "\"]";
776-
}
777-
},
778-
[&] { os << "\n ],\n"; });
779-
os << "\n ]\n";
780-
os << ']';
803+
llvm::yaml::Output out(os);
804+
std::vector<YAMLPassPipeline> data;
805+
transform(getPipelines(), std::back_inserter(data),
806+
[&](const SILPassPipeline &pipeline) {
807+
return YAMLPassPipeline(pipeline, getPipelinePasses(pipeline));
808+
});
809+
out << data;
781810
}
782811

783812
SILPassPipelinePlan
784-
SILPassPipelinePlan::getPassPipelineFromFile(const SILOptions &Options,
785-
StringRef Filename) {
786-
namespace yaml = llvm::yaml;
787-
LLVM_DEBUG(llvm::dbgs() << "Parsing Pass Pipeline from " << Filename << "\n");
788-
789-
// Load the input file.
790-
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
791-
llvm::MemoryBuffer::getFileOrSTDIN(Filename);
792-
if (!FileBufOrErr) {
793-
llvm_unreachable("Failed to read yaml file");
794-
}
795-
796-
StringRef Buffer = FileBufOrErr->get()->getBuffer();
797-
llvm::SourceMgr SM;
798-
yaml::Stream Stream(Buffer, SM);
799-
yaml::document_iterator DI = Stream.begin();
800-
assert(DI != Stream.end() && "Failed to read a document");
801-
yaml::Node *N = DI->getRoot();
802-
assert(N && "Failed to find a root");
813+
SILPassPipelinePlan::getPassPipelineFromFile(const SILOptions &options,
814+
StringRef filename) {
815+
std::vector<YAMLPassPipeline> yamlPipelines;
816+
{
817+
// Load the input file.
818+
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileBufOrErr =
819+
llvm::MemoryBuffer::getFileOrSTDIN(filename);
820+
if (!fileBufOrErr) {
821+
llvm_unreachable("Failed to read yaml file");
822+
}
803823

804-
SILPassPipelinePlan P(Options);
824+
llvm::yaml::Input in(fileBufOrErr->get()->getBuffer());
825+
in >> yamlPipelines;
826+
}
805827

806-
auto *RootList = cast<yaml::SequenceNode>(N);
807-
llvm::SmallVector<PassKind, 32> Passes;
808-
for (yaml::Node &PipelineNode :
809-
make_range(RootList->begin(), RootList->end())) {
810-
Passes.clear();
811-
LLVM_DEBUG(llvm::dbgs() << "New Pipeline:\n");
812-
813-
auto *Desc = cast<yaml::SequenceNode>(&PipelineNode);
814-
yaml::SequenceNode::iterator DescIter = Desc->begin();
815-
StringRef Name = cast<yaml::ScalarNode>(&*DescIter)->getRawValue();
816-
LLVM_DEBUG(llvm::dbgs() << " Name: \"" << Name << "\"\n");
817-
++DescIter;
818-
819-
for (auto DescEnd = Desc->end(); DescIter != DescEnd; ++DescIter) {
820-
auto *InnerPassList = cast<yaml::SequenceNode>(&*DescIter);
821-
auto *FirstNode = &*InnerPassList->begin();
822-
StringRef PassName = cast<yaml::ScalarNode>(FirstNode)->getRawValue();
823-
unsigned Size = PassName.size() - 2;
824-
PassName = PassName.substr(1, Size);
825-
LLVM_DEBUG(llvm::dbgs() << " Pass: \"" << PassName << "\"\n");
826-
auto Kind = PassKindFromString(PassName);
827-
assert(Kind != PassKind::invalidPassKind && "Found invalid pass kind?!");
828-
Passes.push_back(Kind);
829-
}
828+
SILPassPipelinePlan silPlan(options);
830829

831-
P.startPipeline(Name);
832-
P.addPasses(Passes);
830+
for (auto &pipeline : yamlPipelines) {
831+
silPlan.startPipeline(pipeline.name);
832+
silPlan.addPasses(pipeline.passes);
833833
}
834834

835-
return P;
835+
return silPlan;
836836
}

lib/Serialization/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ add_swift_host_library(swiftSerialization STATIC
1212
BitstreamReader
1313
)
1414
target_link_libraries(swiftSerialization PRIVATE
15-
swiftClangImporter)
15+
swiftClangImporter
16+
swiftSIL)
1617

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
// RUN: %sil-passpipeline-dumper -Onone | %FileCheck %s
2-
// RUN: %sil-passpipeline-dumper -Onone | %{python} -c 'import json; import sys; json.load(sys.stdin)'
32

4-
// CHECK: [
5-
// CHECK: [
6-
// CHECK: "Serialization",
7-
// CHECK: ["SerializeSILPass","serialize-sil"]
8-
// CHECK: ],
9-
// CHECK: [
10-
// CHECK: "Rest of Onone",
11-
// CHECK: ["UsePrespecialized","use-prespecialized"],
12-
// CHECK: ["AssumeSingleThreaded","sil-assume-single-threaded"],
13-
// CHECK: ["SILDebugInfoGenerator","sil-debuginfo-gen"]
14-
// CHECK: ]
15-
// CHECK: ]
3+
// CHECK: ---
4+
// CHECK: name: Mandatory Combines
5+
// CHECK: passes: [ "for-each-loop-unroll", "mandatory-combine" ]
6+
// CHECK: ---
7+
// CHECK: name: Serialization
8+
// CHECK: passes: [ "serialize-sil", "ownership-model-eliminator" ]
9+
// CHECK: ---
10+
// CHECK: name: Rest of Onone
11+
// CHECK: passes: [ "use-prespecialized", "sil-assume-single-threaded",
12+
// CHECK: "sil-debuginfo-gen" ]
13+
// CHECK: ...

tools/sil-passpipeline-dumper/CMakeLists.txt

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@ add_swift_host_tool(sil-passpipeline-dumper
22
SILPassPipelineDumper.cpp
33
SWIFT_COMPONENT tools
44
)
5-
target_link_libraries(sil-passpipeline-dumper
6-
PRIVATE
7-
swiftClangImporter
8-
swiftFrontend
9-
swiftSerialization
10-
swiftSILGen
11-
swiftSILOptimizer
12-
# FIXME: Circular dependencies require re-listing these libraries.
13-
swiftAST
14-
swiftSema)
5+
target_link_libraries(sil-passpipeline-dumper PRIVATE
6+
swiftFrontend
7+
swiftIRGen
8+
swiftSILGen
9+
swiftSILOptimizer
10+
# Clang libraries included to appease the linker on linux.
11+
clangBasic
12+
clangCodeGen)

0 commit comments

Comments
 (0)