Author: Jorge Gorbe Moya Date: 2024-10-09T10:44:19-07:00 New Revision: cee0873fc83beb441a27b1f0555da54e56aa0910
URL: https://github.com/llvm/llvm-project/commit/cee0873fc83beb441a27b1f0555da54e56aa0910 DIFF: https://github.com/llvm/llvm-project/commit/cee0873fc83beb441a27b1f0555da54e56aa0910.diff LOG: Revert "[SandboxVectorizer] Use sbvec-passes flag to create a pipeline of Reg…" This reverts commit 10ada4ae738b9d93174e516ca841e61a8f4fd612. Added: Modified: llvm/include/llvm/SandboxIR/PassManager.h llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h llvm/lib/SandboxIR/PassManager.cpp llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.cpp llvm/test/Transforms/SandboxVectorizer/default_pass_pipeline.ll llvm/test/Transforms/SandboxVectorizer/user_pass_pipeline.ll llvm/unittests/SandboxIR/PassTest.cpp Removed: llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/NullPass.h llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/PassRegistry.def ################################################################################ diff --git a/llvm/include/llvm/SandboxIR/PassManager.h b/llvm/include/llvm/SandboxIR/PassManager.h index 247c43615f5766..54192c6bf1333b 100644 --- a/llvm/include/llvm/SandboxIR/PassManager.h +++ b/llvm/include/llvm/SandboxIR/PassManager.h @@ -18,8 +18,6 @@ #ifndef LLVM_SANDBOXIR_PASSMANAGER_H #define LLVM_SANDBOXIR_PASSMANAGER_H -#include <memory> - #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" #include "llvm/SandboxIR/Pass.h" @@ -34,65 +32,25 @@ template <typename ParentPass, typename ContainedPass> class PassManager : public ParentPass { protected: /// The list of passes that this pass manager will run. - SmallVector<std::unique_ptr<ContainedPass>> Passes; + SmallVector<ContainedPass *> Passes; PassManager(StringRef Name) : ParentPass(Name) {} PassManager(const PassManager &) = delete; - PassManager(PassManager &&) = default; virtual ~PassManager() = default; PassManager &operator=(const PassManager &) = delete; public: /// Adds \p Pass to the pass pipeline. - void addPass(std::unique_ptr<ContainedPass> Pass) { + void addPass(ContainedPass *Pass) { // TODO: Check that Pass's class type works with this PassManager type. - Passes.push_back(std::move(Pass)); - } - - using CreatePassFunc = - std::function<std::unique_ptr<ContainedPass>(StringRef)>; - - /// Parses \p Pipeline as a comma-separated sequence of pass names and sets - /// the pass pipeline, using \p CreatePass to instantiate passes by name. - /// - /// After calling this function, the PassManager contains only the specified - /// pipeline, any previously added passes are cleared. - void setPassPipeline(StringRef Pipeline, CreatePassFunc CreatePass) { - static constexpr const char EndToken = '\0'; - static constexpr const char PassDelimToken = ','; - - assert(Passes.empty() && - "setPassPipeline called on a non-empty sandboxir::PassManager"); - // Add EndToken to the end to ease parsing. - std::string PipelineStr = std::string(Pipeline) + EndToken; - int FlagBeginIdx = 0; - - for (auto [Idx, C] : enumerate(PipelineStr)) { - // Keep moving Idx until we find the end of the pass name. - bool FoundDelim = C == EndToken || C == PassDelimToken; - if (!FoundDelim) - continue; - unsigned Sz = Idx - FlagBeginIdx; - std::string PassName(&PipelineStr[FlagBeginIdx], Sz); - FlagBeginIdx = Idx + 1; - - // Get the pass that corresponds to PassName and add it to the pass - // manager. - auto Pass = CreatePass(PassName); - if (Pass == nullptr) { - errs() << "Pass '" << PassName << "' not registered!\n"; - exit(1); - } - addPass(std::move(Pass)); - } + Passes.push_back(Pass); } - #ifndef NDEBUG void print(raw_ostream &OS) const override { OS << this->getName(); OS << "("; // TODO: This should call Pass->print(OS) because Pass may be a PM. - interleave(Passes, OS, [&OS](auto &Pass) { OS << Pass->getName(); }, ","); + interleave(Passes, OS, [&OS](auto *Pass) { OS << Pass->getName(); }, ","); OS << ")"; } LLVM_DUMP_METHOD void dump() const override { @@ -121,6 +79,38 @@ class RegionPassManager final : public PassManager<RegionPass, RegionPass> { bool runOnRegion(Region &R) final; }; +/// Owns the passes and provides an API to get a pass by its name. +class PassRegistry { + SmallVector<std::unique_ptr<Pass>, 8> Passes; + DenseMap<StringRef, Pass *> NameToPassMap; + +public: + static constexpr const char PassDelimToken = ','; + PassRegistry() = default; + /// Registers \p PassPtr and takes ownership. + Pass ®isterPass(std::unique_ptr<Pass> &&PassPtr) { + auto &PassRef = *PassPtr.get(); + NameToPassMap[PassRef.getName()] = &PassRef; + Passes.push_back(std::move(PassPtr)); + return PassRef; + } + /// \Returns the pass with name \p Name, or null if not registered. + Pass *getPassByName(StringRef Name) const { + auto It = NameToPassMap.find(Name); + return It != NameToPassMap.end() ? It->second : nullptr; + } + /// Creates a pass pipeline and returns the first pass manager. + FunctionPassManager &parseAndCreatePassPipeline(StringRef Pipeline); + +#ifndef NDEBUG + void print(raw_ostream &OS) const { + for (const auto &PassPtr : Passes) + OS << PassPtr->getName() << "\n"; + } + LLVM_DUMP_METHOD void dump() const; +#endif +}; + } // namespace llvm::sandboxir #endif // LLVM_SANDBOXIR_PASSMANAGER_H diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h index 02abdf0a1ef0df..a2108f07c28e50 100644 --- a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h +++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h @@ -15,24 +15,18 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/SandboxIR/Constant.h" #include "llvm/SandboxIR/Pass.h" -#include "llvm/SandboxIR/PassManager.h" #include "llvm/Transforms/Vectorize/SandboxVectorizer/Legality.h" namespace llvm::sandboxir { -class RegionPassManager; - class BottomUpVec final : public FunctionPass { bool Change = false; LegalityAnalysis Legality; void vectorizeRec(ArrayRef<Value *> Bndl); void tryVectorize(ArrayRef<Value *> Seeds); - // The PM containing the pipeline of region passes. - RegionPassManager RPM; - public: - BottomUpVec(); + BottomUpVec() : FunctionPass("bottom-up-vec") {} bool runOnFunction(Function &F) final; }; diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/NullPass.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/NullPass.h deleted file mode 100644 index 75b9f42520156c..00000000000000 --- a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/NullPass.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_PASSES_NULLPASS_H -#define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_PASSES_NULLPASS_H - -#include "llvm/SandboxIR/Pass.h" - -namespace llvm::sandboxir { - -class Region; - -/// A Region pass that does nothing, for use as a placeholder in tests. -class NullPass final : public RegionPass { -public: - NullPass() : RegionPass("null") {} - bool runOnRegion(Region &R) final { return false; } -}; - -} // namespace llvm::sandboxir - -#endif // LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_PASSES_NULLPASS_H diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h index 1dcd976bf751c5..dd9f02d3272643 100644 --- a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h +++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h @@ -8,10 +8,7 @@ #ifndef LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_SANDBOXVECTORIZER_H #define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_SANDBOXVECTORIZER_H -#include <memory> - #include "llvm/IR/PassManager.h" -#include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h" namespace llvm { @@ -20,13 +17,10 @@ class TargetTransformInfo; class SandboxVectorizerPass : public PassInfoMixin<SandboxVectorizerPass> { TargetTransformInfo *TTI = nullptr; - // The main vectorizer pass. - sandboxir::BottomUpVec BottomUpVecPass; - - bool runImpl(Function &F); - public: PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); + + bool runImpl(Function &F); }; } // namespace llvm diff --git a/llvm/lib/SandboxIR/PassManager.cpp b/llvm/lib/SandboxIR/PassManager.cpp index 3a1cfa1d367a2a..95bc5e56bb3ec9 100644 --- a/llvm/lib/SandboxIR/PassManager.cpp +++ b/llvm/lib/SandboxIR/PassManager.cpp @@ -8,11 +8,11 @@ #include "llvm/SandboxIR/PassManager.h" -namespace llvm::sandboxir { +using namespace llvm::sandboxir; bool FunctionPassManager::runOnFunction(Function &F) { bool Change = false; - for (auto &Pass : Passes) { + for (FunctionPass *Pass : Passes) { Change |= Pass->runOnFunction(F); // TODO: run the verifier. } @@ -22,7 +22,7 @@ bool FunctionPassManager::runOnFunction(Function &F) { bool RegionPassManager::runOnRegion(Region &R) { bool Change = false; - for (auto &Pass : Passes) { + for (RegionPass *Pass : Passes) { Change |= Pass->runOnRegion(R); // TODO: run the verifier. } @@ -30,4 +30,40 @@ bool RegionPassManager::runOnRegion(Region &R) { return Change; } -} // namespace llvm::sandboxir +FunctionPassManager & +PassRegistry::parseAndCreatePassPipeline(StringRef Pipeline) { + static constexpr const char EndToken = '\0'; + // Add EndToken to the end to ease parsing. + std::string PipelineStr = std::string(Pipeline) + EndToken; + int FlagBeginIdx = 0; + // Start with a FunctionPassManager. + auto &InitialPM = static_cast<FunctionPassManager &>( + registerPass(std::make_unique<FunctionPassManager>("init-fpm"))); + + for (auto [Idx, C] : enumerate(PipelineStr)) { + // Keep moving Idx until we find the end of the pass name. + bool FoundDelim = C == EndToken || C == PassDelimToken; + if (!FoundDelim) + continue; + unsigned Sz = Idx - FlagBeginIdx; + std::string PassName(&PipelineStr[FlagBeginIdx], Sz); + FlagBeginIdx = Idx + 1; + + // Get the pass that corresponds to PassName and add it to the pass manager. + auto *Pass = getPassByName(PassName); + if (Pass == nullptr) { + errs() << "Pass '" << PassName << "' not registered!\n"; + exit(1); + } + // TODO: This is safe for now, but would require proper upcasting once we + // add more Pass sub-classes. + InitialPM.addPass(static_cast<FunctionPass *>(Pass)); + } + return InitialPM; +} +#ifndef NDEBUG +void PassRegistry::dump() const { + print(dbgs()); + dbgs() << "\n"; +} +#endif // NDEBUG diff --git a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp index 77198f932a3ec0..c59abd09d43629 100644 --- a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp +++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp @@ -10,41 +10,10 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/SandboxIR/Function.h" #include "llvm/SandboxIR/Instruction.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/NullPass.h" -namespace llvm::sandboxir { - -static cl::opt<bool> - PrintPassPipeline("sbvec-print-pass-pipeline", cl::init(false), cl::Hidden, - cl::desc("Prints the pass pipeline and returns.")); - -/// A magic string for the default pass pipeline. -static const char *DefaultPipelineMagicStr = "*"; - -static cl::opt<std::string> UserDefinedPassPipeline( - "sbvec-passes", cl::init(DefaultPipelineMagicStr), cl::Hidden, - cl::desc("Comma-separated list of vectorizer passes. If not set " - "we run the predefined pipeline.")); - -static std::unique_ptr<RegionPass> createRegionPass(StringRef Name) { -#define REGION_PASS(NAME, CREATE_PASS) \ - if (Name == NAME) \ - return std::make_unique<decltype(CREATE_PASS)>(CREATE_PASS); -#include "PassRegistry.def" - return nullptr; -} - -BottomUpVec::BottomUpVec() : FunctionPass("bottom-up-vec"), RPM("rpm") { - // Create a pipeline to be run on each Region created by BottomUpVec. - if (UserDefinedPassPipeline == DefaultPipelineMagicStr) { - // TODO: Add default passes to RPM. - } else { - // Create the user-defined pipeline. - RPM.setPassPipeline(UserDefinedPassPipeline, createRegionPass); - } -} +using namespace llvm::sandboxir; +namespace llvm::sandboxir { // TODO: This is a temporary function that returns some seeds. // Replace this with SeedCollector's function when it lands. static llvm::SmallVector<Value *, 4> collectSeeds(BasicBlock &BB) { @@ -65,6 +34,8 @@ static SmallVector<Value *, 4> getOperand(ArrayRef<Value *> Bndl, return Operands; } +} // namespace llvm::sandboxir + void BottomUpVec::vectorizeRec(ArrayRef<Value *> Bndl) { auto LegalityRes = Legality.canVectorize(Bndl); switch (LegalityRes.getSubclassID()) { @@ -82,23 +53,14 @@ void BottomUpVec::vectorizeRec(ArrayRef<Value *> Bndl) { void BottomUpVec::tryVectorize(ArrayRef<Value *> Bndl) { vectorizeRec(Bndl); } bool BottomUpVec::runOnFunction(Function &F) { - if (PrintPassPipeline) { - RPM.printPipeline(outs()); - return false; - } - Change = false; // TODO: Start from innermost BBs first for (auto &BB : F) { // TODO: Replace with proper SeedCollector function. auto Seeds = collectSeeds(BB); // TODO: Slice Seeds into smaller chunks. - // TODO: If vectorization succeeds, run the RegionPassManager on the - // resulting region. if (Seeds.size() >= 2) tryVectorize(Seeds); } return Change; } - -} // namespace llvm::sandboxir diff --git a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/PassRegistry.def b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/PassRegistry.def deleted file mode 100644 index bbb0dcba1ea516..00000000000000 --- a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/PassRegistry.def +++ /dev/null @@ -1,22 +0,0 @@ -//===- PassRegistry.def - Registry of passes --------------------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// This file is used as the registry of sub-passes that are part of the -// SandboxVectorizer pass. -// -//===----------------------------------------------------------------------===// - -// NOTE: NO INCLUDE GUARD DESIRED! - -#ifndef REGION_PASS -#define REGION_PASS(NAME, CREATE_PASS) -#endif - -REGION_PASS("null", NullPass()) - -#undef REGION_PASS diff --git a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.cpp index cbaf2b6288d928..80afcb499a2c22 100644 --- a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.cpp @@ -9,6 +9,8 @@ #include "llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/SandboxIR/Constant.h" +#include "llvm/SandboxIR/PassManager.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h" using namespace llvm; @@ -16,6 +18,18 @@ using namespace llvm; #define SV_NAME "sandbox-vectorizer" #define DEBUG_TYPE SV_NAME +cl::opt<bool> + PrintPassPipeline("sbvec-print-pass-pipeline", cl::init(false), cl::Hidden, + cl::desc("Prints the pass pipeline and returns.")); + +/// A magic string for the default pass pipeline. +const char *DefaultPipelineMagicStr = "*"; + +cl::opt<std::string> UserDefinedPassPipeline( + "sbvec-passes", cl::init(DefaultPipelineMagicStr), cl::Hidden, + cl::desc("Comma-separated list of vectorizer passes. If not set " + "we run the predefined pipeline.")); + PreservedAnalyses SandboxVectorizerPass::run(Function &F, FunctionAnalysisManager &AM) { TTI = &AM.getResult<TargetIRAnalysis>(F); @@ -42,8 +56,31 @@ bool SandboxVectorizerPass::runImpl(Function &LLVMF) { return false; } - // Create SandboxIR for LLVMF and run BottomUpVec on it. sandboxir::Context Ctx(LLVMF.getContext()); + // Create SandboxIR for `LLVMF`. sandboxir::Function &F = *Ctx.createFunction(&LLVMF); - return BottomUpVecPass.runOnFunction(F); + // Create the passes and register them with the PassRegistry. + sandboxir::PassRegistry PR; + auto &BottomUpVecPass = static_cast<sandboxir::FunctionPass &>( + PR.registerPass(std::make_unique<sandboxir::BottomUpVec>())); + + sandboxir::FunctionPassManager *PM = nullptr; + if (UserDefinedPassPipeline == DefaultPipelineMagicStr) { + // Create the default pass pipeline. + PM = &static_cast<sandboxir::FunctionPassManager &>(PR.registerPass( + std::make_unique<sandboxir::FunctionPassManager>("pm"))); + PM->addPass(&BottomUpVecPass); + } else { + // Create the user-defined pipeline. + PM = &PR.parseAndCreatePassPipeline(UserDefinedPassPipeline); + } + + if (PrintPassPipeline) { + PM->printPipeline(outs()); + return false; + } + + // Run the pass pipeline. + bool Change = PM->runOnFunction(F); + return Change; } diff --git a/llvm/test/Transforms/SandboxVectorizer/default_pass_pipeline.ll b/llvm/test/Transforms/SandboxVectorizer/default_pass_pipeline.ll index 86bfbee6364788..5ccd64d9f487a3 100644 --- a/llvm/test/Transforms/SandboxVectorizer/default_pass_pipeline.ll +++ b/llvm/test/Transforms/SandboxVectorizer/default_pass_pipeline.ll @@ -4,7 +4,8 @@ ; This checks the default pass pipeline for the sandbox vectorizer. define void @pipeline() { -; CHECK: rpm +; CHECK: pm +; CHECK: bottom-up-vec ; CHECK-EMPTY: ret void } diff --git a/llvm/test/Transforms/SandboxVectorizer/user_pass_pipeline.ll b/llvm/test/Transforms/SandboxVectorizer/user_pass_pipeline.ll index 2e6dab0aa29c74..2879fbba1b9c00 100644 --- a/llvm/test/Transforms/SandboxVectorizer/user_pass_pipeline.ll +++ b/llvm/test/Transforms/SandboxVectorizer/user_pass_pipeline.ll @@ -1,12 +1,12 @@ -; RUN: opt -passes=sandbox-vectorizer -sbvec-print-pass-pipeline -sbvec-passes=null,null %s -disable-output | FileCheck %s +; RUN: opt -passes=sandbox-vectorizer -sbvec-print-pass-pipeline -sbvec-passes=bottom-up-vec,bottom-up-vec %s -disable-output | FileCheck %s ; !!!WARNING!!! This won't get updated by update_test_checks.py ! ; This checks the user defined pass pipeline. define void @pipeline() { -; CHECK: rpm -; CHECK: null -; CHECK: null +; CHECK: pm +; CHECK: bottom-up-vec +; CHECK: bottom-up-vec ; CHECK-EMPTY: ret void } diff --git a/llvm/unittests/SandboxIR/PassTest.cpp b/llvm/unittests/SandboxIR/PassTest.cpp index ae7284ecf2deb9..b380ae9fd475ab 100644 --- a/llvm/unittests/SandboxIR/PassTest.cpp +++ b/llvm/unittests/SandboxIR/PassTest.cpp @@ -180,10 +180,12 @@ define void @foo() { }; unsigned BBCnt1 = 0; unsigned BBCnt2 = 0; + TestPass1 TPass1(BBCnt1); + TestPass2 TPass2(BBCnt2); FunctionPassManager FPM("test-fpm"); - FPM.addPass(std::make_unique<TestPass1>(BBCnt1)); - FPM.addPass(std::make_unique<TestPass2>(BBCnt2)); + FPM.addPass(&TPass1); + FPM.addPass(&TPass2); // Check runOnFunction(). FPM.runOnFunction(*F); EXPECT_EQ(BBCnt1, 1u); @@ -236,10 +238,12 @@ define i8 @foo(i8 %v0, i8 %v1) { }; unsigned InstCount1 = 0; unsigned InstCount2 = 0; + TestPass1 TPass1(InstCount1); + TestPass2 TPass2(InstCount2); RegionPassManager RPM("test-rpm"); - RPM.addPass(std::make_unique<TestPass1>(InstCount1)); - RPM.addPass(std::make_unique<TestPass2>(InstCount2)); + RPM.addPass(&TPass1); + RPM.addPass(&TPass2); // Check runOnRegion(). llvm::SmallVector<std::unique_ptr<Region>> Regions = Region::createRegionsFromMD(*F); @@ -256,60 +260,62 @@ define i8 @foo(i8 %v0, i8 %v1) { #endif // NDEBUG } -TEST_F(PassTest, SetPassPipeline) { - auto *F = parseFunction(R"IR( -define void @f() { - ret void -} -)IR", - "f"); - class FooPass final : public FunctionPass { - std::string &Str; - +TEST_F(PassTest, PassRegistry) { + class TestPass1 final : public FunctionPass { public: - FooPass(std::string &Str) : FunctionPass("foo-pass"), Str(Str) {} - bool runOnFunction(Function &F) final { - Str += "foo"; - return false; - } + TestPass1() : FunctionPass("test-pass1") {} + bool runOnFunction(Function &F) final { return false; } }; - class BarPass final : public FunctionPass { - std::string &Str; - + class TestPass2 final : public FunctionPass { public: - BarPass(std::string &Str) : FunctionPass("bar-pass"), Str(Str) {} - bool runOnFunction(Function &F) final { - Str += "bar"; - return false; - } + TestPass2() : FunctionPass("test-pass2") {} + bool runOnFunction(Function &F) final { return false; } }; - std::string Str; - auto CreatePass = - [&Str](llvm::StringRef Name) -> std::unique_ptr<FunctionPass> { - if (Name == "foo") - return std::make_unique<FooPass>(Str); - if (Name == "bar") - return std::make_unique<BarPass>(Str); - return nullptr; + PassRegistry Registry; + auto &TP1 = Registry.registerPass(std::make_unique<TestPass1>()); + auto &TP2 = Registry.registerPass(std::make_unique<TestPass2>()); + + // Check getPassByName(). + EXPECT_EQ(Registry.getPassByName("test-pass1"), &TP1); + EXPECT_EQ(Registry.getPassByName("test-pass2"), &TP2); + +#ifndef NDEBUG + // Check print(). + std::string Buff; + llvm::raw_string_ostream SS(Buff); + Registry.print(SS); + EXPECT_EQ(Buff, "test-pass1\ntest-pass2\n"); +#endif // NDEBUG +} + +TEST_F(PassTest, ParsePassPipeline) { + class TestPass1 final : public FunctionPass { + public: + TestPass1() : FunctionPass("test-pass1") {} + bool runOnFunction(Function &F) final { return false; } + }; + class TestPass2 final : public FunctionPass { + public: + TestPass2() : FunctionPass("test-pass2") {} + bool runOnFunction(Function &F) final { return false; } }; - FunctionPassManager FPM("test-fpm"); - FPM.setPassPipeline("foo,bar,foo", CreatePass); - FPM.runOnFunction(*F); - EXPECT_EQ(Str, "foobarfoo"); + PassRegistry Registry; + Registry.registerPass(std::make_unique<TestPass1>()); + Registry.registerPass(std::make_unique<TestPass2>()); - // A second call to setPassPipeline will trigger an assertion in debug mode. + [[maybe_unused]] auto &FPM = + Registry.parseAndCreatePassPipeline("test-pass1,test-pass2,test-pass1"); #ifndef NDEBUG - EXPECT_DEATH(FPM.setPassPipeline("bar,bar,foo", CreatePass), - "setPassPipeline called on a non-empty sandboxir::PassManager"); -#endif + std::string Buff; + llvm::raw_string_ostream SS(Buff); + FPM.print(SS); + EXPECT_EQ(Buff, "init-fpm(test-pass1,test-pass2,test-pass1)"); +#endif // NDEBUG - // Fresh PM for the death tests so they die from bad pipeline strings, rather - // than from multiple setPassPipeline calls. - FunctionPassManager FPM2("test-fpm"); - EXPECT_DEATH(FPM2.setPassPipeline("bad-pass-name", CreatePass), + EXPECT_DEATH(Registry.parseAndCreatePassPipeline("bad-pass-name"), ".*not registered.*"); - EXPECT_DEATH(FPM2.setPassPipeline("", CreatePass), ".*not registered.*"); - EXPECT_DEATH(FPM2.setPassPipeline(",", CreatePass), ".*not registered.*"); + EXPECT_DEATH(Registry.parseAndCreatePassPipeline(""), ".*not registered.*"); + EXPECT_DEATH(Registry.parseAndCreatePassPipeline(","), ".*not registered.*"); } _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits