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.