llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lld-elf Author: Stefan Gränitz (weliveindetail) <details> <summary>Changes</summary> LLVM pass-plugins are loaded into various tools. Plugins can register passes at different stages of the pipeline, called entry-points. Depending on the pipeline's configuration, different entry-points will be exercised. AFAIK there is no documentation on which entry-points are supposed to be exercised under which conditions. This patch adds regression tests for the status quo in the major consumers of pass-plugins. --- Full diff: https://github.com/llvm/llvm-project/pull/172463.diff 10 Files Affected: - (modified) clang/test/CMakeLists.txt (+6) - (added) clang/test/CodeGen/pass-plugins-entrypoints.c (+66) - (added) clang/test/Interpreter/pass-plugins.cpp (+9) - (modified) clang/test/lit.cfg.py (+2) - (modified) clang/test/lit.site.cfg.py.in (+1) - (added) flang/test/Integration/pass-plugins-entrypoints.f90 (+64) - (modified) flang/test/lit.cfg.py (+3-2) - (modified) flang/test/lit.site.cfg.py.in (+1-1) - (modified) lld/test/ELF/lto/ltopasses-extension.ll (+36-1) - (modified) llvm/examples/Bye/Bye.cpp (+101-15) ``````````diff diff --git a/clang/test/CMakeLists.txt b/clang/test/CMakeLists.txt index bcb6bd68fafc2..05b0ee42da42b 100644 --- a/clang/test/CMakeLists.txt +++ b/clang/test/CMakeLists.txt @@ -134,6 +134,12 @@ if(CLANG_BUILD_EXAMPLES AND CLANG_PLUGIN_SUPPORT) ) endif () +if(LLVM_BUILD_EXAMPLES AND NOT WIN32) + list(APPEND CLANG_TEST_DEPS + Bye + ) +endif() + if(LLVM_INCLUDE_SPIRV_TOOLS_TESTS) list(APPEND CLANG_TEST_DEPS spirv-dis diff --git a/clang/test/CodeGen/pass-plugins-entrypoints.c b/clang/test/CodeGen/pass-plugins-entrypoints.c new file mode 100644 index 0000000000000..90182961b8057 --- /dev/null +++ b/clang/test/CodeGen/pass-plugins-entrypoints.c @@ -0,0 +1,66 @@ +// REQUIRES: plugins, llvm-examples + +// Entry-points in default and -O0 pipeline +// +// RUN: %clang -fpass-plugin=%llvmshlibdir/Bye%pluginext \ +// RUN: -Xclang -load -Xclang %llvmshlibdir/Bye%pluginext \ +// RUN: -mllvm -print-ep-callbacks -o /dev/null -S -emit-llvm %s | FileCheck --check-prefix=EP %s +// +// RUN: %clang -fpass-plugin=%llvmshlibdir/Bye%pluginext -flto=full -O0 \ +// RUN: -Xclang -load -Xclang %llvmshlibdir/Bye%pluginext \ +// RUN: -mllvm -print-ep-callbacks -o /dev/null -S -emit-llvm %s | FileCheck --check-prefix=EP %s +// +// RUN: %clang -fpass-plugin=%llvmshlibdir/Bye%pluginext -flto=thin -O0 \ +// RUN: -Xclang -load -Xclang %llvmshlibdir/Bye%pluginext \ +// RUN: -mllvm -print-ep-callbacks -o /dev/null -S -emit-llvm %s | FileCheck --check-prefix=EP %s +// +// EP: PipelineStart +// EP: PipelineEarlySimplification +// EP-NOT: Peephole +// EP-NOT: ScalarOptimizerLate +// EP-NOT: Peephole +// EP: OptimizerEarly +// EP-NOT: Vectorizer +// EP: OptimizerLast + +// Entry-points in optimizer pipeline +// +// RUN: %clang -fpass-plugin=%llvmshlibdir/Bye%pluginext -O2 \ +// RUN: -Xclang -load -Xclang %llvmshlibdir/Bye%pluginext \ +// RUN: -mllvm -print-ep-callbacks -o /dev/null -S -emit-llvm %s | FileCheck --check-prefix=EP-OPT %s +// +// RUN: %clang -fpass-plugin=%llvmshlibdir/Bye%pluginext -O2 -flto=full \ +// RUN: -Xclang -load -Xclang %llvmshlibdir/Bye%pluginext \ +// RUN: -mllvm -print-ep-callbacks -o /dev/null -S -emit-llvm %s | FileCheck --check-prefix=EP-OPT %s +// +// RUN: %clang -fpass-plugin=%llvmshlibdir/Bye%pluginext -O2 -ffat-lto-objects \ +// RUN: -Xclang -load -Xclang %llvmshlibdir/Bye%pluginext \ +// RUN: -mllvm -print-ep-callbacks -o /dev/null -S -emit-llvm %s | FileCheck --check-prefix=EP-OPT %s +// +// EP-OPT: PipelineStart +// EP-OPT: PipelineEarlySimplification +// EP-OPT: Peephole +// EP-OPT: ScalarOptimizerLate +// EP-OPT: Peephole +// EP-OPT: OptimizerEarly +// EP-OPT: VectorizerStart +// EP-OPT: VectorizerEnd +// EP-OPT: OptimizerLast + +// FIXME: Thin-LTO does not invoke vectorizer callbacks +// +// RUN: %clang -fpass-plugin=%llvmshlibdir/Bye%pluginext -O2 -flto=thin \ +// RUN: -Xclang -load -Xclang %llvmshlibdir/Bye%pluginext \ +// RUN: -mllvm -print-ep-callbacks -o /dev/null -S -emit-llvm %s | FileCheck --check-prefix=EP-LTO-THIN %s +// +// EP-LTO-THIN: PipelineStart +// EP-LTO-THIN: PipelineEarlySimplification +// EP-LTO-THIN: Peephole +// EP-LTO-THIN: ScalarOptimizerLate +// EP-LTO-THIN: OptimizerEarly +// EP-LTO-THIN-NOT: Vectorizer +// EP-LTO-THIN: OptimizerLast + +int f(int x) { + return x; +} diff --git a/clang/test/Interpreter/pass-plugins.cpp b/clang/test/Interpreter/pass-plugins.cpp new file mode 100644 index 0000000000000..4d445807c3d70 --- /dev/null +++ b/clang/test/Interpreter/pass-plugins.cpp @@ -0,0 +1,9 @@ +// RUN: cat %s | clang-repl -Xcc -fpass-plugin=%plugindir/pypass-plugin%pluginext \ +// RUN: -Xcc -load=%plugindir/pypass-plugin%pluginext \ +// RUN: -Xcc -Xclang -Xcc -mllvm -Xcc -wave-goodbye | FileCheck %s +// REQUIRES: plugins, llvm-examples + +int i = 10; +%quit + +// CHECK: Bye diff --git a/clang/test/lit.cfg.py b/clang/test/lit.cfg.py index 52b275c095475..a622f5335354a 100644 --- a/clang/test/lit.cfg.py +++ b/clang/test/lit.cfg.py @@ -126,6 +126,8 @@ if config.clang_examples: config.available_features.add("examples") +if config.llvm_examples: + config.available_features.add("llvm-examples") def have_host_out_of_process_jit_feature_support(): diff --git a/clang/test/lit.site.cfg.py.in b/clang/test/lit.site.cfg.py.in index f50953a93a412..8e0ecdbe07805 100644 --- a/clang/test/lit.site.cfg.py.in +++ b/clang/test/lit.site.cfg.py.in @@ -28,6 +28,7 @@ config.clang_staticanalyzer_z3 = @LLVM_WITH_Z3@ config.clang_staticanalyzer_z3_mock = @TEST_WITH_Z3_MOCK@ config.clang_enable_cir = @CLANG_ENABLE_CIR@ config.clang_examples = @CLANG_BUILD_EXAMPLES@ +config.llvm_examples = @LLVM_BUILD_EXAMPLES@ config.enable_shared = @ENABLE_SHARED@ config.enable_backtrace = @ENABLE_BACKTRACES@ config.enable_threads = @LLVM_ENABLE_THREADS@ diff --git a/flang/test/Integration/pass-plugins-entrypoints.f90 b/flang/test/Integration/pass-plugins-entrypoints.f90 new file mode 100644 index 0000000000000..6bbb3421f2dc4 --- /dev/null +++ b/flang/test/Integration/pass-plugins-entrypoints.f90 @@ -0,0 +1,64 @@ +! REQUIRES: plugins, examples + +! Entry-points in default and -O0 pipeline +! +! RUN: %flang -fpass-plugin=%llvmshlibdir/Bye%pluginext \ +! RUN: -Xflang -load -Xflang %llvmshlibdir/Bye%pluginext \ +! RUN: -mllvm -print-ep-callbacks -o /dev/null -S %s | FileCheck --check-prefix=EP %s +! +! RUN: %flang -fpass-plugin=%llvmshlibdir/Bye%pluginext -flto=full -O0 \ +! RUN: -Xflang -load -Xflang %llvmshlibdir/Bye%pluginext \ +! RUN: -mllvm -print-ep-callbacks -o /dev/null -S %s | FileCheck --check-prefix=EP %s +! +! RUN: %flang -fpass-plugin=%llvmshlibdir/Bye%pluginext -flto=thin -O0 \ +! RUN: -Xflang -load -Xflang %llvmshlibdir/Bye%pluginext \ +! RUN: -mllvm -print-ep-callbacks -o /dev/null -S %s | FileCheck --check-prefix=EP %s +! +! EP: PipelineStart +! EP: PipelineEarlySimplification +! EP-NOT: Peephole +! EP: ScalarOptimizerLate +! EP-NOT: Peephole +! EP: OptimizerEarly +! EP: VectorizerStart +! EP: VectorizerEnd +! EP: OptimizerLast + +! Entry-points in optimizer pipeline +! +! RUN: %flang -fpass-plugin=%llvmshlibdir/Bye%pluginext -O2 \ +! RUN: -Xflang -load -Xflang %llvmshlibdir/Bye%pluginext \ +! RUN: -mllvm -print-ep-callbacks -o /dev/null -S %s | FileCheck --check-prefix=EP-OPT %s +! +! RUN: %flang -fpass-plugin=%llvmshlibdir/Bye%pluginext -O2 -flto=full \ +! RUN: -Xflang -load -Xflang %llvmshlibdir/Bye%pluginext \ +! RUN: -mllvm -print-ep-callbacks -o /dev/null -S %s | FileCheck --check-prefix=EP-OPT %s +! +! EP-OPT: PipelineStart +! EP-OPT: PipelineEarlySimplification +! EP-OPT: Peephole +! EP-OPT: ScalarOptimizerLate +! EP-OPT: Peephole +! EP-OPT: OptimizerEarly +! EP-OPT: VectorizerStart +! EP-OPT: VectorizerEnd +! EP-OPT: OptimizerLast + +! FIXME: Thin-LTO does not invoke vectorizer callbacks +! +! RUN: %flang -fpass-plugin=%llvmshlibdir/Bye%pluginext -O2 -flto=thin \ +! RUN: -Xflang -load -Xflang %llvmshlibdir/Bye%pluginext \ +! RUN: -mllvm -print-ep-callbacks -o /dev/null -S %s | FileCheck --check-prefix=EP-LTO-THIN %s +! +! EP-LTO-THIN: PipelineStart +! EP-LTO-THIN: PipelineEarlySimplification +! EP-LTO-THIN: Peephole +! EP-LTO-THIN: ScalarOptimizerLate +! EP-LTO-THIN: OptimizerEarly +! EP-LTO-THIN-NOT: Vectorizer +! EP-LTO-THIN: OptimizerLast + +INTEGER FUNCTION f(x) + INTEGER, INTENT(IN) :: x + f = x +END FUNCTION f diff --git a/flang/test/lit.cfg.py b/flang/test/lit.cfg.py index 4221354df34a2..1d8a1704e6838 100644 --- a/flang/test/lit.cfg.py +++ b/flang/test/lit.cfg.py @@ -90,8 +90,9 @@ # directories. config.excludes = ["Inputs", "CMakeLists.txt", "README.txt", "LICENSE.txt"] -# If the flang examples are built, add examples to the config -if config.flang_examples: +# Some tests depend on examples, mark them as available in the config. This +# setting includes examples from both, flang and llvm. +if config.build_examples: config.available_features.add("examples") # Plugins (loadable modules) diff --git a/flang/test/lit.site.cfg.py.in b/flang/test/lit.site.cfg.py.in index cc1f4fa6cc9c5..1422cc36232cb 100644 --- a/flang/test/lit.site.cfg.py.in +++ b/flang/test/lit.site.cfg.py.in @@ -17,7 +17,7 @@ config.flang_intrinsic_modules_dir = "@FLANG_INTRINSIC_MODULES_DIR@" config.flang_headers_dir = "@HEADER_BINARY_DIR@" config.flang_llvm_tools_dir = "@CMAKE_BINARY_DIR@/bin" config.flang_test_triple = "@FLANG_TEST_TARGET_TRIPLE@" -config.flang_examples = @LLVM_BUILD_EXAMPLES@ +config.build_examples = @LLVM_BUILD_EXAMPLES@ config.python_executable = "@PYTHON_EXECUTABLE@" config.flang_standalone_build = @FLANG_STANDALONE_BUILD@ config.has_plugins = @LLVM_ENABLE_PLUGINS@ diff --git a/lld/test/ELF/lto/ltopasses-extension.ll b/lld/test/ELF/lto/ltopasses-extension.ll index db8edbb8e087d..ce92176d07249 100644 --- a/lld/test/ELF/lto/ltopasses-extension.ll +++ b/lld/test/ELF/lto/ltopasses-extension.ll @@ -1,9 +1,44 @@ ; REQUIRES: x86, plugins, examples ; UNSUPPORTED: target={{.*windows.*}} -; RUN: opt -module-summary %s -o %t.o +; RUN: opt %s -o %t.o +; RUN: opt -module-summary %s -o %t_thin.o + ; RUN: ld.lld -%loadnewpmbye --lto-newpm-passes="goodbye" -mllvm=%loadbye -mllvm=-wave-goodbye %t.o -o /dev/null 2>&1 | FileCheck %s ; CHECK: Bye +; Entry-points in pipeline for regular/monolithic LTO +; +; RUN: ld.lld -%loadnewpmbye -mllvm=%loadbye -mllvm=-print-ep-callbacks %t.o \ +; RUN: -shared -o /dev/null | FileCheck --check-prefix=REGULAR %s +; +; REGULAR-NOT: PipelineStart +; REGULAR-NOT: PipelineEarlySimplification +; REGULAR-NOT: Peephole +; REGULAR-NOT: ScalarOptimizerLate +; REGULAR-NOT: Vectorizer +; REGULAR-NOT: Optimizer +; +; REGULAR: FullLinkTimeOptimizationEarly +; REGULAR: FullLinkTimeOptimizationLast + +; Entry-points in Thin-LTO pipeline +; +; RUN: ld.lld -%loadnewpmbye -mllvm=%loadbye -mllvm=-print-ep-callbacks %t_thin.o \ +; RUN: -shared -o /dev/null | FileCheck --check-prefix=THIN %s +; +; THIN-NOT: FullLinkTimeOptimizationEarly +; THIN-NOT: FullLinkTimeOptimizationLast +; THIN-NOT: PipelineStart +; +; THIN: PipelineEarlySimplification +; THIN: Peephole +; THIN: ScalarOptimizerLate +; THIN: Peephole +; THIN: OptimizerEarly +; THIN: VectorizerStart +; THIN: VectorizerEnd +; THIN: OptimizerLast + target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @junk = global i32 0 diff --git a/llvm/examples/Bye/Bye.cpp b/llvm/examples/Bye/Bye.cpp index d88bf9e490e9c..5108cf4b3d0c0 100644 --- a/llvm/examples/Bye/Bye.cpp +++ b/llvm/examples/Bye/Bye.cpp @@ -11,6 +11,10 @@ using namespace llvm; static cl::opt<bool> Wave("wave-goodbye", cl::init(false), cl::desc("wave good bye")); +static cl::opt<bool> PrintEntryPointCallbacks( + "print-ep-callbacks", cl::init(false), + cl::desc("Print names of all entry-points upon callback")); + namespace { bool runBye(Function &F) { @@ -35,6 +39,102 @@ struct Bye : PassInfoMixin<Bye> { } }; +struct PrintStage : PassInfoMixin<Bye> { + PrintStage(std::string Name) : Name(std::move(Name)) {} + PreservedAnalyses run(Function &F, FunctionAnalysisManager &) { + outs() << Name << "\n"; + return PreservedAnalyses::none(); + } + PreservedAnalyses run(Module &M, ModuleAnalysisManager &) { + outs() << Name << "\n"; + return PreservedAnalyses::none(); + } + +private: + std::string Name; +}; + +void registerPassBuilderCallbacks(PassBuilder &PB) { + PB.registerVectorizerStartEPCallback( + [](llvm::FunctionPassManager &PM, OptimizationLevel Level) { + PM.addPass(Bye()); + }); + PB.registerPipelineParsingCallback( + [](StringRef Name, llvm::FunctionPassManager &PM, + ArrayRef<llvm::PassBuilder::PipelineElement>) { + if (Name == "goodbye") { + PM.addPass(Bye()); + return true; + } + return false; + }); + + if (PrintEntryPointCallbacks) { + PB.registerPipelineStartEPCallback( + [](ModulePassManager &MPM, OptimizationLevel Opt) { + MPM.addPass(PrintStage("PipelineStart")); + return true; + }); + + PB.registerPipelineEarlySimplificationEPCallback( + [](ModulePassManager &MPM, OptimizationLevel Opt, + ThinOrFullLTOPhase Phase) { + MPM.addPass(PrintStage("PipelineEarlySimplification")); + return true; + }); + + PB.registerOptimizerEarlyEPCallback([](ModulePassManager &MPM, + OptimizationLevel Opt, + ThinOrFullLTOPhase Phase) { + MPM.addPass(PrintStage("OptimizerEarly")); + return true; + }); + + PB.registerOptimizerLastEPCallback([](ModulePassManager &MPM, + OptimizationLevel Opt, + ThinOrFullLTOPhase Phase) { + MPM.addPass(PrintStage("OptimizerLast")); + return true; + }); + + PB.registerPeepholeEPCallback( + [](FunctionPassManager &FPM, OptimizationLevel Opt) { + FPM.addPass(PrintStage("Peephole")); + return true; + }); + + PB.registerScalarOptimizerLateEPCallback( + [](FunctionPassManager &FPM, OptimizationLevel Opt) { + FPM.addPass(PrintStage("ScalarOptimizerLate")); + return true; + }); + + PB.registerVectorizerStartEPCallback( + [](FunctionPassManager &FPM, OptimizationLevel Opt) { + FPM.addPass(PrintStage("VectorizerStart")); + return true; + }); + + PB.registerVectorizerEndEPCallback( + [](FunctionPassManager &FPM, OptimizationLevel Opt) { + FPM.addPass(PrintStage("VectorizerEnd")); + return true; + }); + + PB.registerFullLinkTimeOptimizationEarlyEPCallback( + [](ModulePassManager &MPM, OptimizationLevel Opt) { + MPM.addPass(PrintStage("FullLinkTimeOptimizationEarly")); + return true; + }); + + PB.registerFullLinkTimeOptimizationLastEPCallback( + [](ModulePassManager &MPM, OptimizationLevel Opt) { + MPM.addPass(PrintStage("FullLinkTimeOptimizationLast")); + return true; + }); + } +} + } // namespace char LegacyBye::ID = 0; @@ -46,21 +146,7 @@ static RegisterPass<LegacyBye> X("goodbye", "Good Bye World Pass", /* New PM Registration */ llvm::PassPluginLibraryInfo getByePluginInfo() { return {LLVM_PLUGIN_API_VERSION, "Bye", LLVM_VERSION_STRING, - [](PassBuilder &PB) { - PB.registerVectorizerStartEPCallback( - [](llvm::FunctionPassManager &PM, OptimizationLevel Level) { - PM.addPass(Bye()); - }); - PB.registerPipelineParsingCallback( - [](StringRef Name, llvm::FunctionPassManager &PM, - ArrayRef<llvm::PassBuilder::PipelineElement>) { - if (Name == "goodbye") { - PM.addPass(Bye()); - return true; - } - return false; - }); - }}; + registerPassBuilderCallbacks}; } #ifndef LLVM_BYE_LINK_INTO_TOOLS `````````` </details> https://github.com/llvm/llvm-project/pull/172463 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
