Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt
+++ CMakeLists.txt
@@ -492,28 +492,33 @@
 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)
+set(LLVM_ALL_EXTENSION_LIBS "Polly")
+set(LLVM_EXTENSION_LIBS "" CACHE STRING
+	"Semicolon-separated list of extensions to link into tools, or \"all\"")
+
+if(LLVM_ENABLE_PROJECTS STREQUAL "all")
+    set(LLVM_ENABLE_PROJECTS "")
+    foreach(llvm_extension_lib ${LLVM_ALL_EXTENSION_LIBS})
+        string(TOLOWER ${llvm_extension_lib} llvm_extension_dir)
+        if (exists ${LLVM_MAIN_SRC_DIR}/tools/${llvm_extension_dir}/CMakeLists.txt)
+            list(APPEND LLVM_ENABLE_PROJECTS ${llvm_extension_lib})
+        endif()
+    endforeach()
 endif()
 
-if (LLVM_POLLY_BUILD AND POLLY_IN_TREE)
-  set(WITH_POLLY ON)
-else()
-  set(WITH_POLLY OFF)
-endif()
+# load extra configuration variables from extensions
+foreach(llvm_extension_lib ${LLVM_EXTENSION_LIBS})
+    string(TOLOWER ${llvm_extension_lib} llvm_extension_dir)
+    include(${LLVM_MAIN_SRC_DIR}/tools/${llvm_extension_dir}/cmake/extension.cmake OPTIONAL)
+endforeach()
 
-if (LLVM_POLLY_LINK_INTO_TOOLS AND WITH_POLLY)
-  set(LINK_POLLY_INTO_TOOLS ON)
-else()
-  set(LINK_POLLY_INTO_TOOLS OFF)
-endif()
+# generate xfor file for extension handling
+file(WRITE "${CMAKE_BINARY_DIR}/include/llvm/Support/Extension.def" "//extension handlers\n")
+foreach(llvm_extension_lib ${LLVM_EXTENSION_LIBS})
+    string(TOLOWER ${llvm_extension_lib} llvm_extension_namespace)
+    file(APPEND "${CMAKE_BINARY_DIR}/include/llvm/Support/Extension.def" "HANDLE_EXTENSION(${llvm_extension_namespace}, ${llvm_extension_lib})\n")
+endforeach()
+file(APPEND "${CMAKE_BINARY_DIR}/include/llvm/Support/Extension.def" "#undef HANDLE_EXTENSION\n")
 
 # Define an option controlling whether we should build for 32-bit on 64-bit
 # platforms, where supported.
Index: include/llvm/Config/llvm-config.h.cmake
===================================================================
--- include/llvm/Config/llvm-config.h.cmake
+++ 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: tools/CMakeLists.txt
===================================================================
--- tools/CMakeLists.txt
+++ tools/CMakeLists.txt
@@ -9,13 +9,11 @@
 # 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()
+# Build extensions before the tools: the tools link against extension libs
+foreach(llvm_extension_lib ${LLVM_EXTENSION_LIBS})
+    string(TOLOWER ${llvm_extension_lib} llvm_project_name)
+    add_llvm_external_project(${llvm_project_name})
+endforeach()
 
 if(NOT LLVM_BUILD_LLVM_DYLIB AND NOT LLVM_BUILD_LLVM_C_DYLIB)
   set(LLVM_TOOL_LLVM_SHLIB_BUILD Off)
@@ -55,4 +53,11 @@
   add_llvm_external_project(${p})
 endforeach(p)
 
+# Also add extension libs not listed in LLVM_EXTERNAL_PROJECTS
+foreach(p ${LLVM_EXTENSION_LIBS})
+    if(NOT ${p} IN_LIST LLVM_EXTERNAL_PROJECTS)
+        add_llvm_external_project(${p})
+    endif()
+endforeach(p)
+
 set(LLVM_COMMON_DEPENDS ${LLVM_COMMON_DEPENDS} PARENT_SCOPE)
Index: tools/bugpoint/CMakeLists.txt
===================================================================
--- tools/bugpoint/CMakeLists.txt
+++ tools/bugpoint/CMakeLists.txt
@@ -37,8 +37,6 @@
   )
 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)
+if(LLVM_EXTENSION_LIBS)
+    target_link_libraries(bugpoint PRIVATE ${LLVM_EXTENSION_LIBS} ${LLVM_EXTENSION_BUGPOINT_LIBS})
+endif()
Index: tools/bugpoint/bugpoint.cpp
===================================================================
--- tools/bugpoint/bugpoint.cpp
+++ tools/bugpoint/bugpoint.cpp
@@ -109,11 +109,8 @@
 };
 }
 
-#ifdef LINK_POLLY_INTO_TOOLS
-namespace polly {
-void initializePollyPasses(llvm::PassRegistry &Registry);
-}
-#endif
+#define HANDLE_EXTENSION(Ns, Ext) namespace Ns { void initialize##Ext##Passes(llvm::PassRegistry &Registry); }
+#include "llvm/Support/Extension.def"
 
 int main(int argc, char **argv) {
 #ifndef DEBUG_BUGPOINT
@@ -134,9 +131,8 @@
   initializeInstrumentation(Registry);
   initializeTarget(Registry);
 
-#ifdef LINK_POLLY_INTO_TOOLS
-  polly::initializePollyPasses(Registry);
-#endif
+#define HANDLE_EXTENSION(Ns, Ext) Ns::initialize##Ext##Passes(Registry);
+#include "llvm/Support/Extension.def"
 
   if (std::getenv("bar") == (char*) -1) {
     InitializeAllTargets();
Index: tools/clang/tools/driver/CMakeLists.txt
===================================================================
--- tools/clang/tools/driver/CMakeLists.txt
+++ tools/clang/tools/driver/CMakeLists.txt
@@ -123,6 +123,6 @@
   endif()
 endif()
 
-if(WITH_POLLY AND LINK_POLLY_INTO_TOOLS)
-  target_link_libraries(clang PRIVATE Polly)
-endif(WITH_POLLY AND LINK_POLLY_INTO_TOOLS)
+if(LLVM_EXTENSION_LIBS)
+    target_link_libraries(clang PRIVATE ${LLVM_EXTENSION_LIBS} ${LLVM_EXTENSION_CLANG_LIBS})
+endif()
Index: tools/clang/tools/driver/cc1_main.cpp
===================================================================
--- tools/clang/tools/driver/cc1_main.cpp
+++ tools/clang/tools/driver/cc1_main.cpp
@@ -69,11 +69,8 @@
   exit(GenCrashDiag ? 70 : 1);
 }
 
-#ifdef LINK_POLLY_INTO_TOOLS
-namespace polly {
-void initializePollyPasses(llvm::PassRegistry &Registry);
-}
-#endif
+#define HANDLE_EXTENSION(Ns, Ext) namespace Ns { void initialize##Ext##Passes(llvm::PassRegistry &Registry); }
+#include "llvm/Support/Extension.def"
 
 #ifdef CLANG_HAVE_RLIMITS
 #if defined(__linux__) && defined(__PIE__)
@@ -183,10 +180,8 @@
   llvm::InitializeAllAsmPrinters();
   llvm::InitializeAllAsmParsers();
 
-#ifdef LINK_POLLY_INTO_TOOLS
-  llvm::PassRegistry &Registry = *llvm::PassRegistry::getPassRegistry();
-  polly::initializePollyPasses(Registry);
-#endif
+#define HANDLE_EXTENSION(Ns, Ext) { llvm::PassRegistry &Registry = *llvm::PassRegistry::getPassRegistry(); Ns::initialize##Ext##Passes(Registry); }
+#include "llvm/Support/Extension.def"
 
   // Buffer diagnostics from argument parsing so that we can output them using a
   // well formed diagnostic object.
Index: tools/opt/CMakeLists.txt
===================================================================
--- tools/opt/CMakeLists.txt
+++ tools/opt/CMakeLists.txt
@@ -38,6 +38,6 @@
   )
 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)
+if(LLVM_EXTENSION_LIBS)
+    target_link_libraries(opt PRIVATE ${LLVM_EXTENSION_LIBS} ${LLVM_EXTENSION_OPT_LIBS})
+endif()
Index: tools/opt/NewPMDriver.cpp
===================================================================
--- tools/opt/NewPMDriver.cpp
+++ tools/opt/NewPMDriver.cpp
@@ -202,11 +202,8 @@
         });
 }
 
-#ifdef LINK_POLLY_INTO_TOOLS
-namespace polly {
-void RegisterPollyPasses(PassBuilder &);
-}
-#endif
+#define HANDLE_EXTENSION(Ns, Ext) namespace Ns { void Register##Ext##Passes(PassBuilder &); }
+#include "llvm/Support/Extension.def"
 
 bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM,
                            ToolOutputFile *Out, ToolOutputFile *ThinLTOLinkOut,
@@ -290,9 +287,8 @@
         return false;
       });
 
-#ifdef LINK_POLLY_INTO_TOOLS
-  polly::RegisterPollyPasses(PB);
-#endif
+#define HANDLE_EXTENSION(Ns, Ext) Ns::Register##Ext##Passes(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: tools/opt/opt.cpp
===================================================================
--- tools/opt/opt.cpp
+++ tools/opt/opt.cpp
@@ -470,11 +470,8 @@
                                         getCodeModel(), GetCodeGenOptLevel());
 }
 
-#ifdef LINK_POLLY_INTO_TOOLS
-namespace polly {
-void initializePollyPasses(llvm::PassRegistry &Registry);
-}
-#endif
+#define HANDLE_EXTENSION(Ns, Ext) namespace Ns { void initialize##Ext##Passes(llvm::PassRegistry &Registry); }
+#include "llvm/Support/Extension.def"
 
 //===----------------------------------------------------------------------===//
 // main for opt
@@ -529,9 +526,8 @@
   initializeWasmEHPreparePass(Registry);
   initializeWriteBitcodePassPass(Registry);
 
-#ifdef LINK_POLLY_INTO_TOOLS
-  polly::initializePollyPasses(Registry);
-#endif
+#define HANDLE_EXTENSION(Ns, Ext) Ns::initialize##Ext##Passes(Registry);
+#include "llvm/Support/Extension.def"
 
   cl::ParseCommandLineOptions(argc, argv,
     "llvm .bc -> .bc modular optimizer and analysis printer\n");
Index: tools/polly/cmake/extension.cmake
===================================================================
--- tools/polly/cmake/extension.cmake
+++ tools/polly/cmake/extension.cmake
@@ -0,0 +1,2 @@
+# register per-tool extra dependencies here
+list(APPEND LLVM_EXTENSION_BUGPOINT_LIBS LLVMTarget)
Index: utils/gn/secondary/llvm/include/llvm/Config/BUILD.gn
===================================================================
--- utils/gn/secondary/llvm/include/llvm/Config/BUILD.gn
+++ utils/gn/secondary/llvm/include/llvm/Config/BUILD.gn
@@ -321,7 +321,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",