LLVM 23.0.0git
PassManager.h
Go to the documentation of this file.
1//===- PassManager.h --------------------------------------------*- C++ -*-===//
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// Registers and executes the Sandbox IR passes.
10//
11// The pass manager contains an ordered sequence of passes that it runs in
12// order. The passes are owned by the PassRegistry, not by the PassManager.
13//
14// Note that in this design a pass manager is also a pass. So a pass manager
15// runs when it is it's turn to run in its parent pass-manager pass pipeline.
16//
17
18#ifndef LLVM_SANDBOXIR_PASSMANAGER_H
19#define LLVM_SANDBOXIR_PASSMANAGER_H
20
22#include <memory>
23
24#include "llvm/ADT/DenseMap.h"
25#include "llvm/ADT/STLExtras.h"
26#include "llvm/SandboxIR/Pass.h"
27#include "llvm/Support/Debug.h"
28
29namespace llvm::sandboxir {
30
31class Value;
32
33/// Base class.
34template <typename ParentPass, typename ContainedPass>
35class PassManager : public ParentPass {
36public:
37 // CreatePassFunc(StringRef PassName, StringRef PassArgs, StringRef AuxArg)
38 using CreatePassFunc = std::function<std::unique_ptr<ContainedPass>(
40
41protected:
42 /// The list of passes that this pass manager will run.
44
46 PassManager(StringRef Name, StringRef Pipeline, CreatePassFunc CreatePass)
47 : ParentPass(Name) {
48 setPassPipeline(Pipeline, CreatePass);
49 }
50 PassManager(const PassManager &) = delete;
51 PassManager(PassManager &&) = default;
52 ~PassManager() override = default;
53 PassManager &operator=(const PassManager &) = delete;
54
55public:
56 /// Adds \p Pass to the pass pipeline.
57 void addPass(std::unique_ptr<ContainedPass> Pass) {
58 // TODO: Check that Pass's class type works with this PassManager type.
59 Passes.push_back(std::move(Pass));
60 }
61
62 static constexpr char EndToken = '\0';
63 static constexpr char BeginArgsToken = '<';
64 static constexpr char EndArgsToken = '>';
65 static constexpr char BeginAuxArgsToken = '(';
66 static constexpr char EndAuxArgsToken = ')';
67 static constexpr char PassDelimToken = ',';
68
69 /// Parses \p Pipeline as a comma-separated sequence of pass names and sets
70 /// the pass pipeline, using \p CreatePass to instantiate passes by name.
71 ///
72 /// Passes can have two types of arguments:
73 /// - The standard pass arguments within < >, which are commonly used for
74 /// passing a comma-separated list of pass names, for example:
75 /// "pass1<arg1,arg2>,pass2,pass3<arg3,arg4>"
76 /// - An auxiliary pass argument within ( ), which is used as a secondary
77 /// argument, for example:
78 /// "pass1(foo),pass2,pass3(bar)"
79 /// Note that both types of arguments can be combined, like:
80 /// "pass1(foo)<arg1,arg2>,pass2,pass3(bar)<arg3,arg4>"
81 /// The reason why there is more than one type of pass argument, is to make
82 /// it easier for passes to parse the argument contents, and make the pass
83 /// pipeline more consistent and easier to read, than relying on some
84 /// formatting that the passes might expect.
85 ///
86 /// The arguments between both bracket types are treated as a mostly opaque
87 /// string and each pass is responsible for parsing its arguments. The
88 /// exception to this are nested brackets, which must match pair-wise to
89 /// allow arguments to contain nested pipelines or nested aux arguments, like:
90 ///
91 /// "pass1<subpass1,subpass2<arg1,arg2>,subpass3>"
92 /// or
93 /// "pass1(arg1(nestedarg))"
94 ///
95 /// An empty args string is treated the same as no args, so "pass" and
96 /// "pass<>" are equivalent.
97 ///
98 void setPassPipeline(StringRef Pipeline, CreatePassFunc CreatePass) {
99 assert(Passes.empty() &&
100 "setPassPipeline called on a non-empty sandboxir::PassManager");
101
102 // Accept an empty pipeline as a special case. This can be useful, for
103 // example, to test conversion to SandboxIR without running any passes on
104 // it.
105 if (Pipeline.empty())
106 return;
107
108 // Add EndToken to the end to ease parsing.
109 std::string PipelineStr = std::string(Pipeline) + EndToken;
110 Pipeline = StringRef(PipelineStr);
111
112 auto AddPass = [this, CreatePass](StringRef PassName, StringRef PassArgs,
113 StringRef AuxArg) {
114 if (PassName.empty()) {
115 errs() << "Found empty pass name.\n";
116 exit(1);
117 }
118 // Get the pass that corresponds to PassName and add it to the pass
119 // manager.
120 auto Pass = CreatePass(PassName, PassArgs, AuxArg);
121 if (Pass == nullptr) {
122 errs() << "Pass '" << PassName << "' not registered!\n";
123 exit(1);
124 }
125 addPass(std::move(Pass));
126 };
127
128 enum class State {
129 ScanName, // reading a pass name
130 ScanArgs, // reading a list of args
131 ArgsEnded, // read the last '>' in an args list, must read delimiter next
132 ScanAuxArgs, // reading the auxiliary argument
133 AuxArgsEnded, // read the last ')' in aux args list
134 } CurrentState = State::ScanName;
135 int PassBeginIdx = 0;
136 int ArgsBeginIdx;
137 int AuxArgsBeginIdx = 0;
139 StringRef AuxArg;
140 int NestedArgs = 0;
141 int NestedAuxArgs = 0;
142 for (auto [Idx, C] : enumerate(Pipeline)) {
143 switch (CurrentState) {
144 case State::ScanName:
145 if (C == BeginArgsToken) {
146 // Save pass name for later and begin scanning args.
147 PassName = Pipeline.slice(PassBeginIdx, Idx);
148 ArgsBeginIdx = Idx + 1;
149 ++NestedArgs;
150 CurrentState = State::ScanArgs;
151 break;
152 }
153 if (C == BeginAuxArgsToken) {
154 // Save pass name for later and begin scanning args.
155 PassName = Pipeline.slice(PassBeginIdx, Idx);
156 AuxArgsBeginIdx = Idx + 1;
157 ++NestedAuxArgs;
158 CurrentState = State::ScanAuxArgs;
159 AuxArg = StringRef();
160 break;
161 }
162 if (C == EndArgsToken || C == EndAuxArgsToken) {
163 errs() << "Unexpected '" << C << "' in pass pipeline.\n";
164 exit(1);
165 }
166 if (C == EndToken || C == PassDelimToken) {
167 // Delimiter found, add the pass (with empty args), stay in the
168 // ScanName state.
169 AddPass(Pipeline.slice(PassBeginIdx, Idx), StringRef(), AuxArg);
170 PassBeginIdx = Idx + 1;
171 }
172 break;
173 case State::ScanArgs:
174 // While scanning args, we only care about making sure nesting of angle
175 // brackets is correct.
176 if (C == BeginArgsToken) {
177 ++NestedArgs;
178 break;
179 }
180 if (C == EndArgsToken) {
181 --NestedArgs;
182 if (NestedArgs == 0) {
183 // Done scanning args.
184 AddPass(PassName, Pipeline.slice(ArgsBeginIdx, Idx), AuxArg);
185 CurrentState = State::ArgsEnded;
186 } else if (NestedArgs < 0) {
187 errs() << "Unexpected '>' in pass pipeline.\n";
188 exit(1);
189 }
190 break;
191 }
192 if (C == EndToken) {
193 errs() << "Missing '>' in pass pipeline. End-of-string reached while "
194 "reading arguments for pass '"
195 << PassName << "'.\n";
196 exit(1);
197 }
198 break;
199 case State::ArgsEnded:
200 // Once we're done scanning args, only a delimiter is valid. This avoids
201 // accepting strings like "foo<args><more-args>" or "foo<args>bar".
202 if (C == EndToken || C == PassDelimToken) {
203 PassBeginIdx = Idx + 1;
204 AuxArg = StringRef();
205 CurrentState = State::ScanName;
206 } else {
207 errs() << "Expected delimiter or end-of-string after pass "
208 "arguments.\n";
209 exit(1);
210 }
211 break;
212 case State::ScanAuxArgs:
213 if (C == BeginAuxArgsToken) {
214 ++NestedAuxArgs;
215 break;
216 }
217 if (C == EndAuxArgsToken) {
218 --NestedAuxArgs;
219 if (NestedAuxArgs == 0) {
220 AuxArg = Pipeline.slice(AuxArgsBeginIdx, Idx);
221 CurrentState = State::AuxArgsEnded;
222 } else if (NestedAuxArgs < 0) {
223 errs() << "Unexpected '" << EndAuxArgsToken
224 << "' in pass pipeline.\n";
225 exit(1);
226 }
227 break;
228 }
229 if (C == EndToken) {
230 errs() << "Missing '" << EndAuxArgsToken
231 << "' in pass pipeline. End-of-string reached while "
232 "reading arguments for pass '"
233 << PassName << "'.\n";
234 exit(1);
235 }
236 break;
237 case State::AuxArgsEnded:
238 if (C == EndToken || C == PassDelimToken) {
239 AddPass(PassName, StringRef(), AuxArg);
240 CurrentState = State::ScanArgs;
241 } else if (C == BeginArgsToken) {
242 ++NestedArgs;
243 ArgsBeginIdx = Idx + 1;
244 CurrentState = State::ScanArgs;
245 } else {
246 errs() << "Expected delimiter, begin-of-args or end-of-string after "
247 "pass aux argument.\n";
248 exit(1);
249 }
250 break;
251 }
252 }
253 }
254
255#ifndef NDEBUG
256 void print(raw_ostream &OS) const override {
257 OS << this->getName();
258 OS << BeginArgsToken;
259 std::string Delim(1, PassDelimToken);
260 interleave(Passes, OS, [&OS](auto &Pass) { Pass->print(OS); }, Delim);
261 OS << EndArgsToken;
262 }
263 LLVM_DUMP_METHOD void dump() const override {
264 print(dbgs());
265 dbgs() << "\n";
266 }
267#endif
268 /// Similar to print() but prints one pass per line. Used for testing.
269 void printPipeline(raw_ostream &OS) const override {
270 OS << this->getName() << "\n";
271 for (const auto &PassPtr : Passes)
272 PassPtr->printPipeline(OS);
273 }
274};
275
277 : public PassManager<FunctionPass, FunctionPass> {
278public:
281 CreatePassFunc CreatePass)
282 : PassManager(Name, Pipeline, CreatePass) {}
283 bool runOnFunction(Function &F, const Analyses &A) final;
284};
285
287 : public PassManager<RegionPass, RegionPass> {
288public:
291 CreatePassFunc CreatePass)
292 : PassManager(Name, Pipeline, CreatePass) {}
293 bool runOnRegion(Region &R, const Analyses &A) final;
294};
295
296} // namespace llvm::sandboxir
297
298#endif // LLVM_SANDBOXIR_PASSMANAGER_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define LLVM_ABI
Definition Compiler.h:213
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:661
This file defines the DenseMap class.
static bool runOnFunction(Function &F, bool PostInlining)
#define F(x, y, z)
Definition MD5.cpp:54
static StringRef getName(Value *V)
This file contains some templates that are useful if you are working with the STL at all.
static const char PassName[]
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
constexpr bool empty() const
empty - Check if the string is empty.
Definition StringRef.h:140
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
Definition StringRef.h:714
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
FunctionPassManager(StringRef Name, StringRef Pipeline, CreatePassFunc CreatePass)
PassManager(const PassManager &)=delete
static constexpr char EndAuxArgsToken
Definition PassManager.h:66
void addPass(std::unique_ptr< ContainedPass > Pass)
Adds Pass to the pass pipeline.
Definition PassManager.h:57
std::function< std::unique_ptr< ContainedPass >( StringRef, StringRef, StringRef)> CreatePassFunc
Definition PassManager.h:38
void printPipeline(raw_ostream &OS) const override
Similar to print() but prints one pass per line. Used for testing.
static constexpr char EndToken
Definition PassManager.h:62
PassManager(StringRef Name)
Definition PassManager.h:45
void setPassPipeline(StringRef Pipeline, CreatePassFunc CreatePass)
Parses Pipeline as a comma-separated sequence of pass names and sets the pass pipeline,...
Definition PassManager.h:98
PassManager(PassManager &&)=default
static constexpr char BeginArgsToken
Definition PassManager.h:63
void print(raw_ostream &OS) const override
~PassManager() override=default
PassManager(StringRef Name, StringRef Pipeline, CreatePassFunc CreatePass)
Definition PassManager.h:46
PassManager & operator=(const PassManager &)=delete
LLVM_DUMP_METHOD void dump() const override
static constexpr char PassDelimToken
Definition PassManager.h:67
SmallVector< std::unique_ptr< ContainedPass > > Passes
The list of passes that this pass manager will run.
Definition PassManager.h:43
static constexpr char BeginAuxArgsToken
Definition PassManager.h:65
static constexpr char EndArgsToken
Definition PassManager.h:64
The base class of a Sandbox IR Pass.
Definition Pass.h:46
const std::string Name
The pass name.
Definition Pass.h:50
virtual void print(raw_ostream &OS) const
Definition Pass.h:67
RegionPassManager(StringRef Name, StringRef Pipeline, CreatePassFunc CreatePass)
The main job of the Region is to point to new instructions generated by vectorization passes.
Definition Region.h:96
A SandboxIR Value has users. This is the base class.
Definition Value.h:68
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2554
void interleave(ForwardIterator begin, ForwardIterator end, UnaryFunctor each_fn, NullaryFunctor between_fn)
An STL-style algorithm similar to std::for_each that applies a second functor between every pair of e...
Definition STLExtras.h:2275
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.