1 | /** |
2 | * Copyright (c) Glow Contributors. See CONTRIBUTORS file. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | #include "glow/PassManager/Pipeline.h" |
17 | |
18 | #include "glow/Optimizer/IROptimizer/CommandLine.h" |
19 | #include "glow/Optimizer/IROptimizer/IRFunctionPassManager.h" |
20 | #include "glow/Optimizer/IROptimizer/IROptimizer.h" |
21 | #include "glow/PassManager/PassConfigUtils.h" |
22 | |
23 | #include "llvm/Support/CommandLine.h" |
24 | #include "llvm/Support/YAMLParser.h" |
25 | #include "llvm/Support/YAMLTraits.h" |
26 | |
27 | #include <fstream> |
28 | |
29 | namespace glow { |
30 | llvm::StringRef getNameOfPass(IRFunctionPassID passID) { |
31 | switch (passID) { |
32 | #define IR_FUN_PASS(PASS_NAME) \ |
33 | case IRFunctionPassID::PASS_NAME: \ |
34 | return #PASS_NAME; |
35 | #include "glow/Optimizer/IROptimizer/IRPasses.def" |
36 | } |
37 | llvm_unreachable("Unexpected pass." ); |
38 | } |
39 | |
40 | llvm::StringRef IRFunctionPassConfig::getNameOfPass() const { |
41 | return glow::getNameOfPass(getPassID()); |
42 | } |
43 | } // namespace glow |
44 | |
45 | namespace { |
46 | /// A helper class to represent a IRFunctionPassConfig in a way which can be |
47 | /// easily handled by YAML functions. |
48 | struct IRPassConfigHelper { |
49 | std::string passName; |
50 | glow::ConvergenceMode convergenceMode; |
51 | CompilationModes enabledCompilationModes; |
52 | IRPassConfigHelper(const glow::IRFunctionPassConfig &config) |
53 | : passName(config.getNameOfPass()), |
54 | convergenceMode(config.getConvergenceMode()), |
55 | enabledCompilationModes(config.getEnabledCompilationModes()) {} |
56 | IRPassConfigHelper() = default; |
57 | }; |
58 | } // namespace |
59 | |
60 | namespace llvm { |
61 | namespace yaml { |
62 | /// Define the YAML mapping for IRPassConfigHelper. |
63 | template <> struct MappingTraits<IRPassConfigHelper> { |
64 | static void mapping(IO &io, IRPassConfigHelper &config) { |
65 | io.mapRequired("passName" , config.passName); |
66 | io.mapRequired("convergenceMode" , config.convergenceMode); |
67 | io.mapRequired("enabledCompilaitonModes" , config.enabledCompilationModes); |
68 | } |
69 | }; |
70 | } // namespace yaml |
71 | } // namespace llvm |
72 | |
73 | namespace glow { |
74 | |
75 | std::unique_ptr<IRFunctionPassPipeline> |
76 | createDefaultIRFunctionOptimizationPipeline() { |
77 | if (!optimizeIR) { |
78 | return glow::make_unique<IRFunctionPassPipeline>(); |
79 | } |
80 | std::initializer_list<IRFunctionPassConfig> configs{ |
81 | {IRFunctionPassID::PeepholeOptimizations}, |
82 | // Dead store elimination. |
83 | {IRFunctionPassID::DSE}, |
84 | // Replace applicable InsertTensors and ExtractTensors with TensorViews. |
85 | {IRFunctionPassID::OptimizeInserts}, |
86 | {IRFunctionPassID::OptimizeExtracts}, |
87 | // TODO: Only if enabled. |
88 | {IRFunctionPassID::ShareBuffers}, |
89 | {IRFunctionPassID::PeepholeOptimizations}, |
90 | {IRFunctionPassID::HoistDealloc}, |
91 | {IRFunctionPassID::SinkAllocas}, |
92 | // Dead store elimination. |
93 | {IRFunctionPassID::DSE}, |
94 | {IRFunctionPassID::DeleteDeadAllocs}, |
95 | {IRFunctionPassID::MakeWeightsConst}, |
96 | }; |
97 | |
98 | auto pipeline = glow::make_unique<IRFunctionPassPipeline>(configs); |
99 | |
100 | if (instrumentDebug) { |
101 | // Run debug instrumentation only if necessary. |
102 | pipeline->pushBack(IRFunctionPassID::DebugInstrument); |
103 | } |
104 | if (instrumentIR) { |
105 | // Run IR instrumentation only if necessary. |
106 | pipeline->pushBack(IRFunctionPassID::IRInstrument); |
107 | } |
108 | // Always run a verifier at the end. |
109 | pipeline->pushBack(IRFunctionPassID::IRVerify); |
110 | // If requested, dump IR to stdout for debugging. |
111 | if (dumpIR) { |
112 | pipeline->pushBack(IRFunctionPassID::IRDumper); |
113 | } |
114 | return pipeline; |
115 | } |
116 | |
117 | #define IR_FUN_PASS(PASS_NAME) {#PASS_NAME, IRFunctionPassID::PASS_NAME}, |
118 | |
119 | static llvm::StringMap<IRFunctionPassID> passNameToID{ |
120 | #include "glow/Optimizer/IROptimizer/IRPasses.def" |
121 | }; |
122 | |
123 | static IRFunctionPassID getPassID(llvm::StringRef name) { |
124 | CHECK_GT(passNameToID.count(name), 0) << "Unknown pass name: " << name.str(); |
125 | return passNameToID.lookup(name); |
126 | } |
127 | |
128 | template <> |
129 | void IRFunctionPassPipeline::initFromFile(llvm::StringRef pipelineDefFilename) { |
130 | clear(); |
131 | auto configs = |
132 | deserializeFromYaml<std::vector<IRPassConfigHelper>>(pipelineDefFilename); |
133 | for (auto &config : configs) { |
134 | IRFunctionPassConfig irFunctionPassConfig(getPassID(config.passName), |
135 | config.convergenceMode, |
136 | config.enabledCompilationModes); |
137 | pushBack(irFunctionPassConfig); |
138 | } |
139 | } |
140 | |
141 | template <> |
142 | void IRFunctionPassPipeline::dumpToFile(llvm::StringRef pipelineDefFilename) { |
143 | std::vector<IRPassConfigHelper> configs; |
144 | for (unsigned idx = 0, e = size(); idx < e; ++idx) { |
145 | const auto &config = at(idx); |
146 | configs.emplace_back(IRPassConfigHelper(config)); |
147 | } |
148 | serializeToYaml(pipelineDefFilename, configs); |
149 | } |
150 | |
151 | void IRFunctionPassConfig::dump(llvm::raw_ostream &os) const { |
152 | PassConfigBase::dump(os, glow::getNameOfPass(getPassID())); |
153 | } |
154 | |
155 | } // namespace glow |
156 | |