github.com/johnnyeven/libtools@v0.0.0-20191126065708-61829c1adf46/third_party/mlir/lib/ExecutionEngine/OptUtils.cpp (about) 1 //===- OptUtils.cpp - MLIR Execution Engine optimization pass utilities ---===// 2 // 3 // Copyright 2019 The MLIR Authors. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 // ============================================================================= 17 // 18 // This file implements the utility functions to trigger LLVM optimizations from 19 // MLIR Execution Engine. 20 // 21 //===----------------------------------------------------------------------===// 22 23 #include "mlir/ExecutionEngine/OptUtils.h" 24 25 #include "llvm/ADT/ArrayRef.h" 26 #include "llvm/Analysis/TargetTransformInfo.h" 27 #include "llvm/IR/LegacyPassManager.h" 28 #include "llvm/IR/LegacyPassNameParser.h" 29 #include "llvm/IR/Module.h" 30 #include "llvm/InitializePasses.h" 31 #include "llvm/Pass.h" 32 #include "llvm/Support/Allocator.h" 33 #include "llvm/Support/CommandLine.h" 34 #include "llvm/Support/Error.h" 35 #include "llvm/Support/StringSaver.h" 36 #include "llvm/Target/TargetMachine.h" 37 #include "llvm/Transforms/IPO.h" 38 #include "llvm/Transforms/IPO/PassManagerBuilder.h" 39 #include <climits> 40 #include <mutex> 41 42 // Run the module and function passes managed by the module manager. 43 static void runPasses(llvm::legacy::PassManager &modulePM, 44 llvm::legacy::FunctionPassManager &funcPM, 45 llvm::Module &m) { 46 funcPM.doInitialization(); 47 for (auto &func : m) { 48 funcPM.run(func); 49 } 50 funcPM.doFinalization(); 51 modulePM.run(m); 52 } 53 54 // Initialize basic LLVM transformation passes under lock. 55 void mlir::initializeLLVMPasses() { 56 static std::mutex mutex; 57 std::lock_guard<std::mutex> lock(mutex); 58 59 auto ®istry = *llvm::PassRegistry::getPassRegistry(); 60 llvm::initializeCore(registry); 61 llvm::initializeTransformUtils(registry); 62 llvm::initializeScalarOpts(registry); 63 llvm::initializeIPO(registry); 64 llvm::initializeInstCombine(registry); 65 llvm::initializeAggressiveInstCombine(registry); 66 llvm::initializeAnalysis(registry); 67 llvm::initializeVectorization(registry); 68 } 69 70 // Populate pass managers according to the optimization and size levels. 71 // This behaves similarly to LLVM opt. 72 static void populatePassManagers(llvm::legacy::PassManager &modulePM, 73 llvm::legacy::FunctionPassManager &funcPM, 74 unsigned optLevel, unsigned sizeLevel, 75 llvm::TargetMachine *targetMachine) { 76 llvm::PassManagerBuilder builder; 77 builder.OptLevel = optLevel; 78 builder.SizeLevel = sizeLevel; 79 builder.Inliner = llvm::createFunctionInliningPass( 80 optLevel, sizeLevel, /*DisableInlineHotCallSite=*/false); 81 builder.LoopVectorize = optLevel > 1 && sizeLevel < 2; 82 builder.SLPVectorize = optLevel > 1 && sizeLevel < 2; 83 builder.DisableUnrollLoops = (optLevel == 0); 84 85 if (targetMachine) { 86 // Add pass to initialize TTI for this specific target. Otherwise, TTI will 87 // be initialized to NoTTIImpl by defaul. 88 modulePM.add(createTargetTransformInfoWrapperPass( 89 targetMachine->getTargetIRAnalysis())); 90 funcPM.add(createTargetTransformInfoWrapperPass( 91 targetMachine->getTargetIRAnalysis())); 92 } 93 94 builder.populateModulePassManager(modulePM); 95 builder.populateFunctionPassManager(funcPM); 96 } 97 98 // Create and return a lambda that uses LLVM pass manager builder to set up 99 // optimizations based on the given level. 100 std::function<llvm::Error(llvm::Module *)> 101 mlir::makeOptimizingTransformer(unsigned optLevel, unsigned sizeLevel, 102 llvm::TargetMachine *targetMachine) { 103 return [optLevel, sizeLevel, targetMachine](llvm::Module *m) -> llvm::Error { 104 llvm::legacy::PassManager modulePM; 105 llvm::legacy::FunctionPassManager funcPM(m); 106 populatePassManagers(modulePM, funcPM, optLevel, sizeLevel, targetMachine); 107 runPasses(modulePM, funcPM, *m); 108 109 return llvm::Error::success(); 110 }; 111 } 112 113 // Create and return a lambda that is given a set of passes to run, plus an 114 // optional optimization level to pre-populate the pass manager. 115 std::function<llvm::Error(llvm::Module *)> mlir::makeLLVMPassesTransformer( 116 llvm::ArrayRef<const llvm::PassInfo *> llvmPasses, 117 llvm::Optional<unsigned> mbOptLevel, llvm::TargetMachine *targetMachine, 118 unsigned optPassesInsertPos) { 119 return [llvmPasses, mbOptLevel, optPassesInsertPos, 120 targetMachine](llvm::Module *m) -> llvm::Error { 121 llvm::legacy::PassManager modulePM; 122 llvm::legacy::FunctionPassManager funcPM(m); 123 124 bool insertOptPasses = mbOptLevel.hasValue(); 125 for (unsigned i = 0, e = llvmPasses.size(); i < e; ++i) { 126 const auto *passInfo = llvmPasses[i]; 127 if (!passInfo->getNormalCtor()) 128 continue; 129 130 if (insertOptPasses && optPassesInsertPos == i) { 131 populatePassManagers(modulePM, funcPM, mbOptLevel.getValue(), 0, 132 targetMachine); 133 insertOptPasses = false; 134 } 135 136 auto *pass = passInfo->createPass(); 137 if (!pass) 138 return llvm::make_error<llvm::StringError>( 139 "could not create pass " + passInfo->getPassName(), 140 llvm::inconvertibleErrorCode()); 141 modulePM.add(pass); 142 } 143 144 if (insertOptPasses) 145 populatePassManagers(modulePM, funcPM, mbOptLevel.getValue(), 0, 146 targetMachine); 147 148 runPasses(modulePM, funcPM, *m); 149 return llvm::Error::success(); 150 }; 151 }