1 //===- PassManagerOptions.cpp - PassManager Command Line Options ----------===//
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 #include "mlir/Pass/Pass.h"
19 #include "mlir/Pass/PassManager.h"
20 #include "mlir/Pass/PassRegistry.h"
21 #include "llvm/Support/CommandLine.h"
22 #include "llvm/Support/ManagedStatic.h"
23 
24 using namespace mlir;
25 
26 namespace {
27 struct PassManagerOptions {
28   typedef llvm::cl::list<const mlir::PassRegistryEntry *, bool, PassNameParser>
29       PassOptionList;
30 
31   PassManagerOptions();
32 
33   //===--------------------------------------------------------------------===//
34   // Multi-threading
35   //===--------------------------------------------------------------------===//
36   llvm::cl::opt<bool> disableThreads;
37 
38   //===--------------------------------------------------------------------===//
39   // IR Printing
40   //===--------------------------------------------------------------------===//
41   PassOptionList printBefore;
42   PassOptionList printAfter;
43   llvm::cl::opt<bool> printBeforeAll;
44   llvm::cl::opt<bool> printAfterAll;
45   llvm::cl::opt<bool> printModuleScope;
46 
47   /// Add an IR printing instrumentation if enabled by any 'print-ir' flags.
48   void addPrinterInstrumentation(PassManager &pm);
49 
50   //===--------------------------------------------------------------------===//
51   // Pass Timing
52   //===--------------------------------------------------------------------===//
53   llvm::cl::opt<bool> passTiming;
54   llvm::cl::opt<PassTimingDisplayMode> passTimingDisplayMode;
55 
56   /// Add a pass timing instrumentation if enabled by 'pass-timing' flags.
57   void addTimingInstrumentation(PassManager &pm);
58 };
59 } // end anonymous namespace
60 
61 static llvm::ManagedStatic<llvm::Optional<PassManagerOptions>> options;
62 
63 PassManagerOptions::PassManagerOptions()
64     //===------------------------------------------------------------------===//
65     // Multi-threading
66     //===------------------------------------------------------------------===//
67     : disableThreads(
68           "disable-pass-threading",
69           llvm::cl::desc("Disable multithreading in the pass manager"),
70           llvm::cl::init(false)),
71 
72       //===----------------------------------------------------------------===//
73       // IR Printing
74       //===----------------------------------------------------------------===//
75       printBefore("print-ir-before",
76                   llvm::cl::desc("Print IR before specified passes")),
77       printAfter("print-ir-after",
78                  llvm::cl::desc("Print IR after specified passes")),
79       printBeforeAll("print-ir-before-all",
80                      llvm::cl::desc("Print IR before each pass"),
81                      llvm::cl::init(false)),
82       printAfterAll("print-ir-after-all",
83                     llvm::cl::desc("Print IR after each pass"),
84                     llvm::cl::init(false)),
85       printModuleScope(
86           "print-ir-module-scope",
87           llvm::cl::desc("When printing IR for print-ir-[before|after]{-all} "
88                          "always print "
89                          "a module IR"),
90           llvm::cl::init(false)),
91 
92       //===----------------------------------------------------------------===//
93       // Pass Timing
94       //===----------------------------------------------------------------===//
95       passTiming("pass-timing",
96                  llvm::cl::desc("Display the execution times of each pass")),
97       passTimingDisplayMode(
98           "pass-timing-display",
99           llvm::cl::desc("Display method for pass timing data"),
100           llvm::cl::init(PassTimingDisplayMode::Pipeline),
101           llvm::cl::values(
102               clEnumValN(PassTimingDisplayMode::List, "list",
103                          "display the results in a list sorted by total time"),
104               clEnumValN(PassTimingDisplayMode::Pipeline, "pipeline",
105                          "display the results with a nested pipeline view"))) {}
106 
107 /// Add an IR printing instrumentation if enabled by any 'print-ir' flags.
108 void PassManagerOptions::addPrinterInstrumentation(PassManager &pm) {
109   std::function<bool(Pass *)> shouldPrintBeforePass, shouldPrintAfterPass;
110 
111   // Handle print-before.
112   if (printBeforeAll) {
113     // If we are printing before all, then just return true for the filter.
114     shouldPrintBeforePass = [](Pass *) { return true; };
115   } else if (printBefore.getNumOccurrences() != 0) {
116     // Otherwise if there are specific passes to print before, then check to see
117     // if the pass info for the current pass is included in the list.
118     shouldPrintBeforePass = [&](Pass *pass) {
119       auto *passInfo = pass->lookupPassInfo();
120       return passInfo && llvm::is_contained(printBefore, passInfo);
121     };
122   }
123 
124   // Handle print-after.
125   if (printAfterAll) {
126     // If we are printing after all, then just return true for the filter.
127     shouldPrintAfterPass = [](Pass *) { return true; };
128   } else if (printAfter.getNumOccurrences() != 0) {
129     // Otherwise if there are specific passes to print after, then check to see
130     // if the pass info for the current pass is included in the list.
131     shouldPrintAfterPass = [&](Pass *pass) {
132       auto *passInfo = pass->lookupPassInfo();
133       return passInfo && llvm::is_contained(printAfter, passInfo);
134     };
135   }
136 
137   // If there are no valid printing filters, then just return.
138   if (!shouldPrintBeforePass && !shouldPrintAfterPass)
139     return;
140 
141   // Otherwise, add the IR printing instrumentation.
142   pm.enableIRPrinting(shouldPrintBeforePass, shouldPrintAfterPass,
143                       printModuleScope, llvm::errs());
144 }
145 
146 /// Add a pass timing instrumentation if enabled by 'pass-timing' flags.
147 void PassManagerOptions::addTimingInstrumentation(PassManager &pm) {
148   if (passTiming)
149     pm.enableTiming(passTimingDisplayMode);
150 }
151 
152 void mlir::registerPassManagerCLOptions() {
153   // Reset the options instance if it hasn't been enabled yet.
154   if (!options->hasValue())
155     options->emplace();
156 }
157 
158 void mlir::applyPassManagerCLOptions(PassManager &pm) {
159   // Disable multi-threading.
160   if ((*options)->disableThreads)
161     pm.disableMultithreading();
162 
163   // Add the IR printing instrumentation.
164   (*options)->addPrinterInstrumentation(pm);
165 
166   // Note: The pass timing instrumentation should be added last to avoid any
167   // potential "ghost" timing from other instrumentations being unintentionally
168   // included in the timing results.
169   (*options)->addTimingInstrumentation(pm);
170 }
171