xref: /llvm-project/mlir/lib/ExecutionEngine/OptUtils.cpp (revision 7ccd026cf2819ba9f0e89f5100e9363ce5f3bcad)
1 //===- OptUtils.cpp - MLIR Execution Engine optimization pass utilities ---===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the utility functions to trigger LLVM optimizations from
10 // MLIR Execution Engine.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "mlir/ExecutionEngine/OptUtils.h"
15 
16 #include "llvm/Analysis/TargetTransformInfo.h"
17 #include "llvm/IR/Module.h"
18 #include "llvm/Passes/OptimizationLevel.h"
19 #include "llvm/Passes/PassBuilder.h"
20 #include "llvm/Support/Error.h"
21 #include "llvm/Support/FormatVariadic.h"
22 #include "llvm/Target/TargetMachine.h"
23 
24 using namespace llvm;
25 
26 static Optional<OptimizationLevel> mapToLevel(unsigned optLevel,
27                                               unsigned sizeLevel) {
28   switch (optLevel) {
29   case 0:
30     return OptimizationLevel::O0;
31 
32   case 1:
33     return OptimizationLevel::O1;
34 
35   case 2:
36     switch (sizeLevel) {
37     case 0:
38       return OptimizationLevel::O2;
39 
40     case 1:
41       return OptimizationLevel::Os;
42 
43     case 2:
44       return OptimizationLevel::Oz;
45     }
46 
47   case 3:
48     return OptimizationLevel::O3;
49   }
50   return None;
51 }
52 // Create and return a lambda that uses LLVM pass manager builder to set up
53 // optimizations based on the given level.
54 std::function<Error(Module *)>
55 mlir::makeOptimizingTransformer(unsigned optLevel, unsigned sizeLevel,
56                                 TargetMachine *targetMachine) {
57   return [optLevel, sizeLevel, targetMachine](Module *m) -> Error {
58     Optional<OptimizationLevel> ol = mapToLevel(optLevel, sizeLevel);
59     if (!ol) {
60       return make_error<StringError>(
61           formatv("invalid optimization/size level {0}/{1}", optLevel,
62                   sizeLevel)
63               .str(),
64           inconvertibleErrorCode());
65     }
66     LoopAnalysisManager lam;
67     FunctionAnalysisManager fam;
68     CGSCCAnalysisManager cgam;
69     ModuleAnalysisManager mam;
70 
71     PassBuilder pb(targetMachine);
72 
73     pb.registerModuleAnalyses(mam);
74     pb.registerCGSCCAnalyses(cgam);
75     pb.registerFunctionAnalyses(fam);
76     pb.registerLoopAnalyses(lam);
77     pb.crossRegisterProxies(lam, fam, cgam, mam);
78 
79     ModulePassManager mpm;
80     if (*ol == OptimizationLevel::O0)
81       mpm.addPass(pb.buildO0DefaultPipeline(*ol));
82     else
83       mpm.addPass(pb.buildPerModuleDefaultPipeline(*ol));
84 
85     mpm.run(*m, mam);
86     return Error::success();
87   };
88 }
89