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
29namespace glow {
30llvm::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
40llvm::StringRef IRFunctionPassConfig::getNameOfPass() const {
41 return glow::getNameOfPass(getPassID());
42}
43} // namespace glow
44
45namespace {
46/// A helper class to represent a IRFunctionPassConfig in a way which can be
47/// easily handled by YAML functions.
48struct 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
60namespace llvm {
61namespace yaml {
62/// Define the YAML mapping for IRPassConfigHelper.
63template <> 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
73namespace glow {
74
75std::unique_ptr<IRFunctionPassPipeline>
76createDefaultIRFunctionOptimizationPipeline() {
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
119static llvm::StringMap<IRFunctionPassID> passNameToID{
120#include "glow/Optimizer/IROptimizer/IRPasses.def"
121};
122
123static IRFunctionPassID getPassID(llvm::StringRef name) {
124 CHECK_GT(passNameToID.count(name), 0) << "Unknown pass name: " << name.str();
125 return passNameToID.lookup(name);
126}
127
128template <>
129void 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
141template <>
142void 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
151void IRFunctionPassConfig::dump(llvm::raw_ostream &os) const {
152 PassConfigBase::dump(os, glow::getNameOfPass(getPassID()));
153}
154
155} // namespace glow
156