366 changes: 211 additions & 155 deletions llvm/lib/Passes/PassBuilder.cpp

Large diffs are not rendered by default.

83 changes: 66 additions & 17 deletions llvm/test/Other/pass-pipeline-parsing.ll
Original file line number Diff line number Diff line change
Expand Up @@ -54,52 +54,52 @@
; RUN: not opt -disable-output -debug-pass-manager \
; RUN: -passes='no-op-module)' %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-UNBALANCED1
; CHECK-UNBALANCED1: unable to parse pass pipeline description
; CHECK-UNBALANCED1: invalid pipeline 'no-op-module)'

; RUN: not opt -disable-output -debug-pass-manager \
; RUN: -passes='module(no-op-module))' %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-UNBALANCED2
; CHECK-UNBALANCED2: unable to parse pass pipeline description
; CHECK-UNBALANCED2: invalid pipeline 'module(no-op-module))'

; RUN: not opt -disable-output -debug-pass-manager \
; RUN: -passes='module(no-op-module' %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-UNBALANCED3
; CHECK-UNBALANCED3: unable to parse pass pipeline description
; CHECK-UNBALANCED3: invalid pipeline 'module(no-op-module'

; RUN: not opt -disable-output -debug-pass-manager \
; RUN: -passes='no-op-function)' %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-UNBALANCED4
; CHECK-UNBALANCED4: unable to parse pass pipeline description
; CHECK-UNBALANCED4: invalid pipeline 'no-op-function)'

; RUN: not opt -disable-output -debug-pass-manager \
; RUN: -passes='function(no-op-function))' %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-UNBALANCED5
; CHECK-UNBALANCED5: unable to parse pass pipeline description
; CHECK-UNBALANCED5: invalid pipeline 'function(no-op-function))'

; RUN: not opt -disable-output -debug-pass-manager \
; RUN: -passes='function(function(no-op-function)))' %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-UNBALANCED6
; CHECK-UNBALANCED6: unable to parse pass pipeline description
; CHECK-UNBALANCED6: invalid pipeline 'function(function(no-op-function)))'

; RUN: not opt -disable-output -debug-pass-manager \
; RUN: -passes='function(no-op-function' %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-UNBALANCED7
; CHECK-UNBALANCED7: unable to parse pass pipeline description
; CHECK-UNBALANCED7: invalid pipeline 'function(no-op-function'

; RUN: not opt -disable-output -debug-pass-manager \
; RUN: -passes='function(function(no-op-function)' %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-UNBALANCED8
; CHECK-UNBALANCED8: unable to parse pass pipeline description
; CHECK-UNBALANCED8: invalid pipeline 'function(function(no-op-function)'

; RUN: not opt -disable-output -debug-pass-manager \
; RUN: -passes='no-op-module,)' %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-UNBALANCED9
; CHECK-UNBALANCED9: unable to parse pass pipeline description
; CHECK-UNBALANCED9: invalid pipeline 'no-op-module,)'

; RUN: not opt -disable-output -debug-pass-manager \
; RUN: -passes='no-op-function,)' %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-UNBALANCED10
; CHECK-UNBALANCED10: unable to parse pass pipeline description
; CHECK-UNBALANCED10: invalid pipeline 'no-op-function,)'

; RUN: opt -disable-output -debug-pass-manager \
; RUN: -passes=no-op-cgscc,no-op-cgscc %s 2>&1 \
Expand Down Expand Up @@ -176,37 +176,86 @@
; RUN: not opt -disable-output -debug-pass-manager \
; RUN: -passes='function(no-op-function)function(no-op-function)' %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-MISSING-COMMA1
; CHECK-MISSING-COMMA1: unable to parse pass pipeline description
; CHECK-MISSING-COMMA1: invalid pipeline 'function(no-op-function)function(no-op-function)'

; RUN: not opt -disable-output -debug-pass-manager \
; RUN: -passes='function()' %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-EMPTY-INNER-PIPELINE
; CHECK-EMPTY-INNER-PIPELINE: unable to parse pass pipeline description
; CHECK-EMPTY-INNER-PIPELINE: unknown function pass ''

; RUN: not opt -disable-output -debug-pass-manager \
; RUN: -passes='no-op-module(no-op-module,whatever)' %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-PIPELINE-ON-MODULE-PASS
; CHECK-PIPELINE-ON-MODULE-PASS: unable to parse pass pipeline description
; CHECK-PIPELINE-ON-MODULE-PASS: invalid use of 'no-op-module' pass as module pipeline

; RUN: not opt -disable-output -debug-pass-manager \
; RUN: -passes='no-op-cgscc(no-op-cgscc,whatever)' %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-PIPELINE-ON-CGSCC-PASS
; CHECK-PIPELINE-ON-CGSCC-PASS: unable to parse pass pipeline description
; CHECK-PIPELINE-ON-CGSCC-PASS: invalid use of 'no-op-cgscc' pass as cgscc pipeline

; RUN: not opt -disable-output -debug-pass-manager \
; RUN: -passes='no-op-function(no-op-function,whatever)' %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-PIPELINE-ON-FUNCTION-PASS
; CHECK-PIPELINE-ON-FUNCTION-PASS: unable to parse pass pipeline description
; CHECK-PIPELINE-ON-FUNCTION-PASS: invalid use of 'no-op-function' pass as function pipeline

; RUN: not opt -disable-output -debug-pass-manager \
; RUN: -passes='no-op-loop(no-op-loop,whatever)' %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-PIPELINE-ON-LOOP-PASS
; CHECK-PIPELINE-ON-LOOP-PASS: unable to parse pass pipeline description
; CHECK-PIPELINE-ON-LOOP-PASS: invalid use of 'no-op-loop' pass as loop pipeline

; RUN: not opt -disable-output -debug-pass-manager \
; RUN: -passes='no-op-function()' %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-EMPTY-PIPELINE-ON-PASS
; CHECK-EMPTY-PIPELINE-ON-PASS: unable to parse pass pipeline description
; CHECK-EMPTY-PIPELINE-ON-PASS: invalid use of 'no-op-function' pass as function pipeline

; RUN: not opt -passes='no-op-module,bad' \
; RUN: /dev/null -disable-output 2>&1 | FileCheck %s -check-prefix=CHECK-UNKNOWN-MODULE
; CHECK-UNKNOWN-MODULE: opt: unknown module pass 'bad'

; RUN: not opt -passes='no-op-loop,bad' \
; RUN: /dev/null -disable-output 2>&1 | FileCheck %s -check-prefix=CHECK-UNKNOWN-LOOP
; CHECK-UNKNOWN-LOOP: opt: unknown loop pass 'bad'

; RUN: not opt -passes='no-op-cgscc,bad' \
; RUN: /dev/null -disable-output 2>&1 | FileCheck %s -check-prefix=CHECK-UNKNOWN-CGSCC
; CHECK-UNKNOWN-CGSCC: opt: unknown cgscc pass 'bad'

; RUN: not opt -passes='no-op-function,bad' \
; RUN: /dev/null -disable-output 2>&1 | FileCheck %s -check-prefix=CHECK-UNKNOWN-FUNCTION
; RUN: not opt -passes='function(bad,pipeline,text)' \
; RUN: /dev/null -disable-output 2>&1 | FileCheck %s -check-prefix=CHECK-UNKNOWN-FUNCTION
; RUN: not opt -passes='module(no-op-module,function(bad,pipeline,text))' \
; RUN: /dev/null -disable-output 2>&1 | FileCheck %s -check-prefix=CHECK-UNKNOWN-FUNCTION
; RUN: not opt -passes='no-op-module,function(bad,pipeline,text)' \
; RUN: /dev/null -disable-output 2>&1 | FileCheck %s -check-prefix=CHECK-UNKNOWN-FUNCTION
; RUN: not opt -passes='module(cgscc(function(bad,pipeline,text)))' \
; RUN: /dev/null -disable-output 2>&1 | FileCheck %s -check-prefix=CHECK-UNKNOWN-FUNCTION
; CHECK-UNKNOWN-FUNCTION: opt: unknown function pass 'bad'

; RUN: not opt -aa-pipeline=bad -passes=no-op-function \
; RUN: /dev/null -disable-output 2>&1 | FileCheck %s -check-prefix=AA-PIPELINE-ERR
; AA-PIPELINE-ERR: unknown alias analysis name 'bad'
; RUN: opt -passes-ep-peephole=bad -passes=no-op-function \
; RUN: /dev/null -disable-output 2>&1 | FileCheck %s -check-prefix=PASSES-EP-PEEPHOLE-ERR
; PASSES-EP-PEEPHOLE-ERR: Could not parse -passes-ep-peephole pipeline: unknown function pass 'bad'
; RUN: opt -passes-ep-late-loop-optimizations=bad -passes=no-op-function \
; RUN: /dev/null -disable-output 2>&1 | FileCheck %s -check-prefix=PASSES-EP-LATELOOPOPT-ERR
; PASSES-EP-LATELOOPOPT-ERR: Could not parse -passes-ep-late-loop-optimizations pipeline: unknown loop pass 'bad'
; RUN: opt -passes-ep-loop-optimizer-end=bad -passes=no-op-function \
; RUN: /dev/null -disable-output 2>&1 | FileCheck %s -check-prefix=PASSES-EP-LOOPOPTEND-ERR
; PASSES-EP-LOOPOPTEND-ERR: Could not parse -passes-ep-loop-optimizer-end pipeline: unknown loop pass 'bad'
; RUN: opt -passes-ep-scalar-optimizer-late=bad -passes=no-op-function \
; RUN: /dev/null -disable-output 2>&1 | FileCheck %s -check-prefix=PASSES-EP-SCALAROPTLATE-ERR
; PASSES-EP-SCALAROPTLATE-ERR: Could not parse -passes-ep-scalar-optimizer-late pipeline: unknown function pass 'bad'
; RUN: opt -passes-ep-cgscc-optimizer-late=bad -passes=no-op-function \
; RUN: /dev/null -disable-output 2>&1 | FileCheck %s -check-prefix=PASSES-EP-CGSCCOPTLATE-ERR
; PASSES-EP-CGSCCOPTLATE-ERR: Could not parse -passes-ep-cgscc-optimizer-late pipeline: unknown cgscc pass 'bad'
; RUN: opt -passes-ep-vectorizer-start=bad -passes=no-op-function \
; RUN: /dev/null -disable-output 2>&1 | FileCheck %s -check-prefix=PASSES-EP-VECTORIZERSTART-ERR
; PASSES-EP-VECTORIZERSTART-ERR: Could not parse -passes-ep-vectorizer-start pipeline: unknown function pass 'bad'
; RUN: opt -passes-ep-pipeline-start=bad -passes=no-op-function \
; RUN: /dev/null -disable-output 2>&1 | FileCheck %s -check-prefix=PASSES-EP-PIPELINESTART-ERR
; PASSES-EP-PIPELINESTART-ERR: Could not parse -passes-ep-pipeline-start pipeline: unknown pass name 'bad'

define void @f() {
entry:
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/tools/llvm-lto2/X86/pipeline.ll
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ define void @patatino() {
; RUN: -r %t1.bc,patatino,px -opt-pipeline foogoo 2>&1 | \
; RUN: FileCheck %s --check-prefix=ERR

; ERR: LLVM ERROR: unable to parse pass pipeline description: foogoo
; ERR: LLVM ERROR: unable to parse pass pipeline description 'foogoo': unknown pass name 'foogoo'

; RUN: not llvm-lto2 run %t1.bc -o %t.o \
; RUN: -r %t1.bc,patatino,px -aa-pipeline patatino \
; RUN: -opt-pipeline loweratomic 2>&1 | \
; RUN: FileCheck %s --check-prefix=AAERR

; AAERR: LLVM ERROR: unable to parse AA pipeline description: patatino
; AAERR: LLVM ERROR: unable to parse AA pipeline description 'patatino': unknown alias analysis name 'patatino'
2 changes: 1 addition & 1 deletion llvm/test/tools/llvm-opt-fuzzer/command-line.ll
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

; Don't start with incorrect passes specified
; RUN: not llvm-opt-fuzzer %t -ignore_remaining_args=1 -mtriple x86_64 -passes no-pass 2>&1 | FileCheck -check-prefix=PIPELINE %s
; PIPELINE: can't parse pass pipeline
; PIPELINE: unknown pass name 'no-pass'

; Correct command line
; RUN: llvm-opt-fuzzer %t -ignore_remaining_args=1 -mtriple x86_64 -passes instcombine 2>&1 | FileCheck -check-prefix=CORRECT %s
Expand Down
11 changes: 6 additions & 5 deletions llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,10 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
PB.registerLoopAnalyses(LAM);
PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);

bool Ok = PB.parsePassPipeline(MPM, PassPipeline, false, false);
assert(Ok && "Should have been checked during fuzzer initialization");
(void)Ok; // silence unused variable warning on release builds
auto Err = PB.parsePassPipeline(MPM, PassPipeline, false, false);
assert(!Err && "Should have been checked during fuzzer initialization");
// Only fail with assert above, otherwise ignore the parsing error.
consumeError(std::move(Err));

// Run passes which we need to test
//
Expand Down Expand Up @@ -235,8 +236,8 @@ extern "C" LLVM_ATTRIBUTE_USED int LLVMFuzzerInitialize(

PassBuilder PB(TM.get());
ModulePassManager MPM;
if (!PB.parsePassPipeline(MPM, PassPipeline, false, false)) {
errs() << *argv[0] << ": can't parse pass pipeline\n";
if (auto Err = PB.parsePassPipeline(MPM, PassPipeline, false, false)) {
errs() << *argv[0] << ": " << toString(std::move(Err)) << "\n";
exit(1);
}

Expand Down
90 changes: 52 additions & 38 deletions llvm/tools/opt/NewPMDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,69 +118,82 @@ static cl::opt<bool> DebugInfoForProfiling(
/// @}}

template <typename PassManagerT>
bool tryParsePipelineText(PassBuilder &PB, StringRef PipelineText) {
if (PipelineText.empty())
bool tryParsePipelineText(PassBuilder &PB,
const cl::opt<std::string> &PipelineOpt) {
if (PipelineOpt.empty())
return false;

// Verify the pipeline is parseable:
PassManagerT PM;
if (PB.parsePassPipeline(PM, PipelineText))
return true;

errs() << "Could not parse pipeline '" << PipelineText
<< "'. I'm going to igore it.\n";
return false;
if (auto Err = PB.parsePassPipeline(PM, PipelineOpt)) {
errs() << "Could not parse -" << PipelineOpt.ArgStr
<< " pipeline: " << toString(std::move(Err))
<< "... I'm going to ignore it.\n";
return false;
}
return true;
}

/// If one of the EPPipeline command line options was given, register callbacks
/// for parsing and inserting the given pipeline
static void registerEPCallbacks(PassBuilder &PB, bool VerifyEachPass,
bool DebugLogging) {
if (tryParsePipelineText<FunctionPassManager>(PB, PeepholeEPPipeline))
PB.registerPeepholeEPCallback([&PB, VerifyEachPass, DebugLogging](
FunctionPassManager &PM, PassBuilder::OptimizationLevel Level) {
PB.parsePassPipeline(PM, PeepholeEPPipeline, VerifyEachPass,
DebugLogging);
});
PB.registerPeepholeEPCallback(
[&PB, VerifyEachPass, DebugLogging](
FunctionPassManager &PM, PassBuilder::OptimizationLevel Level) {
ExitOnError Err("Unable to parse PeepholeEP pipeline: ");
Err(PB.parsePassPipeline(PM, PeepholeEPPipeline, VerifyEachPass,
DebugLogging));
});
if (tryParsePipelineText<LoopPassManager>(PB,
LateLoopOptimizationsEPPipeline))
PB.registerLateLoopOptimizationsEPCallback(
[&PB, VerifyEachPass, DebugLogging](
LoopPassManager &PM, PassBuilder::OptimizationLevel Level) {
PB.parsePassPipeline(PM, LateLoopOptimizationsEPPipeline,
VerifyEachPass, DebugLogging);
ExitOnError Err("Unable to parse LateLoopOptimizationsEP pipeline: ");
Err(PB.parsePassPipeline(PM, LateLoopOptimizationsEPPipeline,
VerifyEachPass, DebugLogging));
});
if (tryParsePipelineText<LoopPassManager>(PB, LoopOptimizerEndEPPipeline))
PB.registerLoopOptimizerEndEPCallback([&PB, VerifyEachPass, DebugLogging](
LoopPassManager &PM, PassBuilder::OptimizationLevel Level) {
PB.parsePassPipeline(PM, LoopOptimizerEndEPPipeline, VerifyEachPass,
DebugLogging);
});
PB.registerLoopOptimizerEndEPCallback(
[&PB, VerifyEachPass, DebugLogging](
LoopPassManager &PM, PassBuilder::OptimizationLevel Level) {
ExitOnError Err("Unable to parse LoopOptimizerEndEP pipeline: ");
Err(PB.parsePassPipeline(PM, LoopOptimizerEndEPPipeline,
VerifyEachPass, DebugLogging));
});
if (tryParsePipelineText<FunctionPassManager>(PB,
ScalarOptimizerLateEPPipeline))
PB.registerScalarOptimizerLateEPCallback(
[&PB, VerifyEachPass, DebugLogging](
FunctionPassManager &PM, PassBuilder::OptimizationLevel Level) {
PB.parsePassPipeline(PM, ScalarOptimizerLateEPPipeline,
VerifyEachPass, DebugLogging);
ExitOnError Err("Unable to parse ScalarOptimizerLateEP pipeline: ");
Err(PB.parsePassPipeline(PM, ScalarOptimizerLateEPPipeline,
VerifyEachPass, DebugLogging));
});
if (tryParsePipelineText<CGSCCPassManager>(PB, CGSCCOptimizerLateEPPipeline))
PB.registerCGSCCOptimizerLateEPCallback([&PB, VerifyEachPass, DebugLogging](
CGSCCPassManager &PM, PassBuilder::OptimizationLevel Level) {
PB.parsePassPipeline(PM, CGSCCOptimizerLateEPPipeline, VerifyEachPass,
DebugLogging);
});
PB.registerCGSCCOptimizerLateEPCallback(
[&PB, VerifyEachPass, DebugLogging](
CGSCCPassManager &PM, PassBuilder::OptimizationLevel Level) {
ExitOnError Err("Unable to parse CGSCCOptimizerLateEP pipeline: ");
Err(PB.parsePassPipeline(PM, CGSCCOptimizerLateEPPipeline,
VerifyEachPass, DebugLogging));
});
if (tryParsePipelineText<FunctionPassManager>(PB, VectorizerStartEPPipeline))
PB.registerVectorizerStartEPCallback([&PB, VerifyEachPass, DebugLogging](
FunctionPassManager &PM, PassBuilder::OptimizationLevel Level) {
PB.parsePassPipeline(PM, VectorizerStartEPPipeline, VerifyEachPass,
DebugLogging);
});
PB.registerVectorizerStartEPCallback(
[&PB, VerifyEachPass, DebugLogging](
FunctionPassManager &PM, PassBuilder::OptimizationLevel Level) {
ExitOnError Err("Unable to parse VectorizerStartEP pipeline: ");
Err(PB.parsePassPipeline(PM, VectorizerStartEPPipeline,
VerifyEachPass, DebugLogging));
});
if (tryParsePipelineText<ModulePassManager>(PB, PipelineStartEPPipeline))
PB.registerPipelineStartEPCallback(
[&PB, VerifyEachPass, DebugLogging](ModulePassManager &PM) {
PB.parsePassPipeline(PM, PipelineStartEPPipeline, VerifyEachPass,
DebugLogging);
ExitOnError Err("Unable to parse PipelineStartEP pipeline: ");
Err(PB.parsePassPipeline(PM, PipelineStartEPPipeline, VerifyEachPass,
DebugLogging));
});
}

Expand Down Expand Up @@ -258,8 +271,8 @@ bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM,
// Specially handle the alias analysis manager so that we can register
// a custom pipeline of AA passes with it.
AAManager AA;
if (!PB.parseAAPipeline(AA, AAPipeline)) {
errs() << Arg0 << ": unable to parse AA pipeline description.\n";
if (auto Err = PB.parseAAPipeline(AA, AAPipeline)) {
errs() << Arg0 << ": " << toString(std::move(Err)) << "\n";
return false;
}

Expand All @@ -284,8 +297,9 @@ bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM,
if (EnableDebugify)
MPM.addPass(NewPMDebugifyPass());

if (!PB.parsePassPipeline(MPM, PassPipeline, VerifyEachPass, DebugPM)) {
errs() << Arg0 << ": unable to parse pass pipeline description.\n";
if (auto Err =
PB.parsePassPipeline(MPM, PassPipeline, VerifyEachPass, DebugPM)) {
errs() << Arg0 << ": " << toString(std::move(Err)) << "\n";
return false;
}

Expand Down
2 changes: 2 additions & 0 deletions llvm/unittests/IR/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,5 @@ add_llvm_unittest(IRTests
VerifierTest.cpp
WaymarkTest.cpp
)

target_link_libraries(IRTests PRIVATE LLVMTestingSupport)
37 changes: 19 additions & 18 deletions llvm/unittests/IR/PassBuilderCallbacksTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//

#include "llvm/Testing/Support/Error.h"
#include <functional>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
Expand Down Expand Up @@ -460,7 +461,7 @@ TEST_F(ModuleCallbacksTest, Passes) {
.WillOnce(Invoke(getAnalysisResult));

StringRef PipelineText = "test-transform";
ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
<< "Pipeline was: " << PipelineText;

PM.run(*M, AM);
Expand Down Expand Up @@ -494,7 +495,7 @@ TEST_F(ModuleCallbacksTest, InstrumentedPasses) {
.InSequence(PISequence);

StringRef PipelineText = "test-transform";
ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
<< "Pipeline was: " << PipelineText;

PM.run(*M, AM);
Expand Down Expand Up @@ -525,7 +526,7 @@ TEST_F(ModuleCallbacksTest, InstrumentedSkippedPasses) {
.Times(0);

StringRef PipelineText = "test-transform";
ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
<< "Pipeline was: " << PipelineText;

PM.run(*M, AM);
Expand All @@ -537,7 +538,7 @@ TEST_F(FunctionCallbacksTest, Passes) {
.WillOnce(Invoke(getAnalysisResult));

StringRef PipelineText = "test-transform";
ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
<< "Pipeline was: " << PipelineText;
PM.run(*M, AM);
}
Expand Down Expand Up @@ -571,7 +572,7 @@ TEST_F(FunctionCallbacksTest, InstrumentedPasses) {
.InSequence(PISequence);

StringRef PipelineText = "test-transform";
ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
<< "Pipeline was: " << PipelineText;
PM.run(*M, AM);
}
Expand Down Expand Up @@ -604,7 +605,7 @@ TEST_F(FunctionCallbacksTest, InstrumentedSkippedPasses) {
.Times(0);

StringRef PipelineText = "test-transform";
ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
<< "Pipeline was: " << PipelineText;
PM.run(*M, AM);
}
Expand All @@ -615,7 +616,7 @@ TEST_F(LoopCallbacksTest, Passes) {
.WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));

StringRef PipelineText = "test-transform";
ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
<< "Pipeline was: " << PipelineText;
PM.run(*M, AM);
}
Expand Down Expand Up @@ -650,7 +651,7 @@ TEST_F(LoopCallbacksTest, InstrumentedPasses) {
.InSequence(PISequence);

StringRef PipelineText = "test-transform";
ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
<< "Pipeline was: " << PipelineText;
PM.run(*M, AM);
}
Expand Down Expand Up @@ -682,7 +683,7 @@ TEST_F(LoopCallbacksTest, InstrumentedSkippedPasses) {
.Times(0);

StringRef PipelineText = "test-transform";
ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
<< "Pipeline was: " << PipelineText;
PM.run(*M, AM);
}
Expand All @@ -693,7 +694,7 @@ TEST_F(CGSCCCallbacksTest, Passes) {
.WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));

StringRef PipelineText = "test-transform";
ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
<< "Pipeline was: " << PipelineText;
PM.run(*M, AM);
}
Expand Down Expand Up @@ -727,7 +728,7 @@ TEST_F(CGSCCCallbacksTest, InstrumentedPasses) {
.InSequence(PISequence);

StringRef PipelineText = "test-transform";
ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
<< "Pipeline was: " << PipelineText;
PM.run(*M, AM);
}
Expand Down Expand Up @@ -759,7 +760,7 @@ TEST_F(CGSCCCallbacksTest, InstrumentedSkippedPasses) {
.Times(0);

StringRef PipelineText = "test-transform";
ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
<< "Pipeline was: " << PipelineText;
PM.run(*M, AM);
}
Expand All @@ -774,7 +775,7 @@ TEST_F(ModuleCallbacksTest, AnalysisUtilities) {
EXPECT_CALL(AnalysisHandle, invalidate(HasName("<string>"), _, _));

StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
<< "Pipeline was: " << PipelineText;
PM.run(*M, AM);
}
Expand All @@ -784,7 +785,7 @@ TEST_F(CGSCCCallbacksTest, PassUtilities) {
EXPECT_CALL(AnalysisHandle, invalidate(HasName("(foo)"), _, _));

StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
<< "Pipeline was: " << PipelineText;
PM.run(*M, AM);
}
Expand All @@ -794,7 +795,7 @@ TEST_F(FunctionCallbacksTest, AnalysisUtilities) {
EXPECT_CALL(AnalysisHandle, invalidate(HasName("foo"), _, _));

StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
<< "Pipeline was: " << PipelineText;
PM.run(*M, AM);
}
Expand All @@ -805,7 +806,7 @@ TEST_F(LoopCallbacksTest, PassUtilities) {

StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";

ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
<< "Pipeline was: " << PipelineText;
PM.run(*M, AM);
}
Expand Down Expand Up @@ -845,13 +846,13 @@ TEST_F(ModuleCallbacksTest, ParseTopLevelPipeline) {

StringRef PipelineText =
"another-pipeline(test-transform,invalidate<test-analysis>)";
ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
<< "Pipeline was: " << PipelineText;
PM.run(*M, AM);

/// Test the negative case
PipelineText = "another-pipeline(instcombine)";
ASSERT_FALSE(PB.parsePassPipeline(PM, PipelineText, true))
ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Failed())
<< "Pipeline was: " << PipelineText;
}
} // end anonymous namespace
1 change: 1 addition & 0 deletions llvm/unittests/Passes/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ add_llvm_unittest(PluginsTests
PluginsTest.cpp
)
export_executable_symbols(PluginsTests)
target_link_libraries(PluginsTests PRIVATE LLVMTestingSupport)

set(LLVM_LINK_COMPONENTS)
add_llvm_loadable_module(TestPlugin
Expand Down
5 changes: 3 additions & 2 deletions llvm/unittests/Passes/PluginsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Path.h"
#include "llvm/Testing/Support/Error.h"
#include "llvm/Transforms/Scalar/LoopPassManager.h"
#include "gtest/gtest.h"

Expand Down Expand Up @@ -54,8 +55,8 @@ TEST(PluginsTests, LoadPlugin) {

PassBuilder PB;
ModulePassManager PM;
ASSERT_FALSE(PB.parsePassPipeline(PM, "plugin-pass"));
ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, "plugin-pass"), Failed());

Plugin->registerPassBuilderCallbacks(PB);
ASSERT_TRUE(PB.parsePassPipeline(PM, "plugin-pass"));
ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, "plugin-pass"), Succeeded());
}