diff --git a/llvm/include/llvm/SandboxIR/PassManager.h b/llvm/include/llvm/SandboxIR/PassManager.h index 54192c6bf1333..247c43615f576 100644 --- a/llvm/include/llvm/SandboxIR/PassManager.h +++ b/llvm/include/llvm/SandboxIR/PassManager.h @@ -18,6 +18,8 @@ #ifndef LLVM_SANDBOXIR_PASSMANAGER_H #define LLVM_SANDBOXIR_PASSMANAGER_H +#include + #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" #include "llvm/SandboxIR/Pass.h" @@ -32,25 +34,65 @@ template class PassManager : public ParentPass { protected: /// The list of passes that this pass manager will run. - SmallVector Passes; + SmallVector> 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(ContainedPass *Pass) { + void addPass(std::unique_ptr Pass) { // TODO: Check that Pass's class type works with this PassManager type. - Passes.push_back(Pass); + Passes.push_back(std::move(Pass)); + } + + using CreatePassFunc = + std::function(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)); + } } + #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 { @@ -79,38 +121,6 @@ class RegionPassManager final : public PassManager { bool runOnRegion(Region &R) final; }; -/// Owns the passes and provides an API to get a pass by its name. -class PassRegistry { - SmallVector, 8> Passes; - DenseMap NameToPassMap; - -public: - static constexpr const char PassDelimToken = ','; - PassRegistry() = default; - /// Registers \p PassPtr and takes ownership. - Pass ®isterPass(std::unique_ptr &&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 a2108f07c28e5..02abdf0a1ef0d 100644 --- a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h +++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h @@ -15,18 +15,24 @@ #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 Bndl); void tryVectorize(ArrayRef Seeds); + // The PM containing the pipeline of region passes. + RegionPassManager RPM; + public: - BottomUpVec() : FunctionPass("bottom-up-vec") {} + BottomUpVec(); 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 new file mode 100644 index 0000000000000..75b9f42520156 --- /dev/null +++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/NullPass.h @@ -0,0 +1,19 @@ +#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 dd9f02d327264..1dcd976bf751c 100644 --- a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h +++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h @@ -8,7 +8,10 @@ #ifndef LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_SANDBOXVECTORIZER_H #define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_SANDBOXVECTORIZER_H +#include + #include "llvm/IR/PassManager.h" +#include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h" namespace llvm { @@ -17,10 +20,13 @@ class TargetTransformInfo; class SandboxVectorizerPass : public PassInfoMixin { TargetTransformInfo *TTI = nullptr; -public: - PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); + // The main vectorizer pass. + sandboxir::BottomUpVec BottomUpVecPass; bool runImpl(Function &F); + +public: + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; } // namespace llvm diff --git a/llvm/lib/SandboxIR/PassManager.cpp b/llvm/lib/SandboxIR/PassManager.cpp index 95bc5e56bb3ec..3a1cfa1d367a2 100644 --- a/llvm/lib/SandboxIR/PassManager.cpp +++ b/llvm/lib/SandboxIR/PassManager.cpp @@ -8,11 +8,11 @@ #include "llvm/SandboxIR/PassManager.h" -using namespace llvm::sandboxir; +namespace llvm::sandboxir { bool FunctionPassManager::runOnFunction(Function &F) { bool Change = false; - for (FunctionPass *Pass : Passes) { + for (auto &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 (RegionPass *Pass : Passes) { + for (auto &Pass : Passes) { Change |= Pass->runOnRegion(R); // TODO: run the verifier. } @@ -30,40 +30,4 @@ bool RegionPassManager::runOnRegion(Region &R) { return Change; } -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( - registerPass(std::make_unique("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(Pass)); - } - return InitialPM; -} -#ifndef NDEBUG -void PassRegistry::dump() const { - print(dbgs()); - dbgs() << "\n"; -} -#endif // NDEBUG +} // namespace llvm::sandboxir diff --git a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp index c59abd09d4362..77198f932a3ec 100644 --- a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp +++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp @@ -10,10 +10,41 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/SandboxIR/Function.h" #include "llvm/SandboxIR/Instruction.h" - -using namespace llvm::sandboxir; +#include "llvm/Support/CommandLine.h" +#include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/NullPass.h" namespace llvm::sandboxir { + +static cl::opt + 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 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 createRegionPass(StringRef Name) { +#define REGION_PASS(NAME, CREATE_PASS) \ + if (Name == NAME) \ + return std::make_unique(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); + } +} + // TODO: This is a temporary function that returns some seeds. // Replace this with SeedCollector's function when it lands. static llvm::SmallVector collectSeeds(BasicBlock &BB) { @@ -34,8 +65,6 @@ static SmallVector getOperand(ArrayRef Bndl, return Operands; } -} // namespace llvm::sandboxir - void BottomUpVec::vectorizeRec(ArrayRef Bndl) { auto LegalityRes = Legality.canVectorize(Bndl); switch (LegalityRes.getSubclassID()) { @@ -53,14 +82,23 @@ void BottomUpVec::vectorizeRec(ArrayRef Bndl) { void BottomUpVec::tryVectorize(ArrayRef 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 new file mode 100644 index 0000000000000..bbb0dcba1ea51 --- /dev/null +++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/PassRegistry.def @@ -0,0 +1,22 @@ +//===- 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 80afcb499a2c2..cbaf2b6288d92 100644 --- a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.cpp @@ -9,8 +9,6 @@ #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; @@ -18,18 +16,6 @@ using namespace llvm; #define SV_NAME "sandbox-vectorizer" #define DEBUG_TYPE SV_NAME -cl::opt - 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 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(F); @@ -56,31 +42,8 @@ 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); - // Create the passes and register them with the PassRegistry. - sandboxir::PassRegistry PR; - auto &BottomUpVecPass = static_cast( - PR.registerPass(std::make_unique())); - - sandboxir::FunctionPassManager *PM = nullptr; - if (UserDefinedPassPipeline == DefaultPipelineMagicStr) { - // Create the default pass pipeline. - PM = &static_cast(PR.registerPass( - std::make_unique("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; + return BottomUpVecPass.runOnFunction(F); } diff --git a/llvm/test/Transforms/SandboxVectorizer/default_pass_pipeline.ll b/llvm/test/Transforms/SandboxVectorizer/default_pass_pipeline.ll index 5ccd64d9f487a..86bfbee636478 100644 --- a/llvm/test/Transforms/SandboxVectorizer/default_pass_pipeline.ll +++ b/llvm/test/Transforms/SandboxVectorizer/default_pass_pipeline.ll @@ -4,8 +4,7 @@ ; This checks the default pass pipeline for the sandbox vectorizer. define void @pipeline() { -; CHECK: pm -; CHECK: bottom-up-vec +; CHECK: rpm ; 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 2879fbba1b9c0..2e6dab0aa29c7 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=bottom-up-vec,bottom-up-vec %s -disable-output | FileCheck %s +; RUN: opt -passes=sandbox-vectorizer -sbvec-print-pass-pipeline -sbvec-passes=null,null %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: pm -; CHECK: bottom-up-vec -; CHECK: bottom-up-vec +; CHECK: rpm +; CHECK: null +; CHECK: null ; CHECK-EMPTY: ret void } diff --git a/llvm/unittests/SandboxIR/PassTest.cpp b/llvm/unittests/SandboxIR/PassTest.cpp index b380ae9fd475a..ae7284ecf2deb 100644 --- a/llvm/unittests/SandboxIR/PassTest.cpp +++ b/llvm/unittests/SandboxIR/PassTest.cpp @@ -180,12 +180,10 @@ define void @foo() { }; unsigned BBCnt1 = 0; unsigned BBCnt2 = 0; - TestPass1 TPass1(BBCnt1); - TestPass2 TPass2(BBCnt2); FunctionPassManager FPM("test-fpm"); - FPM.addPass(&TPass1); - FPM.addPass(&TPass2); + FPM.addPass(std::make_unique(BBCnt1)); + FPM.addPass(std::make_unique(BBCnt2)); // Check runOnFunction(). FPM.runOnFunction(*F); EXPECT_EQ(BBCnt1, 1u); @@ -238,12 +236,10 @@ 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(&TPass1); - RPM.addPass(&TPass2); + RPM.addPass(std::make_unique(InstCount1)); + RPM.addPass(std::make_unique(InstCount2)); // Check runOnRegion(). llvm::SmallVector> Regions = Region::createRegionsFromMD(*F); @@ -260,62 +256,60 @@ define i8 @foo(i8 %v0, i8 %v1) { #endif // NDEBUG } -TEST_F(PassTest, PassRegistry) { - 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; } - }; - - PassRegistry Registry; - auto &TP1 = Registry.registerPass(std::make_unique()); - auto &TP2 = Registry.registerPass(std::make_unique()); - - // 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, SetPassPipeline) { + auto *F = parseFunction(R"IR( +define void @f() { + ret void } +)IR", + "f"); + class FooPass final : public FunctionPass { + std::string &Str; -TEST_F(PassTest, ParsePassPipeline) { - class TestPass1 final : public FunctionPass { public: - TestPass1() : FunctionPass("test-pass1") {} - bool runOnFunction(Function &F) final { return false; } + FooPass(std::string &Str) : FunctionPass("foo-pass"), Str(Str) {} + bool runOnFunction(Function &F) final { + Str += "foo"; + return false; + } }; - class TestPass2 final : public FunctionPass { + class BarPass final : public FunctionPass { + std::string &Str; + public: - TestPass2() : FunctionPass("test-pass2") {} - bool runOnFunction(Function &F) final { return false; } + BarPass(std::string &Str) : FunctionPass("bar-pass"), Str(Str) {} + bool runOnFunction(Function &F) final { + Str += "bar"; + return false; + } }; - PassRegistry Registry; - Registry.registerPass(std::make_unique()); - Registry.registerPass(std::make_unique()); + std::string Str; + auto CreatePass = + [&Str](llvm::StringRef Name) -> std::unique_ptr { + if (Name == "foo") + return std::make_unique(Str); + if (Name == "bar") + return std::make_unique(Str); + return nullptr; + }; - [[maybe_unused]] auto &FPM = - Registry.parseAndCreatePassPipeline("test-pass1,test-pass2,test-pass1"); + FunctionPassManager FPM("test-fpm"); + FPM.setPassPipeline("foo,bar,foo", CreatePass); + FPM.runOnFunction(*F); + EXPECT_EQ(Str, "foobarfoo"); + + // A second call to setPassPipeline will trigger an assertion in debug mode. #ifndef NDEBUG - 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 + EXPECT_DEATH(FPM.setPassPipeline("bar,bar,foo", CreatePass), + "setPassPipeline called on a non-empty sandboxir::PassManager"); +#endif - EXPECT_DEATH(Registry.parseAndCreatePassPipeline("bad-pass-name"), + // 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), ".*not registered.*"); - EXPECT_DEATH(Registry.parseAndCreatePassPipeline(""), ".*not registered.*"); - EXPECT_DEATH(Registry.parseAndCreatePassPipeline(","), ".*not registered.*"); + EXPECT_DEATH(FPM2.setPassPipeline("", CreatePass), ".*not registered.*"); + EXPECT_DEATH(FPM2.setPassPipeline(",", CreatePass), ".*not registered.*"); }