Index: clang/lib/CodeGen/BackendUtil.cpp =================================================================== --- clang/lib/CodeGen/BackendUtil.cpp +++ clang/lib/CodeGen/BackendUtil.cpp @@ -74,6 +74,10 @@ using namespace clang; using namespace llvm; +#define HANDLE_EXTENSION(Ext) \ + llvm::PassPluginLibraryInfo get##Ext##PluginInfo(); +#include "llvm/Support/Extension.def" + namespace { // Default filename used for profile generation. @@ -1074,6 +1078,9 @@ << PluginFN << toString(PassPlugin.takeError()); } } +#define HANDLE_EXTENSION(Ext) \ + get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB); +#include "llvm/Support/Extension.def" LoopAnalysisManager LAM(CodeGenOpts.DebugPassManager); FunctionAnalysisManager FAM(CodeGenOpts.DebugPassManager); Index: clang/lib/CodeGen/CMakeLists.txt =================================================================== --- clang/lib/CodeGen/CMakeLists.txt +++ clang/lib/CodeGen/CMakeLists.txt @@ -95,6 +95,8 @@ TargetInfo.cpp VarBypassDetector.cpp + ENABLE_PLUGINS + DEPENDS ${codegen_deps} Index: clang/tools/driver/CMakeLists.txt =================================================================== --- clang/tools/driver/CMakeLists.txt +++ clang/tools/driver/CMakeLists.txt @@ -122,7 +122,3 @@ set_target_properties(clang PROPERTIES LINK_DEPENDS ${CLANG_ORDER_FILE}) endif() endif() - -if(WITH_POLLY AND LINK_POLLY_INTO_TOOLS) - target_link_libraries(clang PRIVATE Polly) -endif(WITH_POLLY AND LINK_POLLY_INTO_TOOLS) Index: clang/tools/driver/cc1_main.cpp =================================================================== --- clang/tools/driver/cc1_main.cpp +++ clang/tools/driver/cc1_main.cpp @@ -72,12 +72,6 @@ exit(GenCrashDiag ? 70 : 1); } -#ifdef LINK_POLLY_INTO_TOOLS -namespace polly { -void initializePollyPasses(llvm::PassRegistry &Registry); -} -#endif - #ifdef CLANG_HAVE_RLIMITS #if defined(__linux__) && defined(__PIE__) static size_t getCurrentStackAllocation() { @@ -203,11 +197,6 @@ llvm::InitializeAllAsmPrinters(); llvm::InitializeAllAsmParsers(); -#ifdef LINK_POLLY_INTO_TOOLS - llvm::PassRegistry &Registry = *llvm::PassRegistry::getPassRegistry(); - polly::initializePollyPasses(Registry); -#endif - // Buffer diagnostics from argument parsing so that we can output them using a // well formed diagnostic object. IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); Index: llvm/CMakeLists.txt =================================================================== --- llvm/CMakeLists.txt +++ llvm/CMakeLists.txt @@ -457,29 +457,6 @@ option(LLVM_USE_SPLIT_DWARF "Use -gsplit-dwarf when compiling llvm." OFF) -option(LLVM_POLLY_LINK_INTO_TOOLS "Statically link Polly into tools (if available)" ON) -option(LLVM_POLLY_BUILD "Build LLVM with Polly" ON) - -if (EXISTS ${LLVM_MAIN_SRC_DIR}/tools/polly/CMakeLists.txt) - set(POLLY_IN_TREE TRUE) -elseif(LLVM_EXTERNAL_POLLY_SOURCE_DIR) - set(POLLY_IN_TREE TRUE) -else() - set(POLLY_IN_TREE FALSE) -endif() - -if (LLVM_POLLY_BUILD AND POLLY_IN_TREE) - set(WITH_POLLY ON) -else() - set(WITH_POLLY OFF) -endif() - -if (LLVM_POLLY_LINK_INTO_TOOLS AND WITH_POLLY) - set(LINK_POLLY_INTO_TOOLS ON) -else() - set(LINK_POLLY_INTO_TOOLS OFF) -endif() - # Define an option controlling whether we should build for 32-bit on 64-bit # platforms, where supported. if( CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32 ) @@ -1103,3 +1080,5 @@ add_subdirectory(utils/benchmark) add_subdirectory(benchmarks) endif() + +process_llvm_pass_plugins() Index: llvm/cmake/modules/AddLLVM.cmake =================================================================== --- llvm/cmake/modules/AddLLVM.cmake +++ llvm/cmake/modules/AddLLVM.cmake @@ -389,7 +389,7 @@ # ) function(llvm_add_library name) cmake_parse_arguments(ARG - "MODULE;SHARED;STATIC;OBJECT;DISABLE_LLVM_LINK_LLVM_DYLIB;SONAME;NO_INSTALL_RPATH" + "MODULE;SHARED;STATIC;OBJECT;DISABLE_LLVM_LINK_LLVM_DYLIB;SONAME;NO_INSTALL_RPATH;ENABLE_PLUGINS" "OUTPUT_NAME;PLUGIN_TOOL;ENTITLEMENTS;BUNDLE_PATH" "ADDITIONAL_HEADERS;DEPENDS;LINK_COMPONENTS;LINK_LIBS;OBJLIBS" ${ARGN}) @@ -403,6 +403,9 @@ else() llvm_process_sources(ALL_FILES ${ARG_UNPARSED_ARGUMENTS} ${ARG_ADDITIONAL_HEADERS}) endif() + if(ARG_ENABLE_PLUGINS) + set_property(GLOBAL APPEND PROPERTY LLVM_PLUGIN_TARGETS ${name}) + endif() if(ARG_MODULE) if(ARG_SHARED OR ARG_STATIC) @@ -718,7 +721,7 @@ macro(add_llvm_executable name) cmake_parse_arguments(ARG - "DISABLE_LLVM_LINK_LLVM_DYLIB;IGNORE_EXTERNALIZE_DEBUGINFO;NO_INSTALL_RPATH" + "DISABLE_LLVM_LINK_LLVM_DYLIB;IGNORE_EXTERNALIZE_DEBUGINFO;NO_INSTALL_RPATH;ENABLE_PLUGINS" "ENTITLEMENTS;BUNDLE_PATH" "DEPENDS" ${ARGN}) @@ -800,10 +803,68 @@ # API for all shared libaries loaded by this executable. target_link_libraries(${name} PRIVATE ${LLVM_PTHREAD_LIB}) endif() + if(ARG_ENABLE_PLUGINS) + set_property(GLOBAL APPEND PROPERTY LLVM_PLUGIN_TARGETS ${name}) + endif() llvm_codesign(${name} ENTITLEMENTS ${ARG_ENTITLEMENTS} BUNDLE_PATH ${ARG_BUNDLE_PATH}) endmacro(add_llvm_executable name) +# add_llvm_pass_plugin(name) +# Add ${name} as an llvm plugin. +# If option LLVM_${name_upper}_LINK_INTO_TOOLS is set to ON, the plugin is registered statically. +# Otherwise a pluggable shared library is registered. +function(add_llvm_pass_plugin name) + + string(TOUPPER ${name} name_upper) + + option(LLVM_${name_upper}_LINK_INTO_TOOLS "Statically link ${name} into tools (if available)" OFF) + add_llvm_library(${name} OBJECT ${ARGN}) + if(LLVM_${name_upper}_LINK_INTO_TOOLS) + set_property(TARGET ${name} APPEND PROPERTY COMPILE_DEFINITIONS LLVM_LINK_INTO_TOOLS) + endif() + + message(STATUS "Registering ${name} as a pass plugin (static build: ${LLVM_${name_upper}_LINK_INTO_TOOLS})") + if(LLVM_${name_upper}_LINK_INTO_TOOLS) + set_property(GLOBAL APPEND PROPERTY LLVM_COMPILE_EXTENSIONS ${name}) + endif() +endfunction(add_llvm_pass_plugin) + +# Generate X Macro file for extension handling. It provides a +# HANDLE_EXTENSION(extension_namespace, ExtensionProject) call for each extension +# allowing client code to define HANDLE_EXTENSION to have a specific code be run for +# each extension. +# +# Also correctly set lib dependencies between plugins and tools. +function(process_llvm_pass_plugins) + get_property(LLVM_EXTENSIONS GLOBAL PROPERTY LLVM_COMPILE_EXTENSIONS) + file(WRITE "${CMAKE_BINARY_DIR}/include/llvm/Support/Extension.def.tmp" "//extension handlers\n") + foreach(llvm_extension ${LLVM_EXTENSIONS}) + string(TOLOWER ${llvm_extension} llvm_extension_lower) + + string(TOUPPER ${llvm_extension} llvm_extension_upper) + string(SUBSTRING ${llvm_extension_upper} 0 1 llvm_extension_upper_first) + string(SUBSTRING ${llvm_extension_lower} 1 -1 llvm_extension_lower_tail) + string(CONCAT llvm_extension_project ${llvm_extension_upper_first} ${llvm_extension_lower_tail}) + + if(LLVM_${llvm_extension_upper}_LINK_INTO_TOOLS) + file(APPEND "${CMAKE_BINARY_DIR}/include/llvm/Support/Extension.def.tmp" "HANDLE_EXTENSION(${llvm_extension_project})\n") + endif() + + get_property(llvm_plugin_targets GLOBAL PROPERTY LLVM_PLUGIN_TARGETS) + foreach(llvm_plugin_target ${llvm_plugin_targets}) + set_property(TARGET ${llvm_plugin_target} APPEND PROPERTY LINK_LIBRARIES ${llvm_extension}) + set_property(TARGET ${llvm_plugin_target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${llvm_extension}) + endforeach() + + endforeach() + file(APPEND "${CMAKE_BINARY_DIR}/include/llvm/Support/Extension.def.tmp" "#undef HANDLE_EXTENSION\n") + + # only replace if there's an actual change + execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_BINARY_DIR}/include/llvm/Support/Extension.def.tmp" "${CMAKE_BINARY_DIR}/include/llvm/Support/Extension.def") + file(REMOVE "${CMAKE_BINARY_DIR}/include/llvm/Support/Extension.def.tmp") +endfunction() + function(export_executable_symbols target) if (LLVM_EXPORTED_SYMBOL_FILE) # The symbol file should contain the symbols we want the executable to Index: llvm/docs/WritingAnLLVMPass.rst =================================================================== --- llvm/docs/WritingAnLLVMPass.rst +++ llvm/docs/WritingAnLLVMPass.rst @@ -1241,6 +1241,32 @@ this internal state. This method is called after the ``run*`` method for the class, before the next call of ``run*`` in your pass. +Building pass plugins +===================== + +LLVM provides a mechanism to automatically register pass plugins within +``clang``, ``opt`` and ``bugpoint``. One first needs to create an independent +project and add it to either ``tools/`` or, using the MonoRepo layout, at the +root of the repo alongside other projects. This project must contain the +following minimal ``CMakeLists.txt``: + +.. code-block:: cmake + + add_llvm_pass_plugin(Name source0.cpp) + +The pass must provide two entry points for the new pass manager, one for static +registration and one for dynamically loaded plugins: + +- ``llvm::PassPluginLibraryInfo get##Name##PluginInfo();`` +- ``extern "C" ::llvm::PassPluginLibraryInfo llvmGetPassPluginInfo() LLVM_ATTRIBUTE_WEAK;`` + +Pass plugins are compiled and link dynamically by default, but it's +possible to set the following variables to change this behavior: + +- ``LLVM_${NAME}_LINK_INTO_TOOLS``, when sets to ``ON``, turns the project into + a statcially linked extension + + Registering dynamically loaded passes ===================================== Index: llvm/examples/Bye/Bye.cpp =================================================================== --- /dev/null +++ llvm/examples/Bye/Bye.cpp @@ -0,0 +1,66 @@ +#include "llvm/IR/Function.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/Pass.h" +#include "llvm/Passes/PassBuilder.h" +#include "llvm/Passes/PassPlugin.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" + +using namespace llvm; + +static cl::opt Wave("wave-goodbye", cl::init(false), + cl::desc("wave good bye")); + +namespace { + +bool runBye(Function &F) { + if (Wave) { + errs() << "Bye: "; + errs().write_escaped(F.getName()) << '\n'; + } + return false; +} + +struct LegacyBye : public FunctionPass { + static char ID; + LegacyBye() : FunctionPass(ID) {} + bool runOnFunction(Function &F) override { return runBye(F); } +}; + +struct Bye : PassInfoMixin { + PreservedAnalyses run(Function &F, FunctionAnalysisManager &) { + if (!runBye(F)) + return PreservedAnalyses::all(); + return PreservedAnalyses::none(); + } +}; + +} // namespace + +char LegacyBye::ID = 0; + +static RegisterPass X("goodbye", "Good Bye World Pass", + false /* Only looks at CFG */, + false /* Analysis Pass */); + +/* Legacy PM Registration */ +static llvm::RegisterStandardPasses RegisterBye( + llvm::PassManagerBuilder::EP_EarlyAsPossible, + [](const llvm::PassManagerBuilder &Builder, + llvm::legacy::PassManagerBase &PM) { PM.add(new LegacyBye()); }); + +/* New PM Registration */ + +llvm::PassPluginLibraryInfo getByePluginInfo() { + return {LLVM_PLUGIN_API_VERSION, "Bye", LLVM_VERSION_STRING, + [](PassBuilder &PB) { + PB.registerVectorizerStartEPCallback( + [](llvm::FunctionPassManager &PM, + llvm::PassBuilder::OptimizationLevel Level) { + PM.addPass(Bye()); + }); + }}; +} +extern "C" ::llvm::PassPluginLibraryInfo llvmGetPassPluginInfo() { + return getByePluginInfo(); +} Index: llvm/examples/Bye/CMakeLists.txt =================================================================== --- /dev/null +++ llvm/examples/Bye/CMakeLists.txt @@ -0,0 +1,28 @@ +add_llvm_pass_plugin(Bye Bye.cpp) +if (TARGET intrinsics_gen) + add_dependencies(obj.Bye intrinsics_gen) +endif() + +if (LLVM_LINK_LLVM_DYLIB) + target_link_libraries(Bye PUBLIC LLVM) +else() + target_link_libraries(Bye + PUBLIC + LLVMSupport + LLVMCore + LLVMScalarOpts + LLVMInstCombine + LLVMTransformUtils + LLVMAnalysis + LLVMipo + LLVMMC + LLVMPasses + LLVMLinker + LLVMIRReader + LLVMBitReader + LLVMMCParser + LLVMObject + LLVMTarget + ) +endif() + Index: llvm/examples/CMakeLists.txt =================================================================== --- llvm/examples/CMakeLists.txt +++ llvm/examples/CMakeLists.txt @@ -5,6 +5,7 @@ add_subdirectory(LLJITExamples) add_subdirectory(Kaleidoscope) add_subdirectory(ModuleMaker) +add_subdirectory(Bye) if(LLVM_ENABLE_EH AND (NOT WIN32) AND (NOT "${LLVM_NATIVE_ARCH}" STREQUAL "ARM")) add_subdirectory(ExceptionDemo) Index: llvm/include/llvm/Config/llvm-config.h.cmake =================================================================== --- llvm/include/llvm/Config/llvm-config.h.cmake +++ llvm/include/llvm/Config/llvm-config.h.cmake @@ -17,9 +17,6 @@ /* Define if LLVM_ENABLE_DUMP is enabled */ #cmakedefine LLVM_ENABLE_DUMP -/* Define if we link Polly to the tools */ -#cmakedefine LINK_POLLY_INTO_TOOLS - /* Target triple LLVM will generate code for by default */ #cmakedefine LLVM_DEFAULT_TARGET_TRIPLE "${LLVM_DEFAULT_TARGET_TRIPLE}" Index: llvm/test/Feature/load_extension.ll =================================================================== --- /dev/null +++ llvm/test/Feature/load_extension.ll @@ -0,0 +1,10 @@ +; RUN: not test -f %llvmshlibdir/libBye%shlibext || opt %s -load=%llvmshlibdir/libBye%shlibext -goodbye -wave-goodbye \ +; RUN: -disable-output 2>&1 | grep Bye +; REQUIRES: plugins + +@junk = global i32 0 + +define i32* @somefunk() { + ret i32* @junk +} + Index: llvm/test/Other/new-pm-defaults.ll =================================================================== --- llvm/test/Other/new-pm-defaults.ll +++ llvm/test/Other/new-pm-defaults.ll @@ -9,68 +9,83 @@ ; RUN: opt -disable-verify -debug-pass-manager \ ; RUN: -passes='default' -S %s 2>&1 \ -; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O1 +; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O1 \ +; RUN: --check-prefix=${LLVM_CHECK_EXT} ; RUN: opt -disable-verify -debug-pass-manager \ ; RUN: -passes='default' -S %s 2>&1 \ -; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O2 +; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O2 \ +; RUN: --check-prefix=${LLVM_CHECK_EXT} ; RUN: opt -disable-verify -debug-pass-manager \ ; RUN: -passes='default' -S %s 2>&1 \ -; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O3 +; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O3 \ +; RUN: --check-prefix=${LLVM_CHECK_EXT} ; RUN: opt -disable-verify -debug-pass-manager \ ; RUN: -passes='default' -S %s 2>&1 \ -; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-Os +; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-Os \ +; RUN: --check-prefix=${LLVM_CHECK_EXT} ; RUN: opt -disable-verify -debug-pass-manager \ ; RUN: -passes='default' -S %s 2>&1 \ -; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-Oz +; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-Oz \ +; RUN: --check-prefix=${LLVM_CHECK_EXT} ; RUN: opt -disable-verify -debug-pass-manager \ ; RUN: -passes='lto-pre-link' -S %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O2 \ +; RUN: --check-prefix=${LLVM_CHECK_EXT} \ ; RUN: --check-prefix=CHECK-O2-LTO ; RUN: opt -disable-verify -debug-pass-manager \ ; RUN: -passes-ep-peephole='no-op-function' \ ; RUN: -passes='default' -S %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O3 \ +; RUN: --check-prefix=${LLVM_CHECK_EXT} \ ; RUN: --check-prefix=CHECK-EP-PEEPHOLE ; RUN: opt -disable-verify -debug-pass-manager \ ; RUN: -passes-ep-late-loop-optimizations='no-op-loop' \ ; RUN: -passes='default' -S %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O3 \ +; RUN: --check-prefix=${LLVM_CHECK_EXT} \ ; RUN: --check-prefix=CHECK-EP-LOOP-LATE ; RUN: opt -disable-verify -debug-pass-manager \ ; RUN: -passes-ep-loop-optimizer-end='no-op-loop' \ ; RUN: -passes='default' -S %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O3 \ +; RUN: --check-prefix=${LLVM_CHECK_EXT} \ ; RUN: --check-prefix=CHECK-EP-LOOP-END ; RUN: opt -disable-verify -debug-pass-manager \ ; RUN: -passes-ep-scalar-optimizer-late='no-op-function' \ ; RUN: -passes='default' -S %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O3 \ +; RUN: --check-prefix=${LLVM_CHECK_EXT} \ ; RUN: --check-prefix=CHECK-EP-SCALAR-LATE ; RUN: opt -disable-verify -debug-pass-manager \ ; RUN: -passes-ep-cgscc-optimizer-late='no-op-cgscc' \ ; RUN: -passes='default' -S %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O3 \ +; RUN: --check-prefix=${LLVM_CHECK_EXT} \ ; RUN: --check-prefix=CHECK-EP-CGSCC-LATE ; RUN: opt -disable-verify -debug-pass-manager \ ; RUN: -passes-ep-vectorizer-start='no-op-function' \ ; RUN: -passes='default' -S %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O3 \ +; RUN: --check-prefix=${LLVM_CHECK_EXT} \ ; RUN: --check-prefix=CHECK-EP-VECTORIZER-START ; RUN: opt -disable-verify -debug-pass-manager \ ; RUN: -passes-ep-pipeline-start='no-op-module' \ ; RUN: -passes='default' -S %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O3 \ +; RUN: --check-prefix=${LLVM_CHECK_EXT} \ ; RUN: --check-prefix=CHECK-EP-PIPELINE-START ; RUN: opt -disable-verify -debug-pass-manager \ ; RUN: -passes-ep-pipeline-start='no-op-module' \ ; RUN: -passes='lto-pre-link' -S %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O3 \ +; RUN: --check-prefix=${LLVM_CHECK_EXT} \ ; RUN: --check-prefix=CHECK-EP-PIPELINE-START ; RUN: opt -disable-verify -debug-pass-manager \ ; RUN: -passes-ep-optimizer-last='no-op-function' \ ; RUN: -passes='default' -S %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O3 \ +; RUN: --check-prefix=${LLVM_CHECK_EXT} \ ; RUN: --check-prefix=CHECK-EP-OPTIMIZER-LAST ; CHECK-O: Running analysis: PassInstrumentationAnalysis @@ -231,6 +246,7 @@ ; CHECK-O-NEXT: Starting llvm::Function pass manager run. ; CHECK-O-NEXT: Running pass: Float2IntPass ; CHECK-EP-VECTORIZER-START-NEXT: Running pass: NoOpFunctionPass +; CHECK-EXT: Running pass: {anonymous}::Bye on foo ; CHECK-O-NEXT: Running pass: FunctionToLoopPassAdaptor<{{.*}}LoopRotatePass ; CHECK-O-NEXT: Starting llvm::Function pass manager run. ; CHECK-O-NEXT: Running pass: LoopSimplifyPass Index: llvm/test/Other/new-pm-thinlto-defaults.ll =================================================================== --- llvm/test/Other/new-pm-thinlto-defaults.ll +++ llvm/test/Other/new-pm-thinlto-defaults.ll @@ -30,22 +30,22 @@ ; Postlink pipelines: ; RUN: opt -disable-verify -debug-pass-manager \ ; RUN: -passes='thinlto' -S %s 2>&1 \ -; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O1,CHECK-POSTLINK-O,CHECK-POSTLINK-O1 +; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O1,CHECK-POSTLINK-O,${LLVM_CHECK_EXT},CHECK-POSTLINK-O1 ; RUN: opt -disable-verify -debug-pass-manager \ ; RUN: -passes='thinlto' -S %s 2>&1 \ -; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O2,CHECK-POSTLINK-O,CHECK-POSTLINK-O2 +; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O2,CHECK-POSTLINK-O,${LLVM_CHECK_EXT},CHECK-POSTLINK-O2 ; RUN: opt -disable-verify -debug-pass-manager -passes-ep-pipeline-start='no-op-module' \ ; RUN: -passes='thinlto' -S %s 2>&1 \ -; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O3,CHECK-POSTLINK-O,CHECK-POSTLINK-O3 +; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O3,CHECK-POSTLINK-O,${LLVM_CHECK_EXT},CHECK-POSTLINK-O3 ; RUN: opt -disable-verify -debug-pass-manager \ ; RUN: -passes='thinlto' -S %s 2>&1 \ -; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-Os,CHECK-POSTLINK-O,CHECK-POSTLINK-Os +; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-Os,CHECK-POSTLINK-O,${LLVM_CHECK_EXT},CHECK-POSTLINK-Os ; RUN: opt -disable-verify -debug-pass-manager \ ; RUN: -passes='thinlto' -S %s 2>&1 \ -; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-Oz,CHECK-POSTLINK-O,CHECK-POSTLINK-Oz +; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-Oz,CHECK-POSTLINK-O,${LLVM_CHECK_EXT},CHECK-POSTLINK-Oz ; RUN: opt -disable-verify -debug-pass-manager -new-pm-debug-info-for-profiling \ ; RUN: -passes='thinlto' -S %s 2>&1 \ -; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O2,CHECK-POSTLINK-O,CHECK-POSTLINK-O2 +; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O2,CHECK-POSTLINK-O,${LLVM_CHECK_EXT},CHECK-POSTLINK-O2 ; ; CHECK-O: Running analysis: PassInstrumentationAnalysis ; CHECK-O-NEXT: Starting llvm::Module pass manager run. @@ -204,6 +204,7 @@ ; CHECK-POSTLINK-O-NEXT: Running pass: ModuleToFunctionPassAdaptor<{{.*}}PassManager{{.*}}> ; CHECK-POSTLINK-O-NEXT: Starting llvm::Function pass manager run. ; CHECK-POSTLINK-O-NEXT: Running pass: Float2IntPass +; CHECK-EXT: Running pass: {anonymous}::Bye ; CHECK-POSTLINK-O-NEXT: Running pass: FunctionToLoopPassAdaptor<{{.*}}LoopRotatePass ; CHECK-POSTLINK-O-NEXT: Starting llvm::Function pass manager run ; CHECK-POSTLINK-O-NEXT: Running pass: LoopSimplifyPass Index: llvm/test/Other/opt-O0-pipeline.ll =================================================================== --- llvm/test/Other/opt-O0-pipeline.ll +++ llvm/test/Other/opt-O0-pipeline.ll @@ -1,4 +1,4 @@ -; RUN: opt -mtriple=x86_64-- -O0 -debug-pass=Structure < %s -o /dev/null 2>&1 | FileCheck %s +; RUN: opt -mtriple=x86_64-- -O0 -debug-pass=Structure < %s -o /dev/null 2>&1 | FileCheck %s --check-prefixes=CHECK,${LLVM_CHECK_EXT} ; REQUIRES: asserts @@ -6,6 +6,7 @@ ; CHECK-NEXT: Target Transform Information ; CHECK-NEXT: FunctionPass Manager ; CHECK-NEXT: Module Verifier +; CHECK-EXT: Good Bye World Pass ; CHECK-NEXT: Instrument function entry/exit with calls to e.g. mcount() (pre inlining) ; CHECK-NEXT: Pass Arguments: ; CHECK-NEXT: Target Library Information Index: llvm/test/Other/opt-O2-pipeline.ll =================================================================== --- llvm/test/Other/opt-O2-pipeline.ll +++ llvm/test/Other/opt-O2-pipeline.ll @@ -1,4 +1,4 @@ -; RUN: opt -mtriple=x86_64-- -O2 -debug-pass=Structure < %s -o /dev/null 2>&1 | FileCheck %s +; RUN: opt -mtriple=x86_64-- -O2 -debug-pass=Structure < %s -o /dev/null 2>&1 | FileCheck --check-prefixes=CHECK-,${LLVM_CHECK_EXT} %s ; REQUIRES: asserts @@ -10,6 +10,8 @@ ; CHECK-NEXT: Target Library Information ; CHECK-NEXT: FunctionPass Manager ; CHECK-NEXT: Module Verifier +; CHECK-EXT: Good Bye World Pass +; CHECK-NOEXT-NOT: Good Bye World Pass ; CHECK-NEXT: Instrument function entry/exit with calls to e.g. mcount() (pre inlining) ; CHECK-NEXT: Simplify the CFG ; CHECK-NEXT: Dominator Tree Construction Index: llvm/test/Other/opt-O3-pipeline.ll =================================================================== --- llvm/test/Other/opt-O3-pipeline.ll +++ llvm/test/Other/opt-O3-pipeline.ll @@ -1,4 +1,4 @@ -; RUN: opt -mtriple=x86_64-- -O3 -debug-pass=Structure < %s -o /dev/null 2>&1 | FileCheck %s +; RUN: opt -mtriple=x86_64-- -O3 -debug-pass=Structure < %s -o /dev/null 2>&1 | FileCheck --check-prefixes=CHECK-,${LLVM_CHECK_EXT} %s ; REQUIRES: asserts @@ -10,6 +10,8 @@ ; CHECK-NEXT: Target Library Information ; CHECK-NEXT: FunctionPass Manager ; CHECK-NEXT: Module Verifier +; CHECK-EXT: Good Bye World Pass +; CHECK-NOEXT-NOT: Good Bye World Pass ; CHECK-NEXT: Instrument function entry/exit with calls to e.g. mcount() (pre inlining) ; CHECK-NEXT: Simplify the CFG ; CHECK-NEXT: Dominator Tree Construction Index: llvm/test/Other/opt-Os-pipeline.ll =================================================================== --- llvm/test/Other/opt-Os-pipeline.ll +++ llvm/test/Other/opt-Os-pipeline.ll @@ -1,4 +1,4 @@ -; RUN: opt -mtriple=x86_64-- -Os -debug-pass=Structure < %s -o /dev/null 2>&1 | FileCheck %s +; RUN: opt -mtriple=x86_64-- -Os -debug-pass=Structure < %s -o /dev/null 2>&1 | FileCheck --check-prefixes=CHECK-,${LLVM_CHECK_EXT} %s ; REQUIRES: asserts @@ -10,6 +10,8 @@ ; CHECK-NEXT: Target Library Information ; CHECK-NEXT: FunctionPass Manager ; CHECK-NEXT: Module Verifier +; CHECK-EXT: Good Bye World Pass +; CHECK-NOEXT-NOT: Good Bye World Pass ; CHECK-NEXT: Instrument function entry/exit with calls to e.g. mcount() (pre inlining) ; CHECK-NEXT: Simplify the CFG ; CHECK-NEXT: Dominator Tree Construction Index: llvm/test/lit.cfg.py =================================================================== --- llvm/test/lit.cfg.py +++ llvm/test/lit.cfg.py @@ -190,6 +190,11 @@ if config.has_plugins: config.available_features.add('plugins') +if config.linked_bye_extension: + llvm_config.with_environment('LLVM_CHECK_EXT', 'CHECK-EXT') +else: + llvm_config.with_environment('LLVM_CHECK_EXT', 'CHECK-NOEXT') + # Static libraries are not built if BUILD_SHARED_LIBS is ON. if not config.build_shared_libs and not config.link_llvm_dylib: config.available_features.add('static-libs') Index: llvm/test/lit.site.cfg.py.in =================================================================== --- llvm/test/lit.site.cfg.py.in +++ llvm/test/lit.site.cfg.py.in @@ -46,6 +46,7 @@ config.have_opt_viewer_modules = @LLVM_HAVE_OPT_VIEWER_MODULES@ config.libcxx_used = @LLVM_LIBCXX_USED@ config.has_plugins = @LLVM_ENABLE_PLUGINS@ +config.linked_bye_extension = "@LLVM_BYE_LINK_INTO_TOOLS@".lower() in ("on", 1) # Support substitution of the tools_dir with user parameters. This is # used when we can't determine the tool dir at configuration time. Index: llvm/tools/CMakeLists.txt =================================================================== --- llvm/tools/CMakeLists.txt +++ llvm/tools/CMakeLists.txt @@ -9,14 +9,6 @@ # traversing each directory. create_llvm_tool_options() -# Build polly before the tools: the tools link against polly when -# LINK_POLLY_INTO_TOOLS is set. -if(WITH_POLLY) - add_llvm_external_project(polly) -else() - set(LLVM_TOOL_POLLY_BUILD Off) -endif() - if(NOT LLVM_BUILD_LLVM_DYLIB AND NOT LLVM_BUILD_LLVM_C_DYLIB) set(LLVM_TOOL_LLVM_SHLIB_BUILD Off) endif() @@ -50,6 +42,8 @@ # file as external projects. add_llvm_implicit_projects() +add_llvm_external_project(polly) + # Add subprojects specified using LLVM_EXTERNAL_PROJECTS foreach(p ${LLVM_EXTERNAL_PROJECTS}) add_llvm_external_project(${p}) Index: llvm/tools/bugpoint/CMakeLists.txt =================================================================== --- llvm/tools/bugpoint/CMakeLists.txt +++ llvm/tools/bugpoint/CMakeLists.txt @@ -35,13 +35,9 @@ ToolRunner.cpp bugpoint.cpp + ENABLE_PLUGINS + DEPENDS intrinsics_gen ) export_executable_symbols(bugpoint) - -if(WITH_POLLY AND LINK_POLLY_INTO_TOOLS) - target_link_libraries(bugpoint PRIVATE Polly) - # Ensure LLVMTarget can resolve dependences in Polly. - target_link_libraries(bugpoint PRIVATE LLVMTarget) -endif(WITH_POLLY AND LINK_POLLY_INTO_TOOLS) Index: llvm/tools/bugpoint/bugpoint.cpp =================================================================== --- llvm/tools/bugpoint/bugpoint.cpp +++ llvm/tools/bugpoint/bugpoint.cpp @@ -109,12 +109,6 @@ }; } -#ifdef LINK_POLLY_INTO_TOOLS -namespace polly { -void initializePollyPasses(llvm::PassRegistry &Registry); -} -#endif - int main(int argc, char **argv) { #ifndef DEBUG_BUGPOINT InitLLVM X(argc, argv); @@ -134,10 +128,6 @@ initializeInstrumentation(Registry); initializeTarget(Registry); -#ifdef LINK_POLLY_INTO_TOOLS - polly::initializePollyPasses(Registry); -#endif - if (std::getenv("bar") == (char*) -1) { InitializeAllTargets(); InitializeAllTargetMCs(); Index: llvm/tools/opt/CMakeLists.txt =================================================================== --- llvm/tools/opt/CMakeLists.txt +++ llvm/tools/opt/CMakeLists.txt @@ -37,11 +37,9 @@ PrintSCC.cpp opt.cpp + ENABLE_PLUGINS + DEPENDS intrinsics_gen ) export_executable_symbols(opt) - -if(WITH_POLLY AND LINK_POLLY_INTO_TOOLS) - target_link_libraries(opt PRIVATE Polly) -endif(WITH_POLLY AND LINK_POLLY_INTO_TOOLS) Index: llvm/tools/opt/NewPMDriver.cpp =================================================================== --- llvm/tools/opt/NewPMDriver.cpp +++ llvm/tools/opt/NewPMDriver.cpp @@ -202,11 +202,9 @@ }); } -#ifdef LINK_POLLY_INTO_TOOLS -namespace polly { -void RegisterPollyPasses(PassBuilder &); -} -#endif +#define HANDLE_EXTENSION(Ext) \ + llvm::PassPluginLibraryInfo get##Ext##PluginInfo(); +#include "llvm/Support/Extension.def" bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM, ToolOutputFile *Out, ToolOutputFile *ThinLTOLinkOut, @@ -290,9 +288,9 @@ return false; }); -#ifdef LINK_POLLY_INTO_TOOLS - polly::RegisterPollyPasses(PB); -#endif +#define HANDLE_EXTENSION(Ext) \ + get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB); +#include "llvm/Support/Extension.def" // Specially handle the alias analysis manager so that we can register // a custom pipeline of AA passes with it. Index: llvm/tools/opt/opt.cpp =================================================================== --- llvm/tools/opt/opt.cpp +++ llvm/tools/opt/opt.cpp @@ -476,12 +476,6 @@ getCodeModel(), GetCodeGenOptLevel()); } -#ifdef LINK_POLLY_INTO_TOOLS -namespace polly { -void initializePollyPasses(llvm::PassRegistry &Registry); -} -#endif - //===----------------------------------------------------------------------===// // main for opt // @@ -537,10 +531,6 @@ initializeWriteBitcodePassPass(Registry); initializeHardwareLoopsPass(Registry); -#ifdef LINK_POLLY_INTO_TOOLS - polly::initializePollyPasses(Registry); -#endif - cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .bc modular optimizer and analysis printer\n"); Index: llvm/utils/gn/secondary/llvm/include/llvm/Config/BUILD.gn =================================================================== --- llvm/utils/gn/secondary/llvm/include/llvm/Config/BUILD.gn +++ llvm/utils/gn/secondary/llvm/include/llvm/Config/BUILD.gn @@ -323,7 +323,6 @@ output = "$target_gen_dir/llvm-config.h" values = [ "LLVM_ENABLE_DUMP=", - "LINK_POLLY_INTO_TOOLS=", "LLVM_DEFAULT_TARGET_TRIPLE=$llvm_target_triple", "LLVM_HAS_ATOMICS=1", "LLVM_HOST_TRIPLE=$llvm_current_triple", Index: polly/include/polly/RegisterPasses.h =================================================================== --- polly/include/polly/RegisterPasses.h +++ polly/include/polly/RegisterPasses.h @@ -22,6 +22,5 @@ namespace polly { void initializePollyPasses(llvm::PassRegistry &Registry); -void registerPollyPasses(llvm::legacy::PassManagerBase &PM); } // namespace polly #endif Index: polly/lib/CMakeLists.txt =================================================================== --- polly/lib/CMakeLists.txt +++ polly/lib/CMakeLists.txt @@ -23,7 +23,7 @@ # Use an object-library to add the same files to multiple libs without requiring # the sources them to be recompiled for each of them. -add_library(PollyCore OBJECT +add_llvm_pass_plugin(Polly Analysis/DependenceInfo.cpp Analysis/PolyhedralInfo.cpp Analysis/ScopDetection.cpp @@ -70,13 +70,13 @@ Transform/ScopInliner.cpp ${POLLY_HEADER_FILES} ) -set_target_properties(PollyCore PROPERTIES FOLDER "Polly") +set_target_properties(obj.Polly PROPERTIES FOLDER "Polly") +set_target_properties(Polly PROPERTIES FOLDER "Polly") # Create the library that can be linked into LLVM's tools and Polly's unittests. # It depends on all library it needs, such that with # LLVM_POLLY_LINK_INTO_TOOLS=ON, its dependencies like PollyISL are linked as # well. -add_polly_library(Polly $) target_link_libraries(Polly PUBLIC ${ISL_TARGET} ) @@ -124,6 +124,9 @@ LLVMTarget LLVMVectorize ) + + # Polly-ACC requires the NVPTX target to be present in the executable it is linked to + set_property(TARGET bugpoint APPEND PROPERTY LINK_LIBRARIES LLVMTarget) endif () # Create a loadable module Polly.so that can be loaded using @@ -134,8 +137,7 @@ set_target_properties(LLVMPolly PROPERTIES FOLDER "Polly") else () add_polly_loadable_module(LLVMPolly - Polly.cpp - $ + $ ) # Only add the dependencies that are not part of LLVM. The latter are assumed @@ -159,5 +161,5 @@ if (TARGET intrinsics_gen) # Check if we are building as part of an LLVM build - add_dependencies(PollyCore intrinsics_gen) + add_dependencies(obj.Polly intrinsics_gen) endif() Index: polly/lib/Polly.cpp =================================================================== --- polly/lib/Polly.cpp +++ /dev/null @@ -1,29 +0,0 @@ -//===---------- Polly.cpp - Initialize the Polly Module -------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -//===----------------------------------------------------------------------===// - -#include "polly/RegisterPasses.h" -#include "llvm/PassRegistry.h" - -namespace { - -/// Initialize Polly passes when library is loaded. -/// -/// We use the constructor of a statically declared object to initialize the -/// different Polly passes right after the Polly library is loaded. This ensures -/// that the Polly passes are available e.g. in the 'opt' tool. -class StaticInitializer { -public: - StaticInitializer() { - llvm::PassRegistry &Registry = *llvm::PassRegistry::getPassRegistry(); - polly::initializePollyPasses(Registry); - } -}; -static StaticInitializer InitializeEverything; -} // end of anonymous namespace. Index: polly/lib/Support/RegisterPasses.cpp =================================================================== --- polly/lib/Support/RegisterPasses.cpp +++ polly/lib/Support/RegisterPasses.cpp @@ -701,9 +701,28 @@ } } // namespace polly -// Plugin Entrypoint: -extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK -llvmGetPassPluginInfo() { +/// Initialize Polly passes when library is loaded (shared library mode) or +/// linked into executable (static library mode) +/// +/// We use the constructor of a statically declared object to initialize the +/// different Polly passes right after the Polly library is loaded. This ensures +/// that the Polly passes are available e.g. in the 'opt' tool. + +class StaticInitializer { +public: + StaticInitializer() { + llvm::PassRegistry &Registry = *llvm::PassRegistry::getPassRegistry(); + polly::initializePollyPasses(Registry); + } +}; +static StaticInitializer InitializeEverything; + +// Pass Plugin Entrypoints +llvm::PassPluginLibraryInfo getPollyPluginInfo() { return {LLVM_PLUGIN_API_VERSION, "Polly", LLVM_VERSION_STRING, polly::RegisterPollyPasses}; } + +extern "C" ::llvm::PassPluginLibraryInfo llvmGetPassPluginInfo() { + return getPollyPluginInfo(); +} Index: polly/test/Unit/lit.site.cfg.in =================================================================== --- polly/test/Unit/lit.site.cfg.in +++ polly/test/Unit/lit.site.cfg.in @@ -13,7 +13,7 @@ config.shlibdir = "@SHLIBDIR@" config.target_triple = "@TARGET_TRIPLE@" config.enable_gpgpu_codegen = "@GPU_CODEGEN@" -config.link_polly_into_tools = "@LINK_POLLY_INTO_TOOLS@" +config.llvm_polly_link_into_tools = "@LLVM_POLLY_LINK_INTO_TOOLS@" config.has_unittests = @POLLY_GTEST_AVAIL@ # Support substitution of the tools_dir, libs_dirs, and build_mode with user Index: polly/test/lit.site.cfg.in =================================================================== --- polly/test/lit.site.cfg.in +++ polly/test/lit.site.cfg.in @@ -8,7 +8,7 @@ config.polly_lib_dir = "@POLLY_LIB_DIR@" config.target_triple = "@TARGET_TRIPLE@" config.enable_gpgpu_codegen = "@GPU_CODEGEN@" -config.link_polly_into_tools = "@LINK_POLLY_INTO_TOOLS@" +config.llvm_polly_link_into_tools = "@LLVM_POLLY_LINK_INTO_TOOLS@" config.targets_to_build = "@TARGETS_TO_BUILD@" config.extra_paths = "@POLLY_TEST_EXTRA_PATHS@".split(";") @@ -36,14 +36,14 @@ # directories. config.excludes = ['Inputs'] -if config.link_polly_into_tools == '' or \ - config.link_polly_into_tools.lower() == '0' or \ - config.link_polly_into_tools.lower() == 'n' or \ - config.link_polly_into_tools.lower() == 'no' or \ - config.link_polly_into_tools.lower() == 'off' or \ - config.link_polly_into_tools.lower() == 'false' or \ - config.link_polly_into_tools.lower() == 'notfound' or \ - config.link_polly_into_tools.lower() == 'link_polly_into_tools-notfound': +if config.llvm_polly_link_into_tools == '' or \ + config.llvm_polly_link_into_tools.lower() == '0' or \ + config.llvm_polly_link_into_tools.lower() == 'n' or \ + config.llvm_polly_link_into_tools.lower() == 'no' or \ + config.llvm_polly_link_into_tools.lower() == 'off' or \ + config.llvm_polly_link_into_tools.lower() == 'false' or \ + config.llvm_polly_link_into_tools.lower() == 'notfound' or \ + config.llvm_polly_link_into_tools.lower() == 'llvm_polly_link_into_tools-notfound': config.substitutions.append(('%loadPolly', '-load ' + config.polly_lib_dir + '/LLVMPolly@LLVM_SHLIBEXT@' + ' -load-pass-plugin ' Index: polly/test/update_check.py =================================================================== --- polly/test/update_check.py +++ polly/test/update_check.py @@ -15,7 +15,7 @@ polly_lib_dir = '''@POLLY_LIB_DIR@''' shlibext = '''@LLVM_SHLIBEXT@''' llvm_tools_dir = '''@LLVM_TOOLS_DIR@''' -link_polly_into_tools = not '''@LINK_POLLY_INTO_TOOLS@'''.lower() in {'','0','n','no','off','false','notfound','link_polly_into_tools-notfound'} +llvm_polly_link_into_tools = not '''@LLVM_POLLY_LINK_INTO_TOOLS@'''.lower() in {'','0','n','no','off','false','notfound','llvm_polly_link_into_tools-notfound'} runre = re.compile(r'\s*\;\s*RUN\s*\:(?P.*)') filecheckre = re.compile(r'\s*(?P.*)\|\s*(?PFileCheck\s[^|]*)') @@ -298,7 +298,7 @@ toolarg = toolarg.replace('%s', filename) toolarg = toolarg.replace('%S', os.path.dirname(filename)) if toolarg == '%loadPolly': - if not link_polly_into_tools: + if not llvm_polly_link_into_tools: newtool += ['-load',os.path.join(polly_lib_dir,'LLVMPolly' + shlibext)] newtool.append('-polly-process-unprofitable') newtool.append('-polly-remarks-minimal')