MLIR  20.0.0git
MlirOptMain.cpp
Go to the documentation of this file.
1 //===- MlirOptMain.cpp - MLIR Optimizer Driver ----------------------------===//
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 // This is a utility that runs an optimization pass and prints the result back
10 // out. It is designed to support unit testing.
11 //
12 //===----------------------------------------------------------------------===//
13 
17 #include "mlir/Debug/Counter.h"
23 #include "mlir/IR/AsmState.h"
24 #include "mlir/IR/Attributes.h"
25 #include "mlir/IR/BuiltinOps.h"
26 #include "mlir/IR/Diagnostics.h"
27 #include "mlir/IR/Dialect.h"
28 #include "mlir/IR/Location.h"
29 #include "mlir/IR/MLIRContext.h"
30 #include "mlir/Parser/Parser.h"
31 #include "mlir/Pass/Pass.h"
32 #include "mlir/Pass/PassManager.h"
33 #include "mlir/Pass/PassRegistry.h"
35 #include "mlir/Support/Timing.h"
40 #include "llvm/ADT/StringRef.h"
41 #include "llvm/Support/CommandLine.h"
42 #include "llvm/Support/FileUtilities.h"
43 #include "llvm/Support/InitLLVM.h"
44 #include "llvm/Support/ManagedStatic.h"
45 #include "llvm/Support/Process.h"
46 #include "llvm/Support/Regex.h"
47 #include "llvm/Support/SourceMgr.h"
48 #include "llvm/Support/StringSaver.h"
49 #include "llvm/Support/ThreadPool.h"
50 #include "llvm/Support/ToolOutputFile.h"
51 
52 using namespace mlir;
53 using namespace llvm;
54 
55 namespace {
56 class BytecodeVersionParser : public cl::parser<std::optional<int64_t>> {
57 public:
58  BytecodeVersionParser(cl::Option &o)
59  : cl::parser<std::optional<int64_t>>(o) {}
60 
61  bool parse(cl::Option &o, StringRef /*argName*/, StringRef arg,
62  std::optional<int64_t> &v) {
63  long long w;
64  if (getAsSignedInteger(arg, 10, w))
65  return o.error("Invalid argument '" + arg +
66  "', only integer is supported.");
67  v = w;
68  return false;
69  }
70 };
71 
72 /// This class is intended to manage the handling of command line options for
73 /// creating a *-opt config. This is a singleton.
74 struct MlirOptMainConfigCLOptions : public MlirOptMainConfig {
75  MlirOptMainConfigCLOptions() {
76  // These options are static but all uses ExternalStorage to initialize the
77  // members of the parent class. This is unusual but since this class is a
78  // singleton it basically attaches command line option to the singleton
79  // members.
80 
81  static cl::opt<bool, /*ExternalStorage=*/true> allowUnregisteredDialects(
82  "allow-unregistered-dialect",
83  cl::desc("Allow operation with no registered dialects"),
84  cl::location(allowUnregisteredDialectsFlag), cl::init(false));
85 
86  static cl::opt<bool, /*ExternalStorage=*/true> dumpPassPipeline(
87  "dump-pass-pipeline", cl::desc("Print the pipeline that will be run"),
88  cl::location(dumpPassPipelineFlag), cl::init(false));
89 
90  static cl::opt<bool, /*ExternalStorage=*/true> emitBytecode(
91  "emit-bytecode", cl::desc("Emit bytecode when generating output"),
92  cl::location(emitBytecodeFlag), cl::init(false));
93 
94  static cl::opt<bool, /*ExternalStorage=*/true> elideResourcesFromBytecode(
95  "elide-resource-data-from-bytecode",
96  cl::desc("Elide resources when generating bytecode"),
97  cl::location(elideResourceDataFromBytecodeFlag), cl::init(false));
98 
99  static cl::opt<std::optional<int64_t>, /*ExternalStorage=*/true,
100  BytecodeVersionParser>
101  bytecodeVersion(
102  "emit-bytecode-version",
103  cl::desc("Use specified bytecode when generating output"),
104  cl::location(emitBytecodeVersion), cl::init(std::nullopt));
105 
106  static cl::opt<std::string, /*ExternalStorage=*/true> irdlFile(
107  "irdl-file",
108  cl::desc("IRDL file to register before processing the input"),
109  cl::location(irdlFileFlag), cl::init(""), cl::value_desc("filename"));
110 
111  static cl::opt<bool, /*ExternalStorage=*/true> enableDebuggerHook(
112  "mlir-enable-debugger-hook",
113  cl::desc("Enable Debugger hook for debugging MLIR Actions"),
114  cl::location(enableDebuggerActionHookFlag), cl::init(false));
115 
116  static cl::opt<bool, /*ExternalStorage=*/true> explicitModule(
117  "no-implicit-module",
118  cl::desc("Disable implicit addition of a top-level module op during "
119  "parsing"),
120  cl::location(useExplicitModuleFlag), cl::init(false));
121 
122  static cl::opt<bool, /*ExternalStorage=*/true> listPasses(
123  "list-passes", cl::desc("Print the list of registered passes and exit"),
124  cl::location(listPassesFlag), cl::init(false));
125 
126  static cl::opt<bool, /*ExternalStorage=*/true> runReproducer(
127  "run-reproducer", cl::desc("Run the pipeline stored in the reproducer"),
128  cl::location(runReproducerFlag), cl::init(false));
129 
130  static cl::opt<bool, /*ExternalStorage=*/true> showDialects(
131  "show-dialects",
132  cl::desc("Print the list of registered dialects and exit"),
133  cl::location(showDialectsFlag), cl::init(false));
134 
135  static cl::opt<std::string, /*ExternalStorage=*/true> splitInputFile{
136  "split-input-file", llvm::cl::ValueOptional,
137  cl::callback([&](const std::string &str) {
138  // Implicit value: use default marker if flag was used without value.
139  if (str.empty())
140  splitInputFile.setValue(kDefaultSplitMarker);
141  }),
142  cl::desc("Split the input file into chunks using the given or "
143  "default marker and process each chunk independently"),
144  cl::location(splitInputFileFlag), cl::init("")};
145 
146  static cl::opt<std::string, /*ExternalStorage=*/true> outputSplitMarker(
147  "output-split-marker",
148  cl::desc("Split marker to use for merging the ouput"),
149  cl::location(outputSplitMarkerFlag), cl::init(kDefaultSplitMarker));
150 
151  static cl::opt<bool, /*ExternalStorage=*/true> verifyDiagnostics(
152  "verify-diagnostics",
153  cl::desc("Check that emitted diagnostics match "
154  "expected-* lines on the corresponding line"),
155  cl::location(verifyDiagnosticsFlag), cl::init(false));
156 
157  static cl::opt<bool, /*ExternalStorage=*/true> verifyPasses(
158  "verify-each",
159  cl::desc("Run the verifier after each transformation pass"),
160  cl::location(verifyPassesFlag), cl::init(true));
161 
162  static cl::opt<bool, /*ExternalStorage=*/true> disableVerifyOnParsing(
163  "mlir-very-unsafe-disable-verifier-on-parsing",
164  cl::desc("Disable the verifier on parsing (very unsafe)"),
165  cl::location(disableVerifierOnParsingFlag), cl::init(false));
166 
167  static cl::opt<bool, /*ExternalStorage=*/true> verifyRoundtrip(
168  "verify-roundtrip",
169  cl::desc("Round-trip the IR after parsing and ensure it succeeds"),
170  cl::location(verifyRoundtripFlag), cl::init(false));
171 
172  static cl::list<std::string> passPlugins(
173  "load-pass-plugin", cl::desc("Load passes from plugin library"));
174 
175  static cl::opt<std::string, /*ExternalStorage=*/true>
176  generateReproducerFile(
177  "mlir-generate-reproducer",
178  llvm::cl::desc(
179  "Generate an mlir reproducer at the provided filename"
180  " (no crash required)"),
181  cl::location(generateReproducerFileFlag), cl::init(""),
182  cl::value_desc("filename"));
183 
184  /// Set the callback to load a pass plugin.
185  passPlugins.setCallback([&](const std::string &pluginPath) {
186  auto plugin = PassPlugin::load(pluginPath);
187  if (!plugin) {
188  errs() << "Failed to load passes from '" << pluginPath
189  << "'. Request ignored.\n";
190  return;
191  }
192  plugin.get().registerPassRegistryCallbacks();
193  });
194 
195  static cl::list<std::string> dialectPlugins(
196  "load-dialect-plugin", cl::desc("Load dialects from plugin library"));
197  this->dialectPlugins = std::addressof(dialectPlugins);
198 
199  static PassPipelineCLParser passPipeline("", "Compiler passes to run", "p");
200  setPassPipelineParser(passPipeline);
201  }
202 
203  /// Set the callback to load a dialect plugin.
204  void setDialectPluginsCallback(DialectRegistry &registry);
205 
206  /// Pointer to static dialectPlugins variable in constructor, needed by
207  /// setDialectPluginsCallback(DialectRegistry&).
208  cl::list<std::string> *dialectPlugins = nullptr;
209 };
210 } // namespace
211 
212 ManagedStatic<MlirOptMainConfigCLOptions> clOptionsConfig;
213 
215  clOptionsConfig->setDialectPluginsCallback(registry);
217 }
218 
221  return *clOptionsConfig;
222 }
223 
225  const PassPipelineCLParser &passPipeline) {
226  passPipelineCallback = [&](PassManager &pm) {
227  auto errorHandler = [&](const Twine &msg) {
228  emitError(UnknownLoc::get(pm.getContext())) << msg;
229  return failure();
230  };
231  if (failed(passPipeline.addToPipeline(pm, errorHandler)))
232  return failure();
233  if (this->shouldDumpPassPipeline()) {
234 
235  pm.dump();
236  llvm::errs() << "\n";
237  }
238  return success();
239  };
240  return *this;
241 }
242 
243 void MlirOptMainConfigCLOptions::setDialectPluginsCallback(
244  DialectRegistry &registry) {
245  dialectPlugins->setCallback([&](const std::string &pluginPath) {
246  auto plugin = DialectPlugin::load(pluginPath);
247  if (!plugin) {
248  errs() << "Failed to load dialect plugin from '" << pluginPath
249  << "'. Request ignored.\n";
250  return;
251  };
252  plugin.get().registerDialectRegistryCallbacks(registry);
253  });
254 }
255 
256 LogicalResult loadIRDLDialects(StringRef irdlFile, MLIRContext &ctx) {
257  DialectRegistry registry;
258  registry.insert<irdl::IRDLDialect>();
259  ctx.appendDialectRegistry(registry);
260 
261  // Set up the input file.
262  std::string errorMessage;
263  std::unique_ptr<MemoryBuffer> file = openInputFile(irdlFile, &errorMessage);
264  if (!file) {
265  emitError(UnknownLoc::get(&ctx)) << errorMessage;
266  return failure();
267  }
268 
269  // Give the buffer to the source manager.
270  // This will be picked up by the parser.
271  SourceMgr sourceMgr;
272  sourceMgr.AddNewSourceBuffer(std::move(file), SMLoc());
273 
274  SourceMgrDiagnosticHandler sourceMgrHandler(sourceMgr, &ctx);
275 
276  // Parse the input file.
277  OwningOpRef<ModuleOp> module(parseSourceFile<ModuleOp>(sourceMgr, &ctx));
278  if (!module)
279  return failure();
280 
281  // Load IRDL dialects.
282  return irdl::loadDialects(module.get());
283 }
284 
285 // Return success if the module can correctly round-trip. This intended to test
286 // that the custom printers/parsers are complete.
287 static LogicalResult doVerifyRoundTrip(Operation *op,
288  const MlirOptMainConfig &config,
289  bool useBytecode) {
290  // We use a new context to avoid resource handle renaming issue in the diff.
291  MLIRContext roundtripContext;
292  OwningOpRef<Operation *> roundtripModule;
293  roundtripContext.appendDialectRegistry(
294  op->getContext()->getDialectRegistry());
296  roundtripContext.allowUnregisteredDialects();
297  StringRef irdlFile = config.getIrdlFile();
298  if (!irdlFile.empty() && failed(loadIRDLDialects(irdlFile, roundtripContext)))
299  return failure();
300 
301  std::string testType = (useBytecode) ? "bytecode" : "textual";
302  // Print a first time with custom format (or bytecode) and parse it back to
303  // the roundtripModule.
304  {
305  std::string buffer;
306  llvm::raw_string_ostream ostream(buffer);
307  if (useBytecode) {
308  if (failed(writeBytecodeToFile(op, ostream))) {
309  op->emitOpError()
310  << "failed to write bytecode, cannot verify round-trip.\n";
311  return failure();
312  }
313  } else {
314  op->print(ostream,
315  OpPrintingFlags().printGenericOpForm().enableDebugInfo());
316  }
317  FallbackAsmResourceMap fallbackResourceMap;
318  ParserConfig parseConfig(&roundtripContext, config.shouldVerifyOnParsing(),
319  &fallbackResourceMap);
320  roundtripModule = parseSourceString<Operation *>(buffer, parseConfig);
321  if (!roundtripModule) {
322  op->emitOpError() << "failed to parse " << testType
323  << " content back, cannot verify round-trip.\n";
324  return failure();
325  }
326  }
327 
328  // Print in the generic form for the reference module and the round-tripped
329  // one and compare the outputs.
330  std::string reference, roundtrip;
331  {
332  llvm::raw_string_ostream ostreamref(reference);
333  op->print(ostreamref,
334  OpPrintingFlags().printGenericOpForm().enableDebugInfo());
335  llvm::raw_string_ostream ostreamrndtrip(roundtrip);
336  roundtripModule.get()->print(
337  ostreamrndtrip,
338  OpPrintingFlags().printGenericOpForm().enableDebugInfo());
339  }
340  if (reference != roundtrip) {
341  // TODO implement a diff.
342  return op->emitOpError()
343  << testType
344  << " roundTrip testing roundtripped module differs "
345  "from reference:\n<<<<<<Reference\n"
346  << reference << "\n=====\n"
347  << roundtrip << "\n>>>>>roundtripped\n";
348  }
349 
350  return success();
351 }
352 
353 static LogicalResult doVerifyRoundTrip(Operation *op,
354  const MlirOptMainConfig &config) {
355  auto txtStatus = doVerifyRoundTrip(op, config, /*useBytecode=*/false);
356  auto bcStatus = doVerifyRoundTrip(op, config, /*useBytecode=*/true);
357  return success(succeeded(txtStatus) && succeeded(bcStatus));
358 }
359 
360 /// Perform the actions on the input file indicated by the command line flags
361 /// within the specified context.
362 ///
363 /// This typically parses the main source file, runs zero or more optimization
364 /// passes, then prints the output.
365 ///
366 static LogicalResult
367 performActions(raw_ostream &os,
368  const std::shared_ptr<llvm::SourceMgr> &sourceMgr,
369  MLIRContext *context, const MlirOptMainConfig &config) {
372  TimingScope timing = tm.getRootScope();
373 
374  // Disable multi-threading when parsing the input file. This removes the
375  // unnecessary/costly context synchronization when parsing.
376  bool wasThreadingEnabled = context->isMultithreadingEnabled();
377  context->disableMultithreading();
378 
379  // Prepare the parser config, and attach any useful/necessary resource
380  // handlers. Unhandled external resources are treated as passthrough, i.e.
381  // they are not processed and will be emitted directly to the output
382  // untouched.
383  PassReproducerOptions reproOptions;
384  FallbackAsmResourceMap fallbackResourceMap;
385  ParserConfig parseConfig(context, config.shouldVerifyOnParsing(),
386  &fallbackResourceMap);
387  if (config.shouldRunReproducer())
388  reproOptions.attachResourceParser(parseConfig);
389 
390  // Parse the input file and reset the context threading state.
391  TimingScope parserTiming = timing.nest("Parser");
393  sourceMgr, parseConfig, !config.shouldUseExplicitModule());
394  parserTiming.stop();
395  if (!op)
396  return failure();
397 
398  // Perform round-trip verification if requested
399  if (config.shouldVerifyRoundtrip() &&
400  failed(doVerifyRoundTrip(op.get(), config)))
401  return failure();
402 
403  context->enableMultithreading(wasThreadingEnabled);
404 
405  // Prepare the pass manager, applying command-line and reproducer options.
406  PassManager pm(op.get()->getName(), PassManager::Nesting::Implicit);
407  pm.enableVerifier(config.shouldVerifyPasses());
408  if (failed(applyPassManagerCLOptions(pm)))
409  return failure();
410  pm.enableTiming(timing);
411  if (config.shouldRunReproducer() && failed(reproOptions.apply(pm)))
412  return failure();
413  if (failed(config.setupPassPipeline(pm)))
414  return failure();
415 
416  // Run the pipeline.
417  if (failed(pm.run(*op)))
418  return failure();
419 
420  // Generate reproducers if requested
421  if (!config.getReproducerFilename().empty()) {
422  StringRef anchorName = pm.getAnyOpAnchorName();
423  const auto &passes = pm.getPasses();
424  makeReproducer(anchorName, passes, op.get(),
425  config.getReproducerFilename());
426  }
427 
428  // Print the output.
429  TimingScope outputTiming = timing.nest("Output");
430  if (config.shouldEmitBytecode()) {
431  BytecodeWriterConfig writerConfig(fallbackResourceMap);
432  if (auto v = config.bytecodeVersionToEmit())
433  writerConfig.setDesiredBytecodeVersion(*v);
435  writerConfig.setElideResourceDataFlag();
436  return writeBytecodeToFile(op.get(), os, writerConfig);
437  }
438 
439  if (config.bytecodeVersionToEmit().has_value())
440  return emitError(UnknownLoc::get(pm.getContext()))
441  << "bytecode version while not emitting bytecode";
442  AsmState asmState(op.get(), OpPrintingFlags(), /*locationMap=*/nullptr,
443  &fallbackResourceMap);
444  op.get()->print(os, asmState);
445  os << '\n';
446  return success();
447 }
448 
449 /// Parses the memory buffer. If successfully, run a series of passes against
450 /// it and print the result.
451 static LogicalResult processBuffer(raw_ostream &os,
452  std::unique_ptr<MemoryBuffer> ownedBuffer,
453  const MlirOptMainConfig &config,
454  DialectRegistry &registry,
455  llvm::ThreadPoolInterface *threadPool) {
456  // Tell sourceMgr about this buffer, which is what the parser will pick up.
457  auto sourceMgr = std::make_shared<SourceMgr>();
458  sourceMgr->AddNewSourceBuffer(std::move(ownedBuffer), SMLoc());
459 
460  // Create a context just for the current buffer. Disable threading on creation
461  // since we'll inject the thread-pool separately.
463  if (threadPool)
464  context.setThreadPool(*threadPool);
465 
466  StringRef irdlFile = config.getIrdlFile();
467  if (!irdlFile.empty() && failed(loadIRDLDialects(irdlFile, context)))
468  return failure();
469 
470  // Parse the input file.
472  if (config.shouldVerifyDiagnostics())
473  context.printOpOnDiagnostic(false);
474 
475  tracing::InstallDebugHandler installDebugHandler(context,
476  config.getDebugConfig());
477 
478  // If we are in verify diagnostics mode then we have a lot of work to do,
479  // otherwise just perform the actions without worrying about it.
480  if (!config.shouldVerifyDiagnostics()) {
481  SourceMgrDiagnosticHandler sourceMgrHandler(*sourceMgr, &context);
482  return performActions(os, sourceMgr, &context, config);
483  }
484 
485  SourceMgrDiagnosticVerifierHandler sourceMgrHandler(*sourceMgr, &context);
486 
487  // Do any processing requested by command line flags. We don't care whether
488  // these actions succeed or fail, we only care what diagnostics they produce
489  // and whether they match our expectations.
490  (void)performActions(os, sourceMgr, &context, config);
491 
492  // Verify the diagnostic handler to make sure that each of the diagnostics
493  // matched.
494  return sourceMgrHandler.verify();
495 }
496 
497 std::pair<std::string, std::string>
498 mlir::registerAndParseCLIOptions(int argc, char **argv,
499  llvm::StringRef toolName,
500  DialectRegistry &registry) {
501  static cl::opt<std::string> inputFilename(
502  cl::Positional, cl::desc("<input file>"), cl::init("-"));
503 
504  static cl::opt<std::string> outputFilename("o", cl::desc("Output filename"),
505  cl::value_desc("filename"),
506  cl::init("-"));
507  // Register any command line options.
514 
515  // Build the list of dialects as a header for the --help message.
516  std::string helpHeader = (toolName + "\nAvailable Dialects: ").str();
517  {
518  llvm::raw_string_ostream os(helpHeader);
519  interleaveComma(registry.getDialectNames(), os,
520  [&](auto name) { os << name; });
521  }
522  // Parse pass names in main to ensure static initialization completed.
523  cl::ParseCommandLineOptions(argc, argv, helpHeader);
524  return std::make_pair(inputFilename.getValue(), outputFilename.getValue());
525 }
526 
527 static LogicalResult printRegisteredDialects(DialectRegistry &registry) {
528  llvm::outs() << "Available Dialects: ";
529  interleave(registry.getDialectNames(), llvm::outs(), ",");
530  llvm::outs() << "\n";
531  return success();
532 }
533 
534 static LogicalResult printRegisteredPassesAndReturn() {
536  return success();
537 }
538 
539 LogicalResult mlir::MlirOptMain(llvm::raw_ostream &outputStream,
540  std::unique_ptr<llvm::MemoryBuffer> buffer,
541  DialectRegistry &registry,
542  const MlirOptMainConfig &config) {
543  if (config.shouldShowDialects())
544  return printRegisteredDialects(registry);
545 
546  if (config.shouldListPasses())
548 
549  // The split-input-file mode is a very specific mode that slices the file
550  // up into small pieces and checks each independently.
551  // We use an explicit threadpool to avoid creating and joining/destroying
552  // threads for each of the split.
553  ThreadPoolInterface *threadPool = nullptr;
554 
555  // Create a temporary context for the sake of checking if
556  // --mlir-disable-threading was passed on the command line.
557  // We use the thread-pool this context is creating, and avoid
558  // creating any thread when disabled.
559  MLIRContext threadPoolCtx;
560  if (threadPoolCtx.isMultithreadingEnabled())
561  threadPool = &threadPoolCtx.getThreadPool();
562 
563  auto chunkFn = [&](std::unique_ptr<MemoryBuffer> chunkBuffer,
564  raw_ostream &os) {
565  return processBuffer(os, std::move(chunkBuffer), config, registry,
566  threadPool);
567  };
568  return splitAndProcessBuffer(std::move(buffer), chunkFn, outputStream,
569  config.inputSplitMarker(),
570  config.outputSplitMarker());
571 }
572 
573 LogicalResult mlir::MlirOptMain(int argc, char **argv,
574  llvm::StringRef inputFilename,
575  llvm::StringRef outputFilename,
576  DialectRegistry &registry) {
577 
578  InitLLVM y(argc, argv);
579 
581 
582  if (config.shouldShowDialects())
583  return printRegisteredDialects(registry);
584 
585  if (config.shouldListPasses())
587 
588  // When reading from stdin and the input is a tty, it is often a user mistake
589  // and the process "appears to be stuck". Print a message to let the user know
590  // about it!
591  if (inputFilename == "-" &&
592  sys::Process::FileDescriptorIsDisplayed(fileno(stdin)))
593  llvm::errs() << "(processing input from stdin now, hit ctrl-c/ctrl-d to "
594  "interrupt)\n";
595 
596  // Set up the input file.
597  std::string errorMessage;
598  auto file = openInputFile(inputFilename, &errorMessage);
599  if (!file) {
600  llvm::errs() << errorMessage << "\n";
601  return failure();
602  }
603 
604  auto output = openOutputFile(outputFilename, &errorMessage);
605  if (!output) {
606  llvm::errs() << errorMessage << "\n";
607  return failure();
608  }
609  if (failed(MlirOptMain(output->os(), std::move(file), registry, config)))
610  return failure();
611 
612  // Keep the output file if the invocation of MlirOptMain was successful.
613  output->keep();
614  return success();
615 }
616 
617 LogicalResult mlir::MlirOptMain(int argc, char **argv, llvm::StringRef toolName,
618  DialectRegistry &registry) {
619 
620  // Register and parse command line options.
621  std::string inputFilename, outputFilename;
622  std::tie(inputFilename, outputFilename) =
623  registerAndParseCLIOptions(argc, argv, toolName, registry);
624 
625  return MlirOptMain(argc, argv, inputFilename, outputFilename, registry);
626 }
static LogicalResult printRegisteredDialects(DialectRegistry &registry)
LogicalResult loadIRDLDialects(StringRef irdlFile, MLIRContext &ctx)
static LogicalResult doVerifyRoundTrip(Operation *op, const MlirOptMainConfig &config, bool useBytecode)
static LogicalResult printRegisteredPassesAndReturn()
ManagedStatic< MlirOptMainConfigCLOptions > clOptionsConfig
static LogicalResult processBuffer(raw_ostream &os, std::unique_ptr< MemoryBuffer > ownedBuffer, const MlirOptMainConfig &config, DialectRegistry &registry, llvm::ThreadPoolInterface *threadPool)
Parses the memory buffer.
static LogicalResult performActions(raw_ostream &os, const std::shared_ptr< llvm::SourceMgr > &sourceMgr, MLIRContext *context, const MlirOptMainConfig &config)
Perform the actions on the input file indicated by the command line flags within the specified contex...
This class provides management for the lifetime of the state used when printing the IR.
Definition: AsmState.h:540
This class contains the configuration used for the bytecode writer.
void setElideResourceDataFlag(bool shouldElideResourceData=true)
Set a boolean flag to skip emission of resources into the bytecode file.
void setDesiredBytecodeVersion(int64_t bytecodeVersion)
Set the desired bytecode version to emit.
Facilities for time measurement and report printing to an output stream.
Definition: Timing.h:388
static llvm::Expected< DialectPlugin > load(const std::string &filename)
Attempts to load a dialect plugin from a given file.
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
auto getDialectNames() const
Return the names of dialects known to this registry.
A fallback map containing external resources not explicitly handled by another parser/printer.
Definition: AsmState.h:419
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:60
void appendDialectRegistry(const DialectRegistry &registry)
Append the contents of the given dialect registry to the registry associated with this context.
void disableMultithreading(bool disable=true)
Set the flag specifying if multi-threading is disabled by the context.
void setThreadPool(llvm::ThreadPoolInterface &pool)
Set a new thread pool to be used in this context.
void enableMultithreading(bool enable=true)
Definition: MLIRContext.h:152
void printOpOnDiagnostic(bool enable)
Set the flag specifying if we should attach the operation to diagnostics emitted via Operation::emit.
const DialectRegistry & getDialectRegistry()
Return the dialect registry associated with this context.
llvm::ThreadPoolInterface & getThreadPool()
Return the thread pool used by this context.
bool isMultithreadingEnabled()
Return true if multi-threading is enabled by the context.
void allowUnregisteredDialects(bool allow=true)
Enables creating operations in unregistered dialects.
bool allowsUnregisteredDialects()
Return true if we allow to create operation for unregistered dialects.
Configuration options for the mlir-opt tool.
Definition: MlirOptMain.h:41
tracing::DebugConfig & getDebugConfig()
Definition: MlirOptMain.h:69
static MlirOptMainConfig createFromCLOptions()
Create a new config with the default set from the CL options.
bool shouldVerifyPasses() const
Definition: MlirOptMain.h:184
StringRef inputSplitMarker() const
Definition: MlirOptMain.h:153
bool shouldVerifyRoundtrip() const
Definition: MlirOptMain.h:198
std::optional< int64_t > bytecodeVersionToEmit() const
Definition: MlirOptMain.h:101
StringRef getReproducerFilename() const
Reproducer file generation (no crash required).
Definition: MlirOptMain.h:201
bool shouldShowDialects() const
Definition: MlirOptMain.h:144
MlirOptMainConfig & outputSplitMarker(std::string splitMarker=kDefaultSplitMarker)
Set whether to merge the output chunks into one file using the given marker.
Definition: MlirOptMain.h:158
bool shouldVerifyOnParsing() const
Definition: MlirOptMain.h:191
bool shouldElideResourceDataFromBytecode() const
Definition: MlirOptMain.h:85
bool shouldEmitBytecode() const
Definition: MlirOptMain.h:84
LogicalResult setupPassPipeline(PassManager &pm) const
Populate the passmanager, if any callback was set.
Definition: MlirOptMain.h:116
static void registerCLOptions(DialectRegistry &dialectRegistry)
Register the options as global LLVM command line options.
bool shouldAllowUnregisteredDialects() const
Definition: MlirOptMain.h:60
bool shouldUseExplicitModule() const
Definition: MlirOptMain.h:169
bool shouldRunReproducer() const
Return true if the reproducer should be run.
Definition: MlirOptMain.h:137
bool shouldVerifyDiagnostics() const
Definition: MlirOptMain.h:177
bool shouldListPasses() const
Definition: MlirOptMain.h:127
StringRef getIrdlFile() const
Definition: MlirOptMain.h:94
MlirOptMainConfig & setPassPipelineParser(const PassPipelineCLParser &parser)
Set the parser to use to populate the pass manager.
@ Implicit
Implicit nesting behavior.
iterator_range< pass_iterator > getPasses()
Definition: PassManager.h:80
static StringRef getAnyOpAnchorName()
Return the string name used to anchor op-agnostic pass managers that operate generically on any viabl...
Definition: PassManager.h:138
Set of flags used to control the behavior of the various IR print methods (e.g.
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
void print(raw_ostream &os, const OpPrintingFlags &flags=std::nullopt)
MLIRContext * getContext()
Return the context this operation is associated with.
Definition: Operation.h:216
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
Definition: Operation.cpp:671
OpTy get() const
Allow accessing the internal op.
Definition: OwningOpRef.h:51
This class represents a configuration for the MLIR assembly parser.
Definition: AsmState.h:467
The main pass manager and pipeline builder.
Definition: PassManager.h:231
MLIRContext * getContext() const
Return an instance of the context.
Definition: PassManager.h:256
LogicalResult run(Operation *op)
Run the passes within this manager on the provided operation.
Definition: Pass.cpp:847
void enableVerifier(bool enabled=true)
Runs the verifier after each individual pass.
Definition: Pass.cpp:844
void enableTiming(TimingScope &timingScope)
Add an instrumentation to time the execution of passes and the computation of analyses.
Definition: PassTiming.cpp:148
This class implements a command-line parser for MLIR passes.
Definition: PassRegistry.h:247
LogicalResult addToPipeline(OpPassManager &pm, function_ref< LogicalResult(const Twine &)> errorHandler) const
Adds the passes defined by this parser entry to the given pass manager.
static llvm::Expected< PassPlugin > load(const std::string &filename)
Attempts to load a pass plugin from a given file.
Definition: PassPlugin.cpp:16
This class is a utility diagnostic handler for use with llvm::SourceMgr.
Definition: Diagnostics.h:559
This class is a utility diagnostic handler for use with llvm::SourceMgr that verifies that emitted di...
Definition: Diagnostics.h:625
LogicalResult verify()
Returns the status of the handler and verifies that all expected diagnostics were emitted.
TimingScope getRootScope()
Get the root timer of this timing manager wrapped in a TimingScope for convenience.
Definition: Timing.cpp:74
An RAII-style wrapper around a timer that ensures the timer is properly started and stopped.
Definition: Timing.h:272
TimingScope nest(Args... args)
Create a nested timing scope.
Definition: Timing.h:311
void stop()
Manually stop the timer early.
Definition: Timing.h:300
static DebugConfig createFromCLOptions()
Create a new config with the default set from the CL options.
static void registerCLOptions()
Register the options as global LLVM command line options.
static void registerCLOptions()
Register the command line options for debug counters.
This is a RAII class that installs the debug handlers on the context based on the provided configurat...
The OpAsmOpInterface, see OpAsmInterface.td for more details.
Definition: CallGraph.h:229
llvm::LogicalResult loadDialects(ModuleOp op)
Load all the dialects defined in the module.
QueryRef parse(llvm::StringRef line, const QuerySession &qs)
Definition: Query.cpp:20
Include the generated interface declarations.
std::unique_ptr< llvm::MemoryBuffer > openInputFile(llvm::StringRef inputFilename, std::string *errorMessage=nullptr)
Open the file specified by its name for reading.
LogicalResult applyPassManagerCLOptions(PassManager &pm)
Apply any values provided to the pass manager options that were registered with 'registerPassManagerO...
const char *const kDefaultSplitMarker
void registerDefaultTimingManagerCLOptions()
Register a set of useful command-line options that can be used to configure a DefaultTimingManager.
Definition: Timing.cpp:614
void printRegisteredPasses()
Prints the passes that were previously registered and stored in passRegistry.
LogicalResult MlirOptMain(llvm::raw_ostream &outputStream, std::unique_ptr< llvm::MemoryBuffer > buffer, DialectRegistry &registry, const MlirOptMainConfig &config)
Perform the core processing behind mlir-opt.
std::unique_ptr< llvm::ToolOutputFile > openOutputFile(llvm::StringRef outputFilename, std::string *errorMessage=nullptr)
Open the file specified by its name for writing.
std::string makeReproducer(StringRef anchorName, const llvm::iterator_range< OpPassManager::pass_iterator > &passes, Operation *op, StringRef outputFile, bool disableThreads=false, bool verifyPasses=false)
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
void registerMLIRContextCLOptions()
Register a set of useful command-line options that can be used to configure various flags within the ...
Definition: MLIRContext.cpp:90
LogicalResult splitAndProcessBuffer(std::unique_ptr< llvm::MemoryBuffer > originalBuffer, ChunkBufferHandler processChunkBuffer, raw_ostream &os, llvm::StringRef inputSplitMarker=kDefaultSplitMarker, llvm::StringRef outputSplitMarker="")
Splits the specified buffer on a marker (// ----- by default), processes each chunk independently acc...
OwningOpRef< Operation * > parseSourceFileForTool(const std::shared_ptr< llvm::SourceMgr > &sourceMgr, const ParserConfig &config, bool insertImplicitModule)
This parses the file specified by the indicated SourceMgr.
void registerAsmPrinterCLOptions()
Register a set of useful command-line options that can be used to configure various flags within the ...
Definition: AsmPrinter.cpp:205
void registerPassManagerCLOptions()
Register a set of useful command-line options that can be used to configure a pass manager.
void applyDefaultTimingManagerCLOptions(DefaultTimingManager &tm)
Apply any values that were registered with 'registerDefaultTimingManagerOptions' to a DefaultTimingMa...
Definition: Timing.cpp:619
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
std::pair< std::string, std::string > registerAndParseCLIOptions(int argc, char **argv, llvm::StringRef toolName, DialectRegistry &registry)
Register and parse command line options.
LogicalResult writeBytecodeToFile(Operation *op, raw_ostream &os, const BytecodeWriterConfig &config={})
Write the bytecode for the given operation to the provided output stream.
void attachResourceParser(ParserConfig &config)
Attach an assembly resource parser to 'config' that collects the MLIR reproducer configuration into t...
LogicalResult apply(PassManager &pm) const
Apply the reproducer options to 'pm' and its context.