[Mlir-commits] [mlir] c3efb75 - Revert "[mlir] Remove uses of LLVM's legacy pass manager"

Arthur Eubanks llvmlistbot at llvm.org
Mon Apr 11 16:45:49 PDT 2022


Author: Arthur Eubanks
Date: 2022-04-11T16:45:19-07:00
New Revision: c3efb75061ce0cdec85f691bafc6d658ca587102

URL: https://github.com/llvm/llvm-project/commit/c3efb75061ce0cdec85f691bafc6d658ca587102
DIFF: https://github.com/llvm/llvm-project/commit/c3efb75061ce0cdec85f691bafc6d658ca587102.diff

LOG: Revert "[mlir] Remove uses of LLVM's legacy pass manager"

This reverts commit b0f7f6f78d050cc89b31c87fb48744989145af60.

Causes test failures: https://lab.llvm.org/buildbot#builders/61/builds/24879

Added: 
    

Modified: 
    mlir/include/mlir/ExecutionEngine/OptUtils.h
    mlir/lib/CAPI/ExecutionEngine/ExecutionEngine.cpp
    mlir/lib/ExecutionEngine/CMakeLists.txt
    mlir/lib/ExecutionEngine/JitRunner.cpp
    mlir/lib/ExecutionEngine/OptUtils.cpp
    mlir/tools/mlir-cpu-runner/mlir-cpu-runner.cpp
    mlir/tools/mlir-spirv-cpu-runner/mlir-spirv-cpu-runner.cpp
    mlir/tools/mlir-vulkan-runner/mlir-vulkan-runner.cpp

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/ExecutionEngine/OptUtils.h b/mlir/include/mlir/ExecutionEngine/OptUtils.h
index 4cee8c6d60ff1..b5c4e2d3b3005 100644
--- a/mlir/include/mlir/ExecutionEngine/OptUtils.h
+++ b/mlir/include/mlir/ExecutionEngine/OptUtils.h
@@ -14,6 +14,8 @@
 #ifndef MLIR_EXECUTIONENGINE_OPTUTILS_H
 #define MLIR_EXECUTIONENGINE_OPTUTILS_H
 
+#include "llvm/Pass.h"
+
 #include <functional>
 #include <string>
 
@@ -25,6 +27,10 @@ class TargetMachine;
 
 namespace mlir {
 
+/// Initialize LLVM passes that can be used when running MLIR code using
+/// ExecutionEngine.
+void initializeLLVMPasses();
+
 /// Create a module transformer function for MLIR ExecutionEngine that runs
 /// LLVM IR passes corresponding to the given speed and size optimization
 /// levels (e.g. -O2 or -Os). If not null, `targetMachine` is used to
@@ -34,6 +40,18 @@ std::function<llvm::Error(llvm::Module *)>
 makeOptimizingTransformer(unsigned optLevel, unsigned sizeLevel,
                           llvm::TargetMachine *targetMachine);
 
+/// Create a module transformer function for MLIR ExecutionEngine that runs
+/// LLVM IR passes explicitly specified, plus an optional optimization level,
+/// Any optimization passes, if present, will be inserted before the pass at
+/// position optPassesInsertPos. If not null, `targetMachine` is used to
+/// initialize passes that provide target-specific information to the LLVM
+/// optimizer. `targetMachine` must outlive the returned std::function.
+std::function<llvm::Error(llvm::Module *)>
+makeLLVMPassesTransformer(llvm::ArrayRef<const llvm::PassInfo *> llvmPasses,
+                          llvm::Optional<unsigned> mbOptLevel,
+                          llvm::TargetMachine *targetMachine,
+                          unsigned optPassesInsertPos = 0);
+
 } // namespace mlir
 
 #endif // MLIR_EXECUTIONENGINE_OPTUTILS_H

diff  --git a/mlir/lib/CAPI/ExecutionEngine/ExecutionEngine.cpp b/mlir/lib/CAPI/ExecutionEngine/ExecutionEngine.cpp
index 2190566b22b13..4c55530870df7 100644
--- a/mlir/lib/CAPI/ExecutionEngine/ExecutionEngine.cpp
+++ b/mlir/lib/CAPI/ExecutionEngine/ExecutionEngine.cpp
@@ -48,8 +48,8 @@ mlirExecutionEngineCreate(MlirModule op, int optLevel, int numPaths,
   // Create a transformer to run all LLVM optimization passes at the
   // specified optimization level.
   auto llvmOptLevel = static_cast<llvm::CodeGenOpt::Level>(optLevel);
-  auto transformer = mlir::makeOptimizingTransformer(
-      llvmOptLevel, /*sizeLevel=*/0, /*targetMachine=*/tmOrError->get());
+  auto transformer = mlir::makeLLVMPassesTransformer(
+      /*passes=*/{}, llvmOptLevel, /*targetMachine=*/tmOrError->get());
   ExecutionEngineOptions jitOptions;
   jitOptions.transformer = transformer;
   jitOptions.jitCodeGenOptLevel = llvmOptLevel;

diff  --git a/mlir/lib/ExecutionEngine/CMakeLists.txt b/mlir/lib/ExecutionEngine/CMakeLists.txt
index e1f30470a9fd6..8776d6f7e5d8f 100644
--- a/mlir/lib/ExecutionEngine/CMakeLists.txt
+++ b/mlir/lib/ExecutionEngine/CMakeLists.txt
@@ -52,7 +52,6 @@ add_mlir_library(MLIRExecutionEngine
   TransformUtils
   nativecodegen
   IPO
-  Passes
   ${LLVM_JIT_LISTENER_LIB}
 
   LINK_LIBS PUBLIC

diff  --git a/mlir/lib/ExecutionEngine/JitRunner.cpp b/mlir/lib/ExecutionEngine/JitRunner.cpp
index 5e738002728dd..f61710f390acd 100644
--- a/mlir/lib/ExecutionEngine/JitRunner.cpp
+++ b/mlir/lib/ExecutionEngine/JitRunner.cpp
@@ -57,6 +57,10 @@ struct Options {
 
   llvm::cl::OptionCategory optFlags{"opt-like flags"};
 
+  // CLI list of pass information
+  llvm::cl::list<const llvm::PassInfo *, bool, llvm::PassNameParser> llvmPasses{
+      llvm::cl::desc("LLVM optimizing passes to run"), llvm::cl::cat(optFlags)};
+
   // CLI variables for -On options.
   llvm::cl::opt<bool> optO0{"O0",
                             llvm::cl::desc("Run opt passes and codegen at O0"),
@@ -318,6 +322,27 @@ int mlir::JitRunnerMain(int argc, char **argv, const DialectRegistry &registry,
   Optional<unsigned> optLevel = getCommandLineOptLevel(options);
   SmallVector<std::reference_wrapper<llvm::cl::opt<bool>>, 4> optFlags{
       options.optO0, options.optO1, options.optO2, options.optO3};
+  unsigned optCLIPosition = 0;
+  // Determine if there is an optimization flag present, and its CLI position
+  // (optCLIPosition).
+  for (unsigned j = 0; j < 4; ++j) {
+    auto &flag = optFlags[j].get();
+    if (flag) {
+      optCLIPosition = flag.getPosition();
+      break;
+    }
+  }
+  // Generate vector of pass information, plus the index at which we should
+  // insert any optimization passes in that vector (optPosition).
+  SmallVector<const llvm::PassInfo *, 4> passes;
+  unsigned optPosition = 0;
+  for (unsigned i = 0, e = options.llvmPasses.size(); i < e; ++i) {
+    passes.push_back(options.llvmPasses[i]);
+    if (optCLIPosition < options.llvmPasses.getPosition(i)) {
+      optPosition = i;
+      optCLIPosition = UINT_MAX; // To ensure we never insert again
+    }
+  }
 
   MLIRContext context(registry);
 
@@ -342,11 +367,11 @@ int mlir::JitRunnerMain(int argc, char **argv, const DialectRegistry &registry,
     return EXIT_FAILURE;
   }
 
+  auto transformer = mlir::makeLLVMPassesTransformer(
+      passes, optLevel, /*targetMachine=*/tmOrError->get(), optPosition);
+
   CompileAndExecuteConfig compileAndExecuteConfig;
-  if (optLevel) {
-    compileAndExecuteConfig.transformer = mlir::makeOptimizingTransformer(
-        *optLevel, /*sizeLevel=*/0, /*targetMachine=*/tmOrError->get());
-  }
+  compileAndExecuteConfig.transformer = transformer;
   compileAndExecuteConfig.llvmModuleBuilder = config.llvmModuleBuilder;
   compileAndExecuteConfig.runtimeSymbolMap = config.runtimesymbolMap;
 

diff  --git a/mlir/lib/ExecutionEngine/OptUtils.cpp b/mlir/lib/ExecutionEngine/OptUtils.cpp
index 33b52aadf9c48..53ad7fd66a9af 100644
--- a/mlir/lib/ExecutionEngine/OptUtils.cpp
+++ b/mlir/lib/ExecutionEngine/OptUtils.cpp
@@ -13,76 +13,135 @@
 
 #include "mlir/ExecutionEngine/OptUtils.h"
 
+#include "llvm/ADT/ArrayRef.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/IR/LegacyPassNameParser.h"
 #include "llvm/IR/Module.h"
-#include "llvm/Passes/OptimizationLevel.h"
-#include "llvm/Passes/PassBuilder.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Error.h"
-#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/StringSaver.h"
 #include "llvm/Target/TargetMachine.h"
+#include "llvm/Transforms/Coroutines.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#include <climits>
+#include <mutex>
 
-using namespace llvm;
-
-static Optional<OptimizationLevel> mapToLevel(unsigned optLevel,
-                                              unsigned sizeLevel) {
-  switch (optLevel) {
-  case 0:
-    return OptimizationLevel::O0;
+// Run the module and function passes managed by the module manager.
+static void runPasses(llvm::legacy::PassManager &modulePM,
+                      llvm::legacy::FunctionPassManager &funcPM,
+                      llvm::Module &m) {
+  funcPM.doInitialization();
+  for (auto &func : m) {
+    funcPM.run(func);
+  }
+  funcPM.doFinalization();
+  modulePM.run(m);
+}
 
-  case 1:
-    return OptimizationLevel::O1;
+// Initialize basic LLVM transformation passes under lock.
+void mlir::initializeLLVMPasses() {
+  static std::mutex mutex;
+  std::lock_guard<std::mutex> lock(mutex);
 
-  case 2:
-    switch (sizeLevel) {
-    case 0:
-      return OptimizationLevel::O2;
+  auto &registry = *llvm::PassRegistry::getPassRegistry();
+  llvm::initializeCore(registry);
+  llvm::initializeTransformUtils(registry);
+  llvm::initializeScalarOpts(registry);
+  llvm::initializeIPO(registry);
+  llvm::initializeInstCombine(registry);
+  llvm::initializeAggressiveInstCombine(registry);
+  llvm::initializeAnalysis(registry);
+  llvm::initializeVectorization(registry);
+  llvm::initializeCoroutines(registry);
+}
 
-    case 1:
-      return OptimizationLevel::Os;
+// Populate pass managers according to the optimization and size levels.
+// This behaves similarly to LLVM opt.
+static void populatePassManagers(llvm::legacy::PassManager &modulePM,
+                                 llvm::legacy::FunctionPassManager &funcPM,
+                                 unsigned optLevel, unsigned sizeLevel,
+                                 llvm::TargetMachine *targetMachine) {
+  llvm::PassManagerBuilder builder;
+  builder.OptLevel = optLevel;
+  builder.SizeLevel = sizeLevel;
+  builder.Inliner = llvm::createFunctionInliningPass(
+      optLevel, sizeLevel, /*DisableInlineHotCallSite=*/false);
+  builder.LoopVectorize = optLevel > 1 && sizeLevel < 2;
+  builder.SLPVectorize = optLevel > 1 && sizeLevel < 2;
+  builder.DisableUnrollLoops = (optLevel == 0);
 
-    case 2:
-      return OptimizationLevel::Oz;
-    }
+  // Add all coroutine passes to the builder.
+  addCoroutinePassesToExtensionPoints(builder);
 
-  case 3:
-    return OptimizationLevel::O3;
+  if (targetMachine) {
+    // Add pass to initialize TTI for this specific target. Otherwise, TTI will
+    // be initialized to NoTTIImpl by default.
+    modulePM.add(createTargetTransformInfoWrapperPass(
+        targetMachine->getTargetIRAnalysis()));
+    funcPM.add(createTargetTransformInfoWrapperPass(
+        targetMachine->getTargetIRAnalysis()));
   }
-  return None;
+
+  builder.populateModulePassManager(modulePM);
+  builder.populateFunctionPassManager(funcPM);
 }
+
 // Create and return a lambda that uses LLVM pass manager builder to set up
 // optimizations based on the given level.
-std::function<Error(Module *)>
+std::function<llvm::Error(llvm::Module *)>
 mlir::makeOptimizingTransformer(unsigned optLevel, unsigned sizeLevel,
-                                TargetMachine *targetMachine) {
-  return [optLevel, sizeLevel, targetMachine](Module *m) -> Error {
-    Optional<OptimizationLevel> ol = mapToLevel(optLevel, sizeLevel);
-    if (!ol) {
-      return make_error<StringError>(
-          formatv("invalid optimization/size level {0}/{1}", optLevel,
-                  sizeLevel)
-              .str(),
-          inconvertibleErrorCode());
+                                llvm::TargetMachine *targetMachine) {
+  return [optLevel, sizeLevel, targetMachine](llvm::Module *m) -> llvm::Error {
+    llvm::legacy::PassManager modulePM;
+    llvm::legacy::FunctionPassManager funcPM(m);
+    populatePassManagers(modulePM, funcPM, optLevel, sizeLevel, targetMachine);
+    runPasses(modulePM, funcPM, *m);
+
+    return llvm::Error::success();
+  };
+}
+
+// Create and return a lambda that is given a set of passes to run, plus an
+// optional optimization level to pre-populate the pass manager.
+std::function<llvm::Error(llvm::Module *)> mlir::makeLLVMPassesTransformer(
+    llvm::ArrayRef<const llvm::PassInfo *> llvmPasses,
+    llvm::Optional<unsigned> mbOptLevel, llvm::TargetMachine *targetMachine,
+    unsigned optPassesInsertPos) {
+  return [llvmPasses, mbOptLevel, optPassesInsertPos,
+          targetMachine](llvm::Module *m) -> llvm::Error {
+    llvm::legacy::PassManager modulePM;
+    llvm::legacy::FunctionPassManager funcPM(m);
+
+    bool insertOptPasses = mbOptLevel.hasValue();
+    for (unsigned i = 0, e = llvmPasses.size(); i < e; ++i) {
+      const auto *passInfo = llvmPasses[i];
+      if (!passInfo->getNormalCtor())
+        continue;
+
+      if (insertOptPasses && optPassesInsertPos == i) {
+        populatePassManagers(modulePM, funcPM, mbOptLevel.getValue(), 0,
+                             targetMachine);
+        insertOptPasses = false;
+      }
+
+      auto *pass = passInfo->createPass();
+      if (!pass)
+        return llvm::make_error<llvm::StringError>(
+            "could not create pass " + passInfo->getPassName(),
+            llvm::inconvertibleErrorCode());
+      modulePM.add(pass);
     }
-    LoopAnalysisManager lam;
-    FunctionAnalysisManager fam;
-    CGSCCAnalysisManager cgam;
-    ModuleAnalysisManager mam;
-
-    PassBuilder pb(targetMachine);
-
-    pb.registerModuleAnalyses(mam);
-    pb.registerCGSCCAnalyses(cgam);
-    pb.registerFunctionAnalyses(fam);
-    pb.registerLoopAnalyses(lam);
-    pb.crossRegisterProxies(lam, fam, cgam, mam);
-
-    ModulePassManager mpm;
-    if (*ol == OptimizationLevel::O0)
-      mpm.addPass(pb.buildO0DefaultPipeline(*ol));
-    else
-      mpm.addPass(pb.buildPerModuleDefaultPipeline(*ol));
-
-    mpm.run(*m, mam);
-    return Error::success();
+
+    if (insertOptPasses)
+      populatePassManagers(modulePM, funcPM, mbOptLevel.getValue(), 0,
+                           targetMachine);
+
+    runPasses(modulePM, funcPM, *m);
+    return llvm::Error::success();
   };
 }

diff  --git a/mlir/tools/mlir-cpu-runner/mlir-cpu-runner.cpp b/mlir/tools/mlir-cpu-runner/mlir-cpu-runner.cpp
index 1b1d5d03d2be5..b1009a1fae458 100644
--- a/mlir/tools/mlir-cpu-runner/mlir-cpu-runner.cpp
+++ b/mlir/tools/mlir-cpu-runner/mlir-cpu-runner.cpp
@@ -26,6 +26,7 @@ int main(int argc, char **argv) {
   llvm::InitializeNativeTarget();
   llvm::InitializeNativeTargetAsmPrinter();
   llvm::InitializeNativeTargetAsmParser();
+  mlir::initializeLLVMPasses();
 
   mlir::DialectRegistry registry;
   mlir::registerAllToLLVMIRTranslations(registry);

diff  --git a/mlir/tools/mlir-spirv-cpu-runner/mlir-spirv-cpu-runner.cpp b/mlir/tools/mlir-spirv-cpu-runner/mlir-spirv-cpu-runner.cpp
index fb51af9002e12..ee2c4be2574b8 100644
--- a/mlir/tools/mlir-spirv-cpu-runner/mlir-spirv-cpu-runner.cpp
+++ b/mlir/tools/mlir-spirv-cpu-runner/mlir-spirv-cpu-runner.cpp
@@ -90,6 +90,7 @@ int main(int argc, char **argv) {
 
   llvm::InitializeNativeTarget();
   llvm::InitializeNativeTargetAsmPrinter();
+  mlir::initializeLLVMPasses();
 
   mlir::JitRunnerConfig jitRunnerConfig;
   jitRunnerConfig.mlirTransformer = runMLIRPasses;

diff  --git a/mlir/tools/mlir-vulkan-runner/mlir-vulkan-runner.cpp b/mlir/tools/mlir-vulkan-runner/mlir-vulkan-runner.cpp
index 6d0edda7feb9b..972292954663b 100644
--- a/mlir/tools/mlir-vulkan-runner/mlir-vulkan-runner.cpp
+++ b/mlir/tools/mlir-vulkan-runner/mlir-vulkan-runner.cpp
@@ -67,6 +67,7 @@ int main(int argc, char **argv) {
   llvm::InitLLVM y(argc, argv);
   llvm::InitializeNativeTarget();
   llvm::InitializeNativeTargetAsmPrinter();
+  mlir::initializeLLVMPasses();
 
   mlir::JitRunnerConfig jitRunnerConfig;
   jitRunnerConfig.mlirTransformer = runMLIRPasses;


        


More information about the Mlir-commits mailing list