MLIR: include/mlir/Pass/PassOptions.h Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14 #ifndef MLIR_PASS_PASSOPTIONS_H_
15 #define MLIR_PASS_PASSOPTIONS_H_
16
18 #include "llvm/ADT/FunctionExtras.h"
19 #include "llvm/ADT/StringRef.h"
20 #include "llvm/Support/CommandLine.h"
21 #include "llvm/Support/Compiler.h"
22 #include
23
24 namespace mlir {
25 class OpPassManager;
26
27 namespace detail {
28 namespace pass_options {
29
30
31
32 LogicalResult
34 StringRef optionStr,
35 function_ref<LogicalResult(StringRef)> elementParseFn);
36 template <typename ElementParser, typename ElementAppendFn>
38 StringRef optionStr,
39 ElementParser &elementParser,
40 ElementAppendFn &&appendFn) {
42 opt, argName, optionStr, [&](StringRef valueStr) {
43 typename ElementParser::parser_data_type value = {};
44 if (elementParser.parse(opt, argName, valueStr, value))
45 return failure();
46 appendFn(value);
47 return success();
48 });
49 }
50
51
52 template
54 decltype(std::declval<raw_ostream &>() << std::declval());
55 template
57
58
59 template
61 os << (value ? StringRef("true") : StringRef("false"));
62 }
63 template
64 static void printOptionValue(raw_ostream &os, const std::string &str) {
65
66 const size_t spaceIndex = str.find_first_of(' ');
67 const size_t escapeIndex =
68 std::min({str.find_first_of('{'), str.find_first_of('\''),
69 str.find_first_of('"')});
70 const bool requiresEscape = spaceIndex < escapeIndex;
71 if (requiresEscape)
72 os << "{";
73 os << str;
74 if (requiresEscape)
75 os << "}";
76 }
77 template <typename ParserT, typename DataT>
80 os << value;
81 else
82
83
85 }
86 }
87
88
90 private:
91
92
93 class OptionBase {
94 public:
95 virtual ~OptionBase() = default;
96
97
98 virtual void anchor();
99
100
101 virtual void print(raw_ostream &os) = 0;
102
103
104 StringRef getArgStr() const { return getOption()->ArgStr; }
105
106
107 bool hasValue() const { return optHasValue; }
108
109 protected:
110
111 virtual const llvm:🆑:Option *getOption() const = 0;
112
113
114 virtual void copyValueFrom(const OptionBase &other) = 0;
115
116
117 bool optHasValue = false;
118
119
121 };
122
123
124
125
126 template
127 struct GenericOptionParser : public llvm:🆑:parser {
129
130
131 std::optional findArgStrForValue(const DataType &value) {
132 for (auto &it : this->Values)
133 if (it.V.compare(value))
134 return it.Name;
135 return std::nullopt;
136 }
137 };
138
139
140
141
142 template
145
146
147 bool parse(llvm:🆑:Option &, StringRef, StringRef arg,
148 PassOptionsT &value) {
149 return failed(value.parseFromString(arg));
150 }
151
152
153 static void print(llvm::raw_ostream &os, const PassOptionsT &value) {
154 value.print(os);
155 }
156 };
157
158
159 template
160 static void printValue(raw_ostream &os, GenericOptionParser &parser,
161 const DataT &value) {
162 if (std::optional argStr = parser.findArgStrForValue(value))
163 os << *argStr;
164 else
165 llvm_unreachable("unknown data value for option");
166 }
167 template <typename DataT, typename ParserT>
168 static void printValue(raw_ostream &os, ParserT &parser, const DataT &value) {
169 detail::pass_options::printOptionValue(os, value);
170 }
171
172 public:
173
174
175 template
177
178
179 std::is_base_of_v<PassOptions, DataType>, PassOptionsParser,
180
181
182
183
184 std::conditional_t<std::is_base_of<llvm:🆑:generic_parser_base,
186 GenericOptionParser,
188
189
190
191 template <typename DataType, typename OptionParser = OptionParser>
193 : public llvm:🆑:opt<DataType, false, OptionParser>,
194 public OptionBase {
195 public:
196 template <typename... Args>
198 : llvm:🆑:opt<DataType, false, OptionParser>(
199 arg, llvm:🆑:sub(parent), std::forward(args)...) {
200 assert(!this->isPositional() && !this->isSink() &&
201 "sink and positional options are not supported");
202 parent.options.push_back(this);
203
204
205 this->setCallback([this](const auto &) { this->optHasValue = true; });
206 }
208 using llvm:🆑:opt<DataType, false,
211 *this = other.getValue();
212 return *this;
213 }
214
215 private:
216
217 const llvm:🆑:Option *getOption() const final { return this; }
218
219
220 void print(raw_ostream &os) final {
221 os << this->ArgStr << '=';
222 printValue(os, this->getParser(), this->getValue());
223 }
224
225
226 void copyValueFrom(const OptionBase &other) final {
227 this->setValue(static_cast<const Option<DataType, OptionParser> &>(other)
228 .getValue());
229 optHasValue = other.optHasValue;
230 }
231 };
232
233
234
235
236
237
238 template <typename DataType, typename OptionParser = OptionParser>
240 : public llvm:🆑:list<DataType, bool, OptionParser>,
241 public OptionBase {
242 public:
243 template <typename... Args>
245 : llvm:🆑:list<DataType, bool, OptionParser>(
246 arg, llvm:🆑:sub(parent), std::forward(args)...),
247 elementParser(*this) {
248 assert(!this->isPositional() && !this->isSink() &&
249 "sink and positional options are not supported");
250 assert(!(this->getMiscFlags() & llvm:🆑:MiscFlags::CommaSeparated) &&
251 "ListOption is implicitly comma separated, specifying "
252 "CommaSeparated is extraneous");
253
254
255 if (!this->isDefaultAssigned())
256 this->setInitialValues({});
257
258 parent.options.push_back(this);
259 elementParser.initialize();
260 }
265 this->optHasValue = other.optHasValue;
266 return *this;
267 }
268
270 StringRef arg) override {
271 if (this->isDefaultAssigned()) {
272 this->clear();
273 this->overwriteDefault();
274 }
275 this->optHasValue = true;
277 *this, argName, arg, elementParser,
278 [&](const DataType &value) { this->addValue(value); }));
279 }
280
281
283 ((std::vector &)*this).assign(values.begin(), values.end());
284 optHasValue = true;
285 return *this;
286 }
287
288
290 return static_cast<std::vector &>(*this);
291 }
293 return static_cast<const std::vector &>(*this);
294 }
295
296 private:
297
298 const llvm:🆑:Option *getOption() const final { return this; }
299
300
301
302
303
304 void print(raw_ostream &os) final {
305
306 if (this->isDefaultAssigned() &&
307 this->getDefault().size() == (**this).size()) {
308 unsigned i = 0;
309 for (unsigned e = (**this).size(); i < e; i++) {
310 if (!this->getDefault()[i].compare((**this)[i]))
311 break;
312 }
313 if (i == (**this).size())
314 return;
315 }
316
317 os << this->ArgStr << "={";
318 auto printElementFn = [&](const DataType &value) {
319 printValue(os, this->getParser(), value);
320 };
321 llvm::interleave(*this, os, printElementFn, ",");
322 os << "}";
323 }
324
325
326 void copyValueFrom(const OptionBase &other) final {
327 *this = static_cast<const ListOption<DataType, OptionParser> &>(other);
328 }
329
330
332 };
333
335
338
339
340
342
343
344
345
347 raw_ostream &errorStream = llvm::errs());
348
349
350
351 void print(raw_ostream &os) const;
352
353
354
355 void printHelp(size_t indent, size_t descIndent) const;
356
357
359
360 private:
361
362 std::vector<OptionBase *> options;
363 };
364 }
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379 template
381 public:
382
383
385 auto result = std::make_unique();
386 if (failed(result->parseFromString(options)))
387 return nullptr;
388 return result;
389 }
390 };
391
392
393
395 };
396 }
397
398
399
400
401
402 namespace llvm {
403 namespace cl {
404
405
406
407
408 namespace detail {
409 template <typename VectorT, typename ElementT>
411 public:
412 VectorParserBase(Option &opt) : basic_parser_impl(opt), elementParser(opt) {}
413
415
416 bool parse(Option &opt, StringRef argName, StringRef arg,
418 if (!arg.consume_front("[") || !arg.consume_back("]")) {
419 return opt.error("expected vector option to be wrapped with '[]'",
420 argName);
421 }
422
424 opt, argName, arg, elementParser,
425 [&](const ElementT &value) { vector.push_back(value); }));
426 }
427
428 static void print(raw_ostream &os, const VectorT &vector) {
429 llvm::interleave(
430 vector, os,
431 [&](const ElementT &value) {
434 },
435 ",");
436 }
437
439
440 outs() << " --" << opt.ArgStr;
441 outs() << "=<vector<" << elementParser.getValueName() << ">>";
442 Option::printHelpStr(opt.HelpStr, globalWidth, getOptionWidth(opt));
443 }
444
446
447 StringRef vectorExt("vector<>");
448 return elementParser.getOptionWidth(opt) + vectorExt.size();
449 }
450
451 private:
453 };
454 }
455
456 template
459 public:
460 parser(Option &opt) : detail::VectorParserBase<std::vector, T>(opt) {}
461 };
462 template <typename T, unsigned N>
465 public:
467 };
468
469
470
471
472
473 template <>
476
482
483
484 bool hasValue() const { return value.get(); }
485
486
488 assert(hasValue() && "invalid option value");
489 return *value;
490 }
491
492
495
496
499 const auto &rhsOV =
501 if (!rhsOV.hasValue())
502 return false;
503 return compare(rhsOV.getValue());
504 }
505
506 private:
507 void anchor() override;
508
509
510
511 std::unique_ptrmlir::OpPassManager value;
512 };
513
514
515
516
517
519
520 template <>
522 public:
523
524
525 struct ParsedPassManager {
530 assert(value && "parsed value was invalid");
531 return *value;
532 }
533
534 std::unique_ptrmlir::OpPassManager value;
535 };
538
540
541 bool parse(Option &, StringRef, StringRef arg, ParsedPassManager &value);
542
543
545
546
547 StringRef getValueName() const override { return "pass-manager"; }
548
550 const OptVal &defaultValue, size_t globalWidth) const;
551
552
554 };
555
556 }
557 }
558
559 #endif
static Value min(ImplicitLocOpBuilder &builder, Value value, Value bound)
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
size_t getOptionWidth(const Option &opt) const
VectorParserBase(Option &opt)
bool parse(Option &opt, StringRef argName, StringRef arg, parser_data_type &vector)
void printOptionInfo(const Option &opt, size_t globalWidth) const
static void print(raw_ostream &os, const VectorT &vector)
static void print(raw_ostream &os, const mlir::OpPassManager &value)
Print an instance of the underling option value to the given stream.
StringRef getValueName() const override
void printOptionDiff(const Option &opt, mlir::OpPassManager &pm, const OptVal &defaultValue, size_t globalWidth) const
bool parse(Option &, StringRef, StringRef arg, ParsedPassManager &value)
ParsedPassManager parser_data_type
This class represents a pass manager that runs passes on either a specific operation type,...
Subclasses of PassPipelineOptions provide a set of options that can be used to initialize a pass pipe...
static std::unique_ptr< T > createFromString(StringRef options)
Factory that parses the provided options and returns a unique_ptr to the struct.
This class represents a specific pass option that contains a list of values of the provided data type...
ListOption< DataType, OptionParser > & operator=(ArrayRef< DataType > values)
Allow assigning from an ArrayRef.
ListOption(PassOptions &parent, StringRef arg, Args &&...args)
ListOption< DataType, OptionParser > & operator=(const ListOption< DataType, OptionParser > &other)
MutableArrayRef< DataType > operator*()
Allow accessing the data held by this option.
ArrayRef< DataType > operator*() const
bool handleOccurrence(unsigned pos, StringRef argName, StringRef arg) override
~ListOption() override=default
This class represents a specific pass option, with a provided data type.
Option & operator=(const Option &other)
~Option() override=default
Option(PassOptions &parent, StringRef arg, Args &&...args)
Base container class and manager for all pass options.
size_t getOptionWidth() const
Return the maximum width required when printing the help string.
void printHelp(size_t indent, size_t descIndent) const
Print the help string for the options held by this struct.
PassOptions(PassOptions &&)=delete
LogicalResult parseFromString(StringRef options, raw_ostream &errorStream=llvm::errs())
Parse options out as key=value pairs that can then be handed off to the llvm::cl command line passing...
void print(raw_ostream &os) const
Print the options held by this struct in a form that can be parsed via 'parseFromString'.
void copyOptionValuesFrom(const PassOptions &other)
Copy the option values from 'other' into 'this', where 'other' has the same options as 'this'.
PassOptions(const PassOptions &)=delete
Delete the copy constructor to avoid copying the internal options map.
std::conditional_t< std::is_base_of_v< PassOptions, DataType >, PassOptionsParser< DataType >, std::conditional_t< std::is_base_of< llvm:🆑:generic_parser_base, llvm:🆑:parser< DataType > >::value, GenericOptionParser< DataType >, llvm:🆑:parser< DataType > >> OptionParser
The specific parser to use.
The OpAsmOpInterface, see OpAsmInterface.td for more details.
static void printOptionValue(raw_ostream &os, const bool &value)
Utility methods for printing option values.
LogicalResult parseCommaSeparatedList(llvm:🆑:Option &opt, StringRef argName, StringRef optionStr, function_ref< LogicalResult(StringRef)> elementParseFn)
Parse a string containing a list of comma-delimited elements, invoking the given parser for each sub-...
decltype(std::declval< raw_ostream & >()<< std::declval< T >()) has_stream_operator_trait
Trait used to detect if a type has a operator<< method.
llvm::is_detected< has_stream_operator_trait, T > has_stream_operator
int compare(const Fraction &x, const Fraction &y)
Three-way comparison between two fractions.
QueryRef parse(llvm::StringRef line, const QuerySession &qs)
Include the generated interface declarations.
mlir::OpPassManager & getValue() const
Returns the current value of the option.
void setValue(const mlir::OpPassManager &newValue)
Set the value of the option.
OptionValue(const OptionValue< mlir::OpPassManager > &rhs)
bool compare(const mlir::OpPassManager &rhs) const
Compare the option with the provided value.
bool compare(const GenericOptionValue &rhs) const override
OptionValue< mlir::OpPassManager > & operator=(const mlir::OpPassManager &rhs)
OptionValue(const mlir::OpPassManager &value)
void setValue(StringRef pipelineStr)
bool hasValue() const
Returns if the current option has a value.
ParsedPassManager(ParsedPassManager &&)
std::unique_ptr< mlir::OpPassManager > value
A default empty option struct to be used for passes that do not need to take any options.